Code Snippets

Async Parallel

static Task ParallelForEachAsync<T> (IEnumerable<T> source,
                                           int degreeofParallelization,
                                           Func<T, Task> body)
{
    async Task AwaitPartition(IEnumerator<T> partition)
	{
        using (partition)
        {
            while (partition.MoveNext())
            {
                await body(partition.Current);
            }
        }
    }
  
    return Task.WhenAll(Partitioner
                        .Create(source)
                        .GetPartitions(degreeofParallelization)
                        .AsParallel()
                        .Select(AwaitPartition));
}

Usage:

var tasks = Enumerable.Range(0, 10000).Select(_ => new Func<Task>(() => Worker(results))).ToList();

await ParallelForEachAsync(tasks, 1000, async func =>
{
	await func();
});

AsyncHelper


public static class AsyncHelper
    {
        private static readonly TaskFactory _myTaskFactory = new TaskFactory(CancellationToken.None,
                                                                             TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);

        public static TResult RunSync<TResult>(Func<Task<TResult>> func)
        {
            var cultureUi = CultureInfo.CurrentUICulture;
            var culture = CultureInfo.CurrentCulture;
            return _myTaskFactory.StartNew(() =>
            {
                Thread.CurrentThread.CurrentCulture = culture;
                Thread.CurrentThread.CurrentUICulture = cultureUi;
                return func();
            }).Unwrap().GetAwaiter().GetResult();
        }

        public static void RunSync(Func<Task> func)
        {
            var cultureUi = CultureInfo.CurrentUICulture;
            var culture = CultureInfo.CurrentCulture;
            _myTaskFactory.StartNew(() =>
            {
                Thread.CurrentThread.CurrentCulture = culture;
                Thread.CurrentThread.CurrentUICulture = cultureUi;
                return func();
            }).Unwrap().GetAwaiter().GetResult();
        }
    }

https://github.com/aspnet/AspNetIdentity/blob/main/src/Microsoft.AspNet.Identity.Core/AsyncHelper.cs

Authentik NPM Redirect with Websocket support


# Increase buffer size for large headers
# This is needed only if you get 'upstream sent too big header while reading response
# header from upstream' error when trying to access an application protected by goauthentik
proxy_buffers 8 16k;
proxy_buffer_size 32k;

location / {
    # Put your proxy_pass to your application here
    proxy_pass          $forward_scheme://$server:$port;
    proxy_set_header Host $host;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection upgrade;
    proxy_set_header Accept-Encoding gzip;
  
    # authentik-specific config
    auth_request        /outpost.goauthentik.io/auth/nginx;
    error_page          401 = @goauthentik_proxy_signin;
    auth_request_set $auth_cookie $upstream_http_set_cookie;
    add_header Set-Cookie $auth_cookie;

    # translate headers from the outposts back to the actual upstream
    auth_request_set $authentik_username $upstream_http_x_authentik_username;
    auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
    auth_request_set $authentik_email $upstream_http_x_authentik_email;
    auth_request_set $authentik_name $upstream_http_x_authentik_name;
    auth_request_set $authentik_uid $upstream_http_x_authentik_uid;

    proxy_set_header X-authentik-username $authentik_username;
    proxy_set_header X-authentik-groups $authentik_groups;
    proxy_set_header X-authentik-email $authentik_email;
    proxy_set_header X-authentik-name $authentik_name;
    proxy_set_header X-authentik-uid $authentik_uid;
}

# all requests to /outpost.goauthentik.io must be accessible without authentication
location /outpost.goauthentik.io {
    proxy_pass          https://authentik-server-1:9443/outpost.goauthentik.io;
    # ensure the host of this vserver matches your external URL you've configured
    # in authentik
    proxy_set_header    Host $host;
    proxy_set_header    X-Original-URL $scheme://$http_host$request_uri;
    add_header          Set-Cookie $auth_cookie;
    auth_request_set    $auth_cookie $upstream_http_set_cookie;

    # required for POST requests to work
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
}

# Special location for when the /auth endpoint returns a 401,
# redirect to the /start URL which initiates SSO
location @goauthentik_proxy_signin {
    internal;
    add_header Set-Cookie $auth_cookie;
    return 302 /outpost.goauthentik.io/start?rd=$request_uri;
    # For domain level, use the below error_page to redirect to your authentik server with the full redirect path
    # return 302 https://auth.ultimatecloud.tk/outpost.goauthentik.io/start?rd=$scheme://$http_host$request_uri;
}

