Skip to main content

Posts

Showing posts from February, 2022

Asynchronous Messaging and Eventing Resources

If you are interested in message or event based architectures, bookmark the link to the following Github repo: https://github.com/clemensv/messaging This repository is created by Clemens Vaster, the product architect of the messaging and eventing services in the Microsoft Azure cloud. It refers to a lot of talks and articles that help you to get started with message and event based systems and links to the product pages of multiple cloud providers and open source products that exist in this space.

GraphQL Network Inspector

If you are looking for some tools to help you in you day-to-day job as a GraphQL developer, have a look at the GraphQL Network Inspector chrome extension. It works in the same way as the built-in network inspector but is optimized for GraphQL. You can download the extension here: https://chrome.google.com/webstore/detail/graphql-network-inspector/ndlbedplllcgconngcnfmkadhokfaaln?hl=en-GB

ASP.NET Core - Required query string parameters

Typically when designing your API, query string parameters should be reserved for optional arguments. So for example if ID is a required parameter, it is better to use this as the URI: https://example.api.com/product/1234 instead of this: https://example.api.com/product?id=1234 where 1234 is the ID of the requested product. Of course there are always exceptions and I had a situation where I wanted to use a required query parameter. ASP.NET Core can help you there by using the [Required] or [BindRequired] attributes on your action method parameters: Both controllers will return a validation error when invoked without the id parameter:

HotChocolate GraphQL–Integration tests

The original way I wrote integration tests for my GraphQL endpoints was inspired by this blog post: https://chillicream.com/blog/2019/04/11/integration-tests As explained in this post you can create a schema instance and directly invoke it: However this approach no longer worked after upgrading to HotChocolate 12.  It started to fail with the following error message: Autofac.Core.Registration.ComponentNotRegisteredException : The requested service 'HotChocolate.ISchema' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency. I tried multiple approaches to get rid of this error but after a few attempts I rewrote the tests to use the Microsoft.AspNetCore.Mvc.Testing package. I copied a few Helper classes that I found in the HotChocolate repo to make this easier in combination with GraphQL. Now ...

Using Autofac in .NET 6 Minimal API’s

Before .NET 6 Minimal API’s you had 2 places where you had to apply some changes to replace the built-in IoC container with Autofac. First in your Program.cs file: And second in your Startup.cs file: But what should you do when using .NET 6 Minimal API’s ? In that case your Startup.cs file is gone. You still need to apply the same 2 steps but this time directly on the Host property of the WebApplicationBuilder : Remark: I assume that the process is quite similar for other 3th party IoC containers.

ASP.NET Core MVC model binding and nullable reference types

A few weeks ago I blogged about an issue where my breakpoint inside an ASP.NET MVC controller was never hit . The problem was caused by the built-in ModelStateInvalidFilter . What I didn’t share in that blog post is why the ModelState was invalid in the first place. Let’s see how a small change in my csproj file caused this… This is the model I was using: And this was an example I tried to send through my API: Everything worked until I made one small change. I updated my csproj file to start using nullable reference types : Now when I executed the same code it failed?! One look at the ModelState errors explained it: The FromAddress field is required. By enabling nullable reference types it handled both the ‘ ToAddress’ and ‘ FromAddress’ as required. To fix it, I had to update the DTO and enable nullability:

Impress your colleagues with your knowledge about… the DebuggerDisplay attribute

Sometimes when working with C# you discover some hidden gems. Some of them very usefull, other ones a little bit harder to find a good way to benefit from their functionality. One of those hidden gems that I discovered some days ago is a hidden feature of the DebuggerDisplay attribute. You probably already know the DebuggerDisplayAttribute . It allows you to tell the debugger what information to show in the IDE during a debug session. For example, when we debug the following class: you’ll see this information in the debugger: So far nothing new, but did you know that you can also use this for types you don’t own? Imagine that the Product class above was part of another assembly we don’t own and didn’t had the DebuggerDisplayAttribute . What we can do is set an attribute at the assembly level like this: This has the same effect in the debugger. Nice!

Error when specifying a HttpMessageHandler - System.InvalidOperationException : No service for type 'RetryDelegatingHandler' has been registered.

I created a custom HttpMessageHandler to handle the retry logic in my HttpClient. (I know that I could have used Polly but what is the fun in that?) I registered the HttpMessageHandler as part of my typed http client like this: However when I ran my application it failed with the following error: System.InvalidOperationException : No service for type ‘Reliability.RetryDelegatingHandler' has been registered.   Stack Trace: ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) <>c__4`1.<AddHttpMessageHandler>b__4_1(HttpMessageHandlerBuilder b) <>c__DisplayClass17_0.<CreateHandlerEntry>g__Configure|0(HttpMessageHandlerBuilder b) <>c__DisplayClass3_0.<Configure>b__0(HttpMessageHandlerBuilder builder) DefaultHttpClientFactory.CreateHandlerEntry(String name) <.ctor>b__1() Lazy`...

