Skip to main content

Posts

Showing posts from January, 2022

.NET 6 minimal API–Integration testing

.NET 6 introduces a new way to write your API’s without the need of a Startup.cs file. More about ‘Minimal APIs’ as this feature is called can be found here: https://docs.microsoft.com/en-us/aspnet/core/tutorials/min-web-api?view=aspnetcore-6.0 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/minimal-apis?view=aspnetcore-6.0 But how do you write an integration test for such a minimal API? Before you used the WebApplicationFactory<TStartup> and specified the Startup.cs as the generic argument of the factory. But now the Startup.cs file is gone. Luckily Microsoft thought about this and updated the Microsoft.AspNet.Mvc.Testing package to work without it. I find the solution not very clean but at least it works. Here are the steps you need to take: Microsoft made it possible to use the Program.cs file as the generic argument instead of the Startup.cs file. Unfortunately by default the Program.cs file is internal so we have to make some chang...

ASP.NET Core–Integration testing–Configuration

Integration testing in ASP.NET Core is really easy thanks to the Microsoft.AspNetCore.Mvc.Testing package. (Check out my previous post about this). Reference the startup file,  inject the WebApplicationFactory<TStartup> in your test class and you are good to go. This will create an in memory test server that can be invoked directly. While using this approach I stumbled over a problem. The startup file was not using the configuration I had  specified in the appsettings.json??? To make a long story short, it turns out that the startup file will use the appsettings.json file as available in the API project not in your test project. So if you need to apply specific configuration settings for your test scenario’s, you have to make this changes to the appsettings.json (or appsettings.<environment>.json) in your API project.

ASP.NET Core - No authenticationScheme was specified, and there was no DefaultForbidScheme found.