Batching with LINQ


static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int batchSize)
{
    return source.Select((item, inx) => new { item, inx })
    			 .GroupBy(x => x.inx / batchSize)
				 .Select(g => g.Select(x => x.item));
}

https://stackoverflow.com/questions/13731796/create-batches-in-linq

Build project with SourceGenerator on linux

Add Microsoft.Net.Compilers.Toolset package to the project that references the source generator.

Change file encoding with linux

To get current encoding:

file -i {filename}

To convert it:

iconv -f {sourceEncoding} -t {targetEncoding} {filename}

Example:

iconv -f ISO_8859-1 -t UTF-8 filename.txt

 

Docker Buildx Multi-Arch

sudo docker buildx create --use --name multi-arch-builder

Usage:

sudo docker buildx build --platform=linux/arm64 -t tag:latest -f ./DockerTest/Dockerfile --load --no-cache .

DockerFile:

#See https://aka.ms/customizecontainer to learn how to customize your debug container and how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS base
USER app
WORKDIR /app
EXPOSE 8080
EXPOSE 8081

FROM --platform=$BUILDPLATFORM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
ARG BUILDPLATFORM
ARG TARGETARCH
ARG BUILD_CONFIGURATION=Release
RUN echo "Target: $TARGETARCH"
RUN echo "Build: $BUILDPLATFORM"
WORKDIR /src
COPY ["DockerTest/DockerTest.csproj", "DockerTest/"]
RUN dotnet restore "./DockerTest/DockerTest.csproj" -a $TARGETARCH
COPY . .
WORKDIR "/src/DockerTest"
RUN dotnet build "./DockerTest.csproj" -c $BUILD_CONFIGURATION -o /app/build -a $TARGETARCH

FROM build AS publish
ARG TARGETARCH
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./DockerTest.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false -a $TARGETARCH

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "DockerTest.dll"]

https://stackoverflow.com/questions/70757791/build-linux-arm64-docker-image-on-linux-amd64-host

https://ruanbekker.medium.com/how-to-create-arm-based-container-images-with-buildx-fe917d186824

Handle Exceptions with Task.WhenAll()

var tasks = Enumerable.Range(0, 10).Select(async _ => await Task.Delay(1000));
var whenAll = Task.WhenAll(tasks);
try
{
  await whenAll;
}
catch {}
if (whenAll.Exception is AggregateException ex)
{
  //Handle Exception
}
  

https://www.youtube.com/watch?v=s_NrqRI7Gnc&t=321s

Left outer join


from leftTable in context.leftTable
join rightTable in context.rightTable on leftTable.FKRightTable equals rightTable.Id into rightTableJoin
from joinedRightTable in rightTableJoin.DefaultIfEmpty()
select new { LeftData = leftTable.data, RightData = joinedRightTable?.data }

List iteration using span


var list = new List<int>();
foreach(var item in CollectionsMarshal.AsSpan(list))
{
  
}

Only usable if the collection is not changed during iteration (read only)

Load Assembly Dynamically

In order to Copy NuGet dependecies to the output folder add this to classlibrary.csproj:

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

Set the Output directory with

<BaseOutputPath>$(SolutionDir)AppName\bin</BaseOutputPath>

To load Assembly the best approach is to use

Assembly module = Assembly.LoadFrom(filePath);

To check if type A can be assigned to a variable with type B:

B.IsAssignableFrom(A)

 

macOS Defaults

Auto-Resize Columns in column view

defaults write com.apple.finder _FXEnableColumnAutoSizing -bool YES && killall Finder

Scroll to Exposé app

defaults write com.apple.dock "scroll-to-open" -bool "true" && killall Dock

Make Dock icons of hidden applications translucent

defaults write com.apple.dock showhidden -bool true && killall Dock

https://raw.githubusercontent.com/mathiasbynens/dotfiles/refs/heads/main/.macos

https://macos-defaults.com

Mount host volumes in WSL2

Add the following to /etc/wsl.conf

[automount]
options = "metadata"

Optional<T>

See Attachments

RegEx in multiple files multi-line pattern

pcregrep -h -r --include=".*\.cs" -M "LogEvent\([\s\S]*?\)\;" .

Example: await LogEvent($"This is a test message that has embedded {property}");

pcregrep -h -r --include=".*\.cs" -o1 -M "LogEvent\(([\s\S]*?)\)\;" .