ASP.NET Core–Typed HttpClient

One of the ways that you can inject an HttpClient instance in your ASP.NET Core application is through ‘Typed clients’ . It is my preferred way as it takes maximal benefit from dependency injection, avoid the magic strings that ‘Named clients’ need and allows you to encapsulate the client configuration in one place. A typical example of a named client is this: This is possible thanks to following registration: Most examples of the typed client you find out there are using a concrete class(like in the example above) but I wanted to use an interface. Here was my first (naive) attempt: The result of the code above was that an HttpClient instance was injected but it wasn’t using the configuration values I specified in the Startup.cs. A second attempt was to specify the named client on the interface but this caused the same problem. The correct solution is the following:

.NET 7–Microsoft Orleans

I’m a big fan of the (virtual) actor model and a happy user of Microsoft Orleans . So I’m excited to see that Microsoft Orleans is getting some extra love from Microsoft. Not only by bringing the Orleans documentation to Microsoft Docs but also by the announcement made by Microsoft that Orleans will be one of the focus areas for .NET 7: Orleans : The ASP.NET Core and Orleans teams are investigating ways to further align and integrate the Orleans distributed programming model with ASP.NET Core. Orleans 4 will ship alongside .NET 7 and focuses on simplicity, maintainability, and performance, including human readable stream identities and a new optimized, version-tolerant serializer. If you are interested in the related roadmap, have a look here: https://github.com/dotnet/aspnetcore/issues/39504 This was the list of announced changes: Implement POCO Grains orleans#7351 Configurable serializers for grain persistence orleans#7471 Remove SMS Provider orleans#7475 ...

Happy Valentines Day–20 years of .NET

This year we are celebrating 20(!) years of .NET. Microsoft kicked off the celebration with a first event on Valentines Day. In case you had more romantic plans, you’ve probably missed the first event but no worries, you can watch the event here: Certainly tune in for the other upcoming events related to this celebration: I’ll certainly share my ‘war stories’ about my first years in .NET in an upcoming post(yes, I was there from the beginning).

ASP.NET Core–Help, my breakpoint is never hit

When debugging an ASP.NET Core Controller, my breakpoint in the action method was never hit. It took me some time to figure out why this was happening. It turns out that my model wasn’t valid.  ASP.NET Core has a default ModelStateInvalidFilter . This filter is executed before the controller method is executed. So when the ModelState is invalid, the code in the controller is never executed explaining why my breakpoint is never hit. If you want, you can suppress this filter: Be aware that this disables the filter globally.

Private fields in Javascript

I’ve always learned that Javascript didn’t support private fields. You could use closures as a ‘language hack’ to keep information private but it is not at the same level of simplicity: In the example above the privateVar field is not directly accessible. As I switched to TypeScript a long time ago, I didn’t care too much and happily used the private keyword there. Of course this was just a TypeScript hack and in the generated Javascript, the field was still accessible. More recently I switched to a different syntax in TypeScript to specify private fields: What I wasn’t aware of that this became the default way that private fields are specified in Javascript . Cool!

Serilog - Filter out the ASP.NET Core info

When you are using the built-in logging in ASP.NET Core, you can filter out specific information by changing the log levels in the appsettings.json: But when you switch to Serilog, this no longer works and the configuration values are ignored. Our original configuration looked like this: Here is what was logged by default after switching to Serilog: 2022-02-03 12:17:07.861 +01:00 [WRN] Failed to determine the https port for redirect. 2022-02-03 12:17:58.429 +01:00 [WRN] Failed to determine the https port for redirect. 2022-02-03 12:19:19.555 +01:00 [WRN] Failed to determine the https port for redirect. 2022-02-03 12:20:21.553 +01:00 [INF] OnStarted has been called. 2022-02-03 12:20:21.631 +01:00 [INF] Request starting HTTP/1.1 POST http://localhost/mail/ application/json;+charset=utf-8 318 2022-02-03 12:20:21.631 +01:00 [INF] Request starting HTTP/1.1 POST http://localhost/mail/ application/json;+charset=utf-8 318 2022-02-03 12:20:21.631 +01:00 [I...

.NET 5.0 End of life

