Constructing URLs

HttpClient type in .NET is one of the most dominant types to create network calls using HTTP protocol. One of the questions I face every time: how can I build the Uri that is then passed to HttpRequestMessage or HttpClient to identify the resource to be requested. The API surface of these types accepts strings and Uris, and Uris can be built from strings.

Many line of business (LOB) applications also need to present links/URI that point out from the current application to some external resource. The parts of these URIs typically get concatenated from a well-known host, port, some path that may vary based on the resource and a query string.

In this post I am going explore different ways of creating URIs, focusing on creating the path segments. While schemas, hosts, ports, or query strings are going to be part of the final URI built, I am going to handle them as well formed constants for the purpose of this blog post. I do this because most applications define the base URIs in the settings, including the schema, the host and the port, such as https://localhost:5000/. The path typically varies on the resource to be referenced. The query can also vary, but many RESTful APIs tend to choose path parameters and request bodies instead. However, the findings and concepts described in this post for the paths can generally applied for the other parts of the URI as well.

I am writing this blog post in the .NET 8 timeframe. This post uses the API surface of the preview versions of .NET 9.

Find out more


Kestrel HTTP/2 Internals

In the previous post I explored some of the inner workings of Kestrel. Kestrel is one of the servers built into ASP.NET Core.

First, I investigated how HTTP socket connections are dispatched to a request processor, such as the Http2Connection.

In a different post I looked into how HEADER frames work with HTTP/2 responses, and what are the main building blocks of writing headers to the response stream in Kestrel.

Lastly, I explored how HEADER and CONTINUATION frames are used in ASP.NET Core to serve response headers larger to the frame size.

Find out more


Switch Expression or Visitor pattern

A few months ago I looked into optimizing dictionary lookups using switch expressions.

In this post I investigate a seemingly similar problem, but with vastly different constraints, that eventually demand a vastly different solution.

Problem Definition

Given a set of polymorphic objects and a DTO. A method needs to iterate all the polymorphic objects and evaluate them against the DTO. Each polymorphic object evaluates a different (C#) property of the DTO. While there are a few designs to achieve this, in this case I seek for a design that does not introduce a coupling between the polymorphic objects and the DTO. I compare two possible solutions in this post.

Find out more


Range Indexer

With C# 12's collection expression feature, the range indexers has become also more powerful.

These two constructs along with the C#'s spreads feature allow to easily create new collections by slicing and concatenating existing ones. For example, given the following snippet:

int[] a = [1, 2];
int[] b = [3, 4, 5];
int[] c = [..a, ..b[..1]];

When executing the snippet, variable c will reference an integer array containing 1 2 and 3 values. While these operations are universal in many languages for a longer time, they are only introduced as new in C# 12.

Find out more


Large HTTP/2 Header Frames

In a previous post I explored how HTTP2 handles header frames in .NET 8. In this post I explore how it is planned to handle larger HTTP2 response header values.

Recap

  • RFC7540 describes the HTTP/2 protocol's related details.

  • In HTTP/2 a request-response pair is serialized in a stream.

  • A stream consists of message frames.

  • Frames have a type, frame header, a given size and corresponding data. Frames are associated with a given stream with the stream ID.

  • HTTP/2 requests start with HEADER frame. A header frame may be followed by CONTINUATION frames containing further headers.

  • The HTTP/2 request headers HPack encoded and split into HEADER and CONTINUATION frames.

  • In ASP.NET Core's Kestrel HPackHeaderWriter static class writes the headers.

    • HPackHeaderWriter iterates over the headers/trailers (except for the response status header which is written separately) using the Http2FrameWriter types.

  • Http2FrameWriter creates the buffer which it passes as a Span<byte> to the header writer. The default size of the buffer is 16K, but it can be updated via Kestrel's option by setting the Http2Limits's MaxFrameSize property. Clients can also influence the frame size by sending a value in the SETTING frame.

Planned changes

Find out more