tags

asp.net core

C# 9 records as strongly-typed ids - Part 3: JSON serialization

Created by Wireform from the Noun Project Using C# 9 records as strongly-typed ids
In the previous post in this series, we noticed that the strongly-typed id was serialized to JSON in an unexpected way: { "id": { "value": 1 }, "name": "Apple", "unitPrice": 0.8 } When you think about it, it’s not really unexpected: the strongly-typed id is a “complex” object, not a primitive type, so it makes sense that it’s serialized as an object. But it’s clearly not what we want… Let’s see how to fix that.

C# 9 records as strongly-typed ids - Part 2: ASP.NET Core route and query parameters

Created by Wireform from the Noun Project Using C# 9 records as strongly-typed ids
Last time, I explained how easy it is to use C# 9 record types as strongly-typed ids: public record ProductId(int Value); But unfortunately, we’re not quite done yet: there are a few issues to fix before our strongly-typed ids are really usable. For instance, ASP.NET Core doesn’t know how to handle them in route parameters or query string parameters. In this post, I’ll show how to address this issue. Model binding of route and query string parameters Let’s say we have an entity like this:

Inject a service into a System.Text.Json converter

Most JSON converters are fairly simple, and typically self-contained. But once in a while, you need to do something a little more complex in a converter, and you end up needing to call a service. However, there’s no built-in dependency injection in System.Text.Json converters… How can you access the service you need? There are basically two variants of this problem. One has a simple solution, the other is a bit of a hack…

ASP.NET Core 3, IIS and empty HTTP headers

HTTP headers are key/value pairs sent at the beginning of a request or response. According to the grammar in RFC 7230, a field could have an empty value. In practice, it probably doesn’t make much sense: semantically, a header with an empty value or the absence of that header are equivalent. However, some client or server implementations actually require that a given header is present, even if it’s empty. For instance, the validation tests for WOPI (an HTTP-based protocol used to integrate Office for the Web with an application) require that the X-WOPI-Lock header is included in the response in certain situations, even if it’s empty (even though the spec says it can be omitted).

Exposing a custom type as a JSON string in an ASP.NET Core API

Sometimes your API needs to expose a non-primitive type that has a “natural” string representation. For instance, a standard representation for a duration is the ISO 8601 format, where “1 month, 2 days, 3 hours and 4 minutes” can be represented as P1M2DT3H4M (note that this isn’t the same as a Timespan, which has no notion of calendar months and years). A duration could be represented in C# as a custom type, like the Duration structure in my Iso8601DurationHelper project.

Handling query string parameters with no value in ASP.NET Core

Query strings are typically made of a sequence of key-value pairs, like ?foo=hello&bar=world…. However, if you look at RFC 3986, you can see that query strings are very loosely specified. It mentions that query components are often used to carry identifying information in the form of “key=value” pairs But it’s just an observation, not a rule (RFCs usually have very specific wording for rules, with words like MUST, SHOULD, etc.

ASP.NET Core: when environments are not enough, use sub-environments!

Out of the box, ASP.NET Core has the concept of “environments”, which allows your app to use different settings based on which environment it’s running in. For instance, you can have Development/Staging/Production environments, each with its own settings file, and a common settings file shared by all environments: appsettings.json: global settings appsettings.Development.json: settings specific to the Development environment appsettings.Staging.json: settings specific to the Staging environment appsettings.Production.json: settings specific to the Production environment With the default configuration, environment-specific settings just override global settings, so you don’t have to specify unchanged settings in every environment if they’re already specified in the global settings file.

Scaling out ASP.NET Core SignalR using Azure Service Bus

ASP.NET Core SignalR is a super easy way to establish two-way communication between an ASP.NET Core app and its clients, using WebSockets, Server-Sent Events, or long polling, depending on the client’s capabilities. For instance, it can be used to send a notification to all connected clients. However, if you scale out your application to multiple server instances, it no longer works out of the box: only the clients connected to the instance that sent the notification will receive it.

Google+ shutdown: fixing Google authentication in ASP.NET Core

A few months ago, Google decided to shutdown Google+, due to multiple data leaks. More recently, they announced that the Google+ APIs will be shutdown on March 7, 2019, which is pretty soon! In fact, calls to these APIs might start to fail as soon as January 28, which is less than 3 weeks from now. You might think that it doesn’t affect you as a developer; but if you’re using Google authentication in an ASP.

Multitenant Azure AD issuer validation in ASP.NET Core

If you use Azure AD authentication and want to allow users from any tenant to connect to your ASP.NET Core application, you need to configure the Azure AD app as multi-tenant, and use a “wildcard” tenant id such as organizations or common in the authority URL: openIdConnectOptions.Authority = "https://login.microsoftonline.com/organizations/v2.0"; The problem when you do that is that with the default configuration, the token validation will fail because the issuer in the token won’t match the issuer specified in the OpenID metadata.