Laszlo

Hello, I am Laszlo

Software-Engineer, .NET developer

Contact Me

HTTP/3 with ASP.NET Core and browsers

Configure ASP.NET Core WebApi

In this post I explore how to test locally an ASP.NET Core WebApi with HTTP/3 in a local environment using a browser. In ASP.NET Core with .NET 10, HTTP/3 is already supported, but it is an opt-in feature.

To enable HTTP/3, add the following configuration to the application, either in the appsettings.json file

"Kestrel": {
  "EndpointDefaults": {
    "Protocols": "Http1AndHttp2AndHttp3"
  }
}

Find out more »


Know Your Data

There are many social posts, blog posts, and code suggestions online for .NET code snippets titled "Use X instead of Y" or "Why X is better than Y". These posts usually (but not always) include a basic performance comparison using BenchmarkDotNet to validate their catchy titles.

At first glance, these suggestions appear justified by the measurements. However, upon closer inspection, many important details are typically excluded:

  • What version of .NET (SDK and Runtime) was used?
  • What version of OS was used?
  • What is the underlying hardware architecture (ARM or x64)?
  • Does the hardware support vectorized operations?
  • What are the sizes of the vector registers?
  • What is the memory read latency?
  • What are the CPU cache sizes?
  • What branch prediction algorithm does the CPU use?
  • What are the input data types (structs, classes, primitives)?
  • What is the input data structure?
  • What is the size of the input data (bytes/array length)?
  • What is the data access pattern?
  • And many more factors

Since explaining all these factors is beyond this post's scope, I will focus on data access patterns and data sizes. For those interested in a deeper analysis, I recommend reading Pro .NET Benchmarking by Andrey Akinshin, which explains many common pitfalls.

Find out more »


Request Cancellation in ASP.NET Core with HTTP/2

ASP.NET Core allows to create endpoints that receive a cancellation token, such as below:

app.MapGet("/path", async (CancellationToken token) =>
{
});

In this post, I will explore how a server (such as Kestrel) may fire the token to be canceled.

Cooperative Cancellation

Find out more »


Distinct and HashSet

A common pattern in business-as-usual (BAU) applications is that a class in the business logic layer requests a set of entities by their integer IDs from a repository class. Here is one possible implementation of this pattern:

  1. A method in the business layer receives a list of integers as an argument (List<int>).
  2. It applies filtering and selection on these integers by creating a new enumerable.
  3. It extracts the unique values from the filtered and projected numbers.
  4. It passes the filtered, selected unique numbers to a query method in the repository class.
  5. This repository method processes the passed in integer enumerable:
    • If there aren't any numbers in the enumeration, it returns null (or empty results).
    • Otherwise, it copies the numbers into an SQL query and returns the query's result.

In this blog post, I will focus on two possible implementations to produce the unique set of integers:

  1. Using the Distinct LINQ extension method.
  2. Using the ToHashSet<T> method to materialize the result before passing it to the repository class.

Find out more »


Extension Members in C# 14

In this post, I explore C# 14's extension members feature and how it is compiled into IL code.

From Extension Methods to Extension Members

Previous versions of C# allowed developers to declare extension methods. The code snippets in this post are for demonstration purposes only and should not be used directly in production applications:

string value = "ThisIsPascalCased";
Console.WriteLine(value.ToCamel());

public static class MyExtensions
{
    public static string ToCamel(this string str) => str.Length switch
    {
        0 => string.Empty,
        1 => str.ToLowerInvariant(),
        _ => new([char.ToLower(str[0]), .. str[1..]])
    };
}

Find out more »