.NET 5.0 will reach end of life on May 08, 2022. After that time, .NET 5.0 patch updates will no longer be provided. So don’t wait until then to upgrade your .NET 5 application to .NET 6. Upgrading is easy: Update your global.json file (if applicable) to the .NET 6 SDK: Update the target framework moniker in your csproj file: Update the ASP.NET Core package references to 6.0.0 or later: Remark: If you want you can start using new features in .NET 6 like the minimal hosting model but this is not necessary. More information: https://docs.microsoft.com/en-us/aspnet/core/migration/50-to-60?WT.mc_id=DOP-MVP-5001942

XUnit - Simulate concurrency and load against an API endpoint

Today I was working on an ASP.NET Core Web API that implements rate limiting. The ASP.NET Core Web API should still accept the incoming requests but the handling of the requests should be buffered when the rate limits where exceeded. Maybe I’ll share how I implemented this in another blog post, but in this post I want to focus on how I tested this functionality. My first idea was to use Parallel.For() to generate a lot of concurrent requests. You would think it would generate a number of request using the specified or calculated degree of parallelism.  Unfortunately that is not the case. Instead, all the tasks are started at the same time. In the example above all 10 tasks are started at the same time. Another issue is that Parallel.For() doesn’t wait for the started tasks to finish which would result in the completion of the test without waiting for the results. So we need to find another way to achieve our goal. I got what I want by using a combination of Task.WhenAll()...

Azure Open Source Day

On Tuesday, February 15 Microsoft will host a free digital event ‘Azure Open Source Day’. Here is the announcement : Join this free digital event to learn how Microsoft is committed to open source and works with the open-source community to develop new technologies. Hear about the latest trends and capabilities of using Linux and Azure together—direct from Microsoft insiders. Whether you’re new to Azure or are already using it, you’ll discover how to turbocharge your apps and data with open-source and hybrid cloud technologies. Register now to: Discover practical ways to optimize your Linux investments and innovate faster on Azure. Discover tools for every developer, including Visual Studio Code, GitHub Codespaces, and the new Azure Cosmos DB API for MongoDB. Learn about the latest innovations in containers and serverless computing, including Azure Kubernetes Service (AKS). Dig into CBL-Mariner, the Linux distribution built by Microsoft to host A...

XUnit–Cancel a test when it takes too long

As part of one of my projects I have a set of smoke tests that I use to test the availability and correct behaviour of an external API. All our code that interacts with other services is using retries with exponential backoff(through Polly ) which helps with the reliability and resiliency of our system. Unfortunately this also means that when we use the same code for our smoke tests, it takes a lot of time before the tests fail when the external API is not available. Taking into account all the retries, an individual test will fail after about 2 minutes. If you know that we have a lot of smoke tests available, the tests take a long time to execute. I could reconfigure the retry policies to fail sooner but  another option is to cancel a test when it takes too long. In XUnit you can do this through the Timeout property on the [Fact] attribute. Remark: Timeout is only supported when parallellization is disabled. An example I first disabled the parallel test execution...

.NET 6–Add timeout and cancellation support to existing async methods using Task.WaitAsync

.NET 6 adds a new WaitAsync method to System.Threading.Tasks.Task. The documentation says the following about this method: Gets a Task that will complete when this Task completes, when the specified timeout expires, or when the specified CancellationToken has cancellation requested. So when is this alternative to Task.Wait useful? There are a lot of libraries that provide task-based methods but don’t allow to pass a cancellation token. With Task.WaitAsync() you can add cancellation or timeout ability for async methods, that inherently don't provide such capability. Before you would typically write a helper method to solve this issue, but now you get a solution out-of-the-box. An example Here is an example where we add timeout functionality to an existing async method: In this case the task never completes, so after 5 seconds (the configured timeout) a timeout exception will be thrown. Another example would be to add cancellation support to an existing asy...

Azure DevOps–TLS warning

Today, when I browsed to Azure DevOps I was welcomed with the following warning: Over night something had changed and Microsoft stopped accepting TLS 1.0 / TLS 1.1 connections. It seems that I missed this blog post . Due to the potential for future protocol downgrade attacks and other Transport Layer Security (TLS) protocol versions 1.0 and 1.1 vulnerabilities not specific to Microsoft’s implementation, it is required that dependencies on all security protocols older than TLS 1.2 be removed wherever possible. Impact should be minimable unless you are still using Visual Studio 2010, 2012 or 2013. It also may impact Git operations in Visual Studio 2017(if you didn’t install the latest update). In case you are still using these older Visual Studio versions, you can use the following registry change to force TLS 1.2 for all(!) .NET applications on your machine: https://docs.microsoft.com/en-us/troubleshoot/azure/active-directory/enable-support-tls-environment?tabs=azure-moni...