Today I encountered a strange issue in an ASP.NET Core Web API application. Although I didn’t had authentication nor authorization configured(or at least that was what I thought) in my application, I still got a security related error when I tried to call any of the API endpoints: System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultForbidScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).    at Microsoft.AspNetCore.Authentication.AuthenticationService.ForbidAsync(HttpContext context, String scheme, AuthenticationProperties properties)    at Microsoft.AspNetCore.Mvc.ForbidResult.ExecuteResultAsync(ActionContext context)    at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeResultAsync>g__Logged|22_0(ResourceInvoker inv...

Azure DevOps Server 2020 - Warning NETSDK1182: Targeting .NET 6.0 in Visual Studio 2019 is not supported

In a build pipeline on Azure DevOps Server 2020 I was trying to build a .NET 6 application. Unfortunately the build failed with the following error message: ##[warning]C:\Program Files\dotnet\sdk\6.0.101\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.targets(134,5): Warning NETSDK1182: Targeting .NET 6.0 in Visual Studio 2019 is not supported. I was using the Visual Studio Build task to build my application. Here is the related yaml file: The problem is that the current version of this task only support Visual Studio  version up 2019 on Azure DevOps Server. Visual Studio 2022 is not yet supported by this build task (at the moment of writing this post). I worked around this issue by switching to the .NET Core CLI task : Another option is to download and install the updated Visual Studio Build task manually. You will also need to update your agents to the latest version. If you want to try this approach, check out this post by Jesse Houwing: https...

Learn something new about GraphQL

New to GraphQL and you want to learn about the possibilities, ecosystem and tooling? Subscribe to graphql.wtf to get new content every week.  

Osmotic communication–Why I don’t like to work remotely

Image you are sitting in a room together with your team mates. You are reviewing a pull request why in the background you hear your team discussing on how to implement a specific feature. While you are focussing on your own work you are passively picking up some information from the team chatter in the background. This can be distracting but also highly valuable, as you learn what is going on in your team and always can start to participate if you want to.  This is what is called ‘osmotic communication’ and it is a technique I like to apply. (People who have worked with me before will certainly recognize this…) (You should remember the term ‘osmosis’ from your biology or chemistry lessons) Some think that ‘osmotic communication’ is an anti-pattern, but in my job as an architect, it not only helps me understand how the team is tackling a specific problem but also where I didn’t do a good job explaining the overall architecture. It gives me the opportunity to provide some c...

.NET - Renaming a project

If there is one thing that is painfull when using Visual Studio then it is renaming your project. I typically try to keep my projectnames in sync with my current understanding of the business domain. But as I gain new insights, it can happen that I need to rename these projects to align them with the ubiquitous language. So far, I always used a manual approach where I typically do the following: Rename the project file Rename the folder Change the project references in other project If there are a lot of projects that should be renamed, it is really cumbersome to do. Project Renamer to the rescue! This global tool does all the things above (and more) for you. To use it, first install it as a global tool: dotnet tool install -g ModernRonin.ProjectRenamer After the tool is installed, you can use it from the command line, in the directory of your solution: renameproject <oldProjectName> <newProjectName> After asking for confirmat...

Build GUI console applications through Terminal.Gui

While browsing through GitHub, I stumbled over the following project; Terminal.Gui - Cross Platform Terminal GUI toolkit for .NET This is a toolkit library that helps you build cross-platform GUI console apps. It contains a large list of controls for building text user interfaces and even let you use a reactive programming style through support for reactive extensions . I created a small example that allows you to scroll through all files in the current directory. Create a new console application: dotnet new console Add the Terminal.Gui NuGet package: dotnet add package terminal.gui Add your code: Run the console app: dotnet run  

GraphQL–Upload files using HotChocolate

Originally it was not possible to upload files through GraphQL so typically I used a seperate REST API when I needed support for uploading files. The main disadvantage of this approach was that it introduced some extra work and that I had to make sure that things like authentication and authorization were handled on both the REST endpoint and the GraphQL endpoint. With the introduction of the GraphQL Multipart Request specification , this separate endpoint became obsolete and uploading files through your GraphQL server became an option. Let’s walk through the steps to get this done in HotChocolate : I used the HotChocolate template to get started quickly. If you don’t have the template yet, first install it using: dotnet new -i HotChocolate.Templates.Server Now you can bootstrap your application using: dotnet new graphql Register the Upload scalar to support file uploads: Create a mutation that uses this scalar to upload the file: Register the ...

ASP.NET Core–Health checks

ASP.NET Core offers Health Checks Middleware for reporting the health of your application. Health checks are exposed as HTTP endpoints and can be probed by container orchestrators and load balancers to check an app's status. For Kubernetes I typically create 2 type of health checks: Readiness indicates if the app is running normally but isn't ready to receive requests. Liveness indicates if an app has crashed and must be restarted. This is a general guideline we use for all containerized applications that we have running in Kubernetes. Last week I was reviewing one of those applications and I noticed the following code: This code is perfectly fine, but I couldn’t remember exactly what the role of the Predicate was in the example above. Time to dig in somewhat deeper… By default, the Health Checks Middleware runs all registered health checks. To run a subset of health checks, you can provide a function that returns a boolean to the Predicate option. So...

Azure DevOps–Run GraphQL Inspector as part of your build pipeline

I introduced GraphQL Inspector in a previous blog post . Let’s see today how you can integrate it into your Azure DevOps pipeline. You can do this by adding a command line task that invokes NPX. NPX stands for Node Package Execute and it comes with NPM. It is an npm package runner that can execute any package that you want from the npm registry. I added a command line task to invoke npx: Remark: I blogged about NPX before (using GraphQL Inspector as an example). Something you should really be aware of is the order of the parameters when invoking graphql-inspector. The first parameter should be the existing schema and the second parameter should be the new, updated schema. Today I accidently switched them around which of course broke the backwards compatibility. Here is the build output when using the wrong argument order: And here is the build output after fixing the order:

ASP.NET Core–Mark a web api as deprecated

Versioning of your API’s in ASP.NET Core is easy thanks to the Microsoft.Aspnetcore.Mvc.Versioning nuget package. It allows us to implement versioning with a few configuration lines. After installing the Nuget you should update the ConfigureServices() method in Startup.cs: Now you can add the [ApiVersion] attribute on your controller: If you now have multiple versions of your api, you can decide which version to use by adding an ?api-version=1.0 at the end of your url. So far nothing new. A feature I only discovered recently is that you can also flag an API as deprecated.  Therefore you need to set an additional Deprecated property on the attribute: When a client now calls the deprecated API, an extra response header ‘ api-deprecated-versions ’ is returned : api-deprecated-versions: 1.0

ASP.NET Core - Configure file upload size limits

By default, ASP.NET Core allows you to upload files up of (approximately) 28 MB  in size. However, for an application I had to update this limit to support files up to 128MB. Let’s see what should be done to get this working in ASP.NET Core: Open your Startup.cs and write the following code in the ConfigureServices(): The code above configures the FormOptions and sets the MultipartBodyLengthLimit property to 128MB. Unfortunately we are not done yet. Depending on if you use Kestrel or host your application in IIS (Express), some extra work is required. IIS (Express) For IIS (Express) you need to update your web.config and add the following configuration section: Kestrel For Kestrel, you need to add some extra code in your Program.cs file:

C# - Case-insensitive Enumerable.Contains()

While writing tests for an application, one test I created failed unexpectedly. The code it tested was the following: This code reads all querystring parameters from the current request excluding a set of predefined parameters. I use this code to capture all query string parameters that are not explicitely bound to an action method parameter: Do you spot the bug? The problem was that this code only worked when the query string parameter name has the same casing as the parameter names in my code. If the casing was different not all parameters where excluded. To explain this further, following querystring worked as expected: ?foldername=root&isProtected=false&tag1=value1 Whereas the following querystring didn’t do the trick: ?folder N ame=root& I sProtected=false&tag1=value1 To fix it, I had to update the Contains() check to be case-insensitive. This can be done by using an overload that allows you to specify an IEqualityComparer&lt;T&gt...

Github - Deploy a Nuget Package on a new release

I have a small library that I created a few years ago to use PostgreSQL as a distributed cache in .NET core. As I wanted to get more acquainted with Github and all it possibilities, I thought it was a good occasion to make some improvements and optimize the deployment process. (I manually pushed the first version of the package to NuGet.org). Let’s see how we can automate this by combining the Release functionality in Github with Github actions.   Create the Github actions workflow Let’s first create a workflow that does the following: Build the library Create the NuGet package Upload the NuGet package to NuGet.org Therefore we go to our Github page and select Actions. Choose New workflow . We will not use one the suggested workflows but want to create our workflow from scratch so click on set up a workflow yourself . Now we’ve finally arrived on the Edit workflow screen. Replace the existing workflow definition with the following: ...

NuGet–Add a README to your NuGet Package

Did you know that yu can pack a README.md file in your NuGet Package and that it will be rendered on NuGet.org? NuGet.org supports this (new) feature for some time but I didn’t had time so far to try it out.  To use it, you need to have first of all an README.md file in your Repo. This is already the case for my Extensions.Caching.PostgreSQL repo : Now I need to update my project file and reference the README.md: After deploying the updated package, my Readme file becomes visible on Nuget.org: More information: https://devblogs.microsoft.com/nuget/add-a-readme-to-your-nuget-package/

Towards more diversity–Becoming a more inclusive IT industry

As a priviliged white male, it is maybe not up to me talk about diversity. But I want to help and I try to move from being unconscious incompetent to (at least) conscious incompetent when talking about diversity.  My eyese are opening slowly and I start to be aware how lucky I am and how hard it must be for people with different color, religion, background, gender,… to work in our industry. Working in a male dominated industry(IT) where we are continuously looking for new talent, being more inclusive will be an important part of the solution. It is our responsibility to make this possible. I want to share 2 talks that helped me open my eyes: One is by Kent Beck, titled “XP as an incentive system”. The title doesn’t match the content as it is a shout out to everyone to become more inclusive and forces us to think on how we are behaving and how maybe we (unconsciously) contribute to the problem instead of being part of the solution. The second video is a TED talk “Why do s...

Error MSB3030: Could not copy the file "StaticWebAssets.xml" because it was not found.

A collegae contacted me today with the following question; his builds started to fail suddenly with the following error: ##[error]C:\Program Files\dotnet\sdk\6.0.101\Microsoft.Common.CurrentVersion.targets(5100,5): Error MSB3030: Could not copy the file "StaticWebAssets.xml" because it was not found. He was wondering if something was changed on the build server and indeed he was right; we recently installed the .NET 6 SDK on the build server. As you can see in the error message, the project was built using the .NET 6 SDK. To fix the error we provided a short and long term solution. The short term solution The short term solution was triggering a clean solution before building the project. This will remove all remaining build artifacts and guarantees a clean slate. To achieve this in Azure DevOps using the Classic pipeline: Go to your Build pipeline Select the Get Sources Tab Set the Clean value to true Save the pipeline and run the build ...

Swashbuckle - Free form query parameters

I’m creating an api where an arbitrary number of query parameters can be added. The API looks something like this: GET /api/example?param1=value1&param2=value2&param3=value3 By default when Swashbuckle generates the Swagger UI it only includes parameters that are explicitly defined at the action method level. Luckily the Open API spec supports this starting from version 3 through ‘free form query parameters’. At the spec level this looks like this: To achieve this using Swashbuckle you can use an operation filter: This will generate the following UI: