Skip to main content

Posts

Showing posts with the label .NET 8

GitHub Copilot SDK issue after upgrading to the 1.0.0-beta.10

After upgrading the GitHub Copilot SDK to the 1.0.0-beta.10 version, initiating the CopilotClient no longer worked. Instead I got the following error message: System.Text.Json.JsonException: The JSON value could not be converted to System.DateTimeOffset. Path: $.timestamp | LineNumber: 0 | BytePositionInLine: 43.  ---> System.InvalidOperationException: Cannot get the value of a token type 'Number' as a string.    at System.Text.Json.ThrowHelper.ThrowInvalidOperationException_ExpectedString(JsonTokenType tokenType)    at System.Text.Json.Utf8JsonReader.TryGetDateTimeOffset(DateTimeOffset& value)    at System.Text.Json.Utf8JsonReader.GetDateTimeOffset()    at System.Text.Json.Serialization.Converters.DateTimeOffsetConverter.Read(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options)    at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.ReadJsonAndSetMember(Object o...

Cleaner Minimal API Endpoints with [AsParameters]

I only recently started using the ASP.NET Core's minimal API style, but an annoying thing I already encountered is the "long parameter list" problem. Route handlers that accept five, six, or seven parameters start to feel unwieldy fast. The good news is that a solution exists through the [AsParameters] attribute, introduced in .NET 7,  that gives you a clean way out. The problem it solves Minimal APIs are appealing precisely because they're lightweight — no controllers, no ceremony. But that simplicity starts to break down as your endpoints grow more complex. Consider this example endpoint: That's eight(!) parameters before you've written a single line of business logic. It's hard to read, hard to test, and grows more painful every time requirements change. Enter [AsParameters] [AsParameters] lets you group related parameters into a plain C# class or record and bind them all at once. ASP.NET Core inspects the type's constructor and public ...

Unlocking Collection Expressions for your own types

C# 12 introduced collection expressions, a new, simplified syntax for initializing collections: This syntax works great with built-in collection types, but what about your own custom collections? That's where CollectionBuilderAttribute comes in, allowing you to extend this modern syntax to your own types. Custom Collections left behind Imagine you've built a custom immutable collection type: Before CollectionBuilderAttribute , you couldn't use the new collection expression syntax with this type. You'd be stuck with the old way: Not exactly elegant compared to the modern syntax. Enter CollectionBuilderAttribute The CollectionBuilderAttribute bridges this gap by telling the compiler how to construct your collection from a collection expression. Here's an example: Now you can write: Beautiful! The compiler automatically calls your Create method with the items. How it works The attribute takes two parameters: Builder Type : A type con...

WSFederation broken after upgrade to .NET 8

This week a colleague contacted me with an issue he encountered after upgrading to .NET 8.0. On the project involved we were using the WsFederation middleware to authenticate and interact with ADFS. However after upgrading to .NET 8 and the 8.x version of the Microsoft.AspNetCore.Authentication.WsFederation middleware the trouble began. Using this version resulted in a change in behavior as suddenly the middleware starts to expect a SAML 2.0 token instead of a SAML 1.1 token that is now issued by our ADFS server: XmlReadException: IDX30011: Unable to read XML. Expecting XmlReader to be at ns.element: 'urn:oasis:names:tc:SAML:2.0:assertion.Assertion', found: 'urn:oasis:names:tc:SAML:1.0:assertion.Assertion'. Although I found a post online that it would be technically possible to let ADFS return a SAML 2.0 token through WSTrust, this doesn’t fit in the passive federation scenario we had, so time to look at some alternative solutions. Attempt 1 – Reverting to an ...

.NET Conf Focus on Modernization

I don’t know what happened but somehow I succeeded to miss the latest .NET Conf Focus edition. And this time, it was all about a topic that every developer has to handle sooner or later during his professional career; Application Modernization! Here was the original announcement: Get Ready for .NET Conf: Focus on Modernization | Microsoft Community Hub and a screenshot from the agenda: The good news is all the content is available on YouTube here: .NET Conf - Focus on Modernization: Day 1 I’m especially interested in the session about the upcoming AI-assisted tooling to upgrade .NET apps. With the current pace at which new(er) LTS versions of .NET are released, any help to keep these applications supported and up-to-date is more then welcome:

AsyncEnumerable in C#: The importance of EnumeratorCancellation attribute

Modern applications often need to process large datasets or streams of data asynchronously. When we need to iterate through such data without loading everything at once, we've traditionally used IEnumerable. But what if our data access is inherently asynchronous? Enter IAsyncEnumerable<T> , introduced in C# 8.0 and .NET Core 3.0, designed specifically for asynchronous streaming scenarios. In this post, we'll explore IAsyncEnumerable<T> and why the EnumeratorCancellation attribute with a CancellationToken is crucial for writing robust, cancellable asynchronous code. What is IAsyncEnumerable<T>? IAsyncEnumerable<T> is an interface that represents a sequence of elements that can be asynchronously enumerated. It's the asynchronous counterpart to the familiar IEnumerable<T> interface. The beauty of IAsyncEnumerable<T> is that it allows you to: Perform asynchronous operations while iterating through a sequence Yield resu...

Using legacy text encodings in .NET Core

Upgrading an (old) .NET application to .NET core turned into a learning experience when we got the following error message after the upgrade was done: System.NotSupportedException : No data is available for encoding 1252. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method. TLDR; The application was using an older Windows-1252 text encoding causing the error above when trying to use this in .NET Core which doesn’t support this encoding out-of-the-box. Introduction to Text Encodings Text encoding is a method used to convert text data into a format that can be easily processed by computers. Computers inherently understand numbers, not characters, so text encoding maps characters to numerical values. This process ensures that text data can be stored, transmitted, and interpreted correctly across different systems and platforms. There are various text encodings, each designed to support different sets of characters. Some c...

.NET 8 upgrade - AuthenticationHandler

I know, I know, .NET 9 is released but I’m still helping one of my customers to move all workloads to .NET 8 first. Today we got a compiler error after upgrading our authentication code to .NET 8: 'ISystemClock' is obsolete: 'Use TimeProvider instead.' 1>C:\projects\IAMCore\IAM.Loket\IAMApiKeyAuthenticationHandler.cs(21,13,21,52): warning CS0618: 'AuthenticationHandler<IAMApiKeyAuthenticationOptions>.AuthenticationHandler(IOptionsMonitor<IAMApiKeyAuthenticationOptions>, ILoggerFactory, UrlEncoder, ISystemClock)' is obsolete: 'ISystemClock is obsolete, use TimeProvider on AuthenticationSchemeOptions instead.' Sidenote: I know that this is a warning, but we got ‘ Treat warnings as errors enabled’, a good practice I would recommend everyone to activate on their projects. Here is the original code: ISystemClock was an old abstraction to help during testing. It was never promoted as an official feature. With the release of .NE...

.NET 8 upgrade - error NETSDK1045: The current .NET SDK does not support targeting .NET 8.0.

A colleague asked me to create a small fix on an existing library. I implemented the fix and decided to take the occasion to upgrade to .NET 8 as well. How hard can it be… Turns out that this was harder than I thought. After upgrading the target framework moniker to .NET 8, the build started to fail with the following (cryptic) error message: C:\Program Files\dotnet\sdk\6.0.407\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.TargetFrameworkInference.targets(144,5): error NETSDK1045: The current .NET SDK does not support targeting .NET 8.0.  Either target .NET 6.0 or lower, or use a version of the .NET SDK that supports .NET 8.0. .NET 8 was certainly installed on this machine, so that could not be the issue: Then I took a second look at the error message and I noticed something, the compiler was using the .NET 6 SDK although the application itself was configured to use .NET 8. Of course! Now I remembered. In this project I was using a global.json file. Through this file y...

EF Core–Read and write models

Today I was working with a team that was implementing a CQRS architecture. CQRS (Command Query Responsibility Segregation) is a design pattern that separates the responsibilities of reading and writing data into distinct models. The idea is to use one model to handle commands (which modify data) and another model to handle queries (which retrieve data). This separation allows for better scalability, performance optimization, and flexibility, as the read and write operations can be independently optimized or scaled based on the specific needs of the system. After creating a read model for a specific table in the database, EF core started to complain and returned the following error message: System.InvalidOperationException : Cannot use table 'Categories' for entity type 'CategoryReadModel since it is being used for entity type 'Category' and potentially other entity types, but there is no linking relationship. Add a foreign key to 'CategoryReadModel' on the...

Implementing an OAuth client credentials flow with ADFS–Part 4–Understanding and fixing returned error codes

It looked like most of the world has made the switch to Microsoft Entra(Azure Active Directory). However one of my clients is still using ADFS. Unfortunately there isn't much information left on how to get an OAuth flow up and running in ADFS. Most of the links I found point to documentation that no longer exists. So therefore this short blog series to show you end-to-end how to get an OAuth Client Credentials flow configured in ADFS. Part 1 - ADFS configuration Part 2 – Application configuration Part 3 – Debugging the flow Part 4 (this post) – Understanding and fixing returned error codes Last post we updated our configuration so we could see any errors returned and are able to debug the authentication flow. In the first 2 posts I showed you everything that was needed to get up and running. The reality was that it took some trial and error to get everything up and running. In this post I share all the errors I got along the way and how I fixed them. IDX10204: Unabl...

Implementing an OAuth client credentials flow with ADFS–Part 3–Debugging the flow

It looked like most of the world has made the switch to Microsoft Entra(Azure Active Directory). However one of my clients is still using ADFS. Unfortunately there isn't much information left on how to get an OAuth flow up and running in ADFS. Most of the links I found point to documentation that no longer exists. So therefore this short blog series to show you end-to-end how to get an OAuth Client Credentials flow configured in ADFS. Part 1 - ADFS configuration Part 2 – Application configuration Part 3 (this post) – Debugging the flow In the first 2 posts I showed you the happy path. So if you did everything exactly as I showed, you should end up with a working Client Credentials flow in ADFS. Unfortunately there are a lot of small details that matter, and if you make one mistake you’ll end with a wide range of possible errors. In today’s post, I focus on the preparation work to help us debug the process and better understand what is going on. Updating your OAuth Confi...

Implementing an OAuth client credentials flow with ADFS–Part 2–Application configuration

It looked like most of the world has made the switch to Microsoft Entra(Azure Active Directory). However one of my clients is still using ADFS. Unfortunately there isn't much information left on how to get an OAuth flow up and running in ADFS. Most of the links I found point to documentation that no longer exists. So therefore this short blog series to show you end-to-end how to get an OAuth Client Credentials flow configured in ADFS. Part 1 - ADFS configuration Part 2 (this post) – Application configuration After doing all the configuration work in ADFS, I’ll focus today on the necessary work that needs to be done on the application side. Configuring the API We’ll start by configuring the API part. First create a new ASP.NET Core API project dotnet new webapi --use-controllers -o ExampleApi Add the ‘ Microsoft.AspNetCore.Authentication.JwtBearer ’ package to your project: dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer Add the auth...

.NET 8– Improved build output

Before .NET 8 when you build an application from the command line, the output looked like this: Starting with .NET 8 a new terminal logger is available that has the following improvements compared to the default console logger: Better use of colors Display of the execution time Better indication of the build status Improved grouping of warnings and errors Hyperlink to the output file if the build succeeds Unfortunately this new terminal logger is not enabled by default. You need to use the ‘--tl’ flag to enable it: There is an option to always use this new terminal logger by setting the MSBUILDTERMINALLOGGER environment variable to any of the following values: true : Always use the new terminal logger false : Never use the new terminal logger auto : Use the new terminal logger when supported by your console More information dotnet build command - .NET CLI | Microsoft Learn

Use dotnet pack with nuspec file

My understanding has always been that when packaging a library in a nuget package, I had 2 options available: Option 1 - Using a nuspec file with nuget pack command Option 2 - Using a csproj file with dotnet pack command Turns out I was wrong. So I want to use this post to explain where I was wrong. But before I do that let me dive into the 2 options above… Using a nuspec file with nuget pack One option you have is to put all the metadata for your nuget package inside a nuspec file. Here is how such a file can look like: To transform this nuspec file to a valid nuget package, use the following command: nuget pack example.nuspec Using a csproj file with dotnet pack A second option is to put all the metadata inside your csproj file: Now we can transform this to a valid nuget package, use the following command dotnet pack example.csproj Where was I wrong? Both of the options above work, but first of all I though that these are the only options(my first ...

BinaryFormatter serialization and deserialization are disabled within this application

Knowing that the support for .NET 6 will end soon (I’m writing this post August 2024, support ends in November 2024), I’m helping my customers move to .NET 8. UPDATE: After writing this article, Microsoft created a blog post with more details about the removal of the Binary Formatter in .NET 9.  Although Microsoft does a lot of effort to guarantee backwards compatibility, we still encountered some problems. In one (older) application where we were using (Fluent)NHibernate, we got the following error after upgrading: FluentNHibernate.Cfg.FluentConfigurationException: An invalid or incomplete configuration was used while creating a SessionFactory. Check PotentialReasons collection, and InnerException for more detail. ---> System.NotSupportedException: BinaryFormatter serialization and deserialization are disabled within this application. See https://aka.ms/binaryformatter for more information.    at System.Runtime.Serialization.Formatters.Binary.BinaryForm...

C# 12- Type Aliasing

During a code review I noticed a file I had not seen before in this application; a GlobalUsings.cs file. When opening the file I noticed it had a combination of global using statements and type aliases . Turns out that this is an emerging pattern emerge in .NET applications where developers are defining a GlobalUsings.cs file to encapsulate all (or most) using directives into a single file. If you have no clue what  these 2 language features are, here is a short summary for you. Global Usings Global usings were introduced in C# 10 and allows you to declare a namespace once in your application and make it available everywhere. So if we want to use a specific namespace, we need to add the following line to any source file: Remark: As I mentioned in the introduction, I would recommend to centralize these global usings in one file instead of spreading them out over multiple files in your codebase. What we can also do is instead of declaring this inside a source file, ...

Debug your .NET 8 code more efficiently

.NET 8 introduces a lot of debugging improvements. If you take a look for example at the HttpContext , you see that you get a much better debug summary than in .NET 7: .NET 7: .NET 8: But that is not a feature I want to bring under your attention. After recently updating my Visual Studio version, I noticed the following announcement among the list of new Visual Studio features: That is great news! This means that you can debug your .NET 8 applications without a big performance impact on the rest of your code. The only thing we need to do is to disable the Just My Code option in Visual Studio: If we now try to debug a referenced release binary, only the relevant parts are decompiled without impacting the other code: More information Debugging Enhancements in .NET 8 - .NET Blog (microsoft.com)

Publish a console app as a single executable

I created a small console application that automatically adds the application pool users on your local IIS server to the correct groups on the web server so that performance counter data is correctly send to Application Insights. You can find some extra content, the original announcement and the source code here: Azure Application Insights– Collect Performance counters data (bartwullems.blogspot.com) Azure Application Insights–Collect Performance Counters data - Part II (bartwullems.blogspot.com) wullemsb/AppInsightsPoolTool: Allows to automatically add AppPool users to the correct groups for Application Insights (github.com) So what is the reason for this post? When you publish the tool, it resulted in a combination of an exe and multiple DLL’s: This means that you need to copy all these files to be able to run the tool. It would be nice if there was only a single executable. Let’s see how to get this done… Switch to single file publish Open up the csproj f...

Azure Static Web Apps–Introducing the SWA CLI

As a follow-up on the presentation I did at CloudBrew about Azure Static Web Apps I want to write a series of blog posts. Part I - Using the VS Code Extension Part II - Using the Astro Static Site Generator Part III  – Deploying to multiple environments Part IV – Password protect your environments Part V – Traffic splitting Part VI – Authentication using pre-configured providers Part VII – Application configuration using staticwebapp.config.json Part VIII – API Configuration Part IX – Injecting snippets Part X – Custom authentication Part XI – Authorization Part XII -  Assign roles through an Azure function Part XIII -  API integration Part XIV – Bring your own API Part XV – Pass authentication info to your linked API Part XVI – Distributed Functions Part XVII – Data API Builder Part XVIII -  Deploy using Bicep Part XIX(this post) – Introducing the SWA CLI Today I want to introduce you a...