<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Gilles TOURREAU's blog]]></title><description><![CDATA[A French seasoned architect and developer specializing in Microsoft technologies such as .NET and Azure.]]></description><link>https://gilles.tourreau.fr</link><generator>RSS for Node</generator><lastBuildDate>Tue, 21 Apr 2026 17:13:33 GMT</lastBuildDate><atom:link href="https://gilles.tourreau.fr/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Discover PosInformatique.Foundations 1.0.0: A Comprehensive Overview]]></title><description><![CDATA[Today I am releasing PosInformatique.Foundations 1.0.0: a set of small, focused .NET libraries that I use every day in my projects, and that are now available as NuGet packages.
This project was born from a very simple frustration:

I was tired of re...]]></description><link>https://gilles.tourreau.fr/announcing-posinformatique-foundations-100-small-practical-net-building-blocks</link><guid isPermaLink="true">https://gilles.tourreau.fr/announcing-posinformatique-foundations-100-small-practical-net-building-blocks</guid><category><![CDATA[.NET]]></category><category><![CDATA[Building Block Set]]></category><category><![CDATA[email]]></category><category><![CDATA[ValueObject]]></category><category><![CDATA[ValueObjects]]></category><category><![CDATA[bulk emailing]]></category><category><![CDATA[standardization]]></category><category><![CDATA[Nuget]]></category><category><![CDATA[Phone number]]></category><category><![CDATA[normalization]]></category><category><![CDATA[normalizer]]></category><category><![CDATA[library]]></category><category><![CDATA[dotnet]]></category><dc:creator><![CDATA[Gilles TOURREAU]]></dc:creator><pubDate>Thu, 20 Nov 2025 11:03:54 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/US9Tc9pKNBU/upload/1039db40c3be7337eb7656c46899166a.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today I am releasing <a target="_blank" href="https://github.com/PosInformatique/PosInformatique.Foundations/"><strong>PosInformatique.Foundations</strong></a> <strong>1.0.0</strong>: a set of small, focused .NET libraries that I use every day in my projects, and that are now available as <a target="_blank" href="https://www.nuget.org/packages?q=PosInformatique.Foundations">NuGet packages</a>.</p>
<p>This project was born from a very simple frustration:</p>
<ul>
<li><p>I was tired of <strong>recreating the same basic value objects</strong> (email, phone number, names, MIME types, etc.) in every project.</p>
</li>
<li><p>I wanted to <strong>standardize data</strong> across applications instead of having a different string format and validation rule in each solution.</p>
</li>
<li><p>I did not want to create a huge “framework” or “super library” that you install for <strong>one useful type</strong> and then carry hundreds of classes you never use.</p>
</li>
</ul>
<p>So instead, I decided to build a set of <strong>small, independent libraries</strong>, each one doing <strong>one thing well</strong>, and all following the same philosophy.</p>
<h2 id="heading-philosophy-small-focused-and-standards-based">Philosophy: Small, Focused and Standards-Based</h2>
<p><a target="_blank" href="https://github.com/PosInformatique/PosInformatique.Foundations">PosInformatique.Foundations</a> is not a framework. It is a <strong>toolbox of tiny building blocks</strong>:</p>
<ul>
<li><p><strong>Granular</strong>: each package is <strong>independent, lightweight, minimal</strong>.</p>
</li>
<li><p><strong>Composable</strong>: you install <strong>only what you need</strong>.</p>
</li>
<li><p><strong>Practical</strong>: most packages are about <strong>value objects</strong>, helpers, and small utilities that are missing in many projects.</p>
</li>
<li><p><strong>Standards-based</strong>: whenever possible, implementations follow existing standards:</p>
<ul>
<li><p>Email addresses: <strong>RFC 5322</strong></p>
</li>
<li><p>Phone numbers: <strong>E.164</strong></p>
</li>
<li><p>MIME types: <strong>IANA</strong> media types</p>
</li>
</ul>
</li>
<li><p><strong>Integration-specific packages</strong>: instead of making the core value object depend on everything, I provide <strong>derived packages</strong> per technology:</p>
<ul>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations">DataAnnotations</a></p>
</li>
<li><p><a target="_blank" href="https://fluentvalidation.net/">FluentValidation</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/ef/core/">Entity Framework Core</a></p>
</li>
<li><p><a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.text.json">System.Text.Json</a></p>
</li>
<li><p>etc.</p>
</li>
</ul>
</li>
</ul>
<p>You can use the core value objects alone, or plug them into Entity Framework Core, validation, or JSON serialization with the packages you need.</p>
<p>All libraries target <strong>.NET 8.0</strong>, <strong>.NET 9.0</strong> and <strong>.NET 10.0</strong>.</p>
<h2 id="heading-main-features-in-100">Main Features in 1.0.0</h2>
<h3 id="heading-email-address-value-object">Email Address Value Object</h3>
<p>Package: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.EmailAddresses">PosInformatique.Foundations.EmailAddresses</a><br />Plus integrations: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.EmailAddresses.EntityFramework">EF Core</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.EmailAddresses.FluentValidation">FluentValidation</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.EmailAddresses.Json">System.Text.Json</a>.</p>
<p>This package provides a <strong>strongly-typed</strong> <code>EmailAddress</code> value object with:</p>
<ul>
<li><p>Validation based on <strong>RFC 5322</strong></p>
</li>
<li><p>Normalization (for example on casing of the local and domain parts)</p>
</li>
<li><p>Equality and comparison on the normalized form</p>
</li>
</ul>
<p>Why it helps:</p>
<ul>
<li><p>No more <code>string</code> email arguments everywhere.</p>
</li>
<li><p>You avoid inconsistent regexes and ad-hoc checks in each project.</p>
</li>
<li><p>You can share a standard, tested implementation across many solutions.</p>
</li>
</ul>
<h3 id="heading-phone-number-value-object-e164">Phone Number Value Object (E.164)</h3>
<p>Package: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.PhoneNumbers">PosInformatique.Foundations.PhoneNumbers</a><br />Plus integrations: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.PhoneNumbers.EntityFramework">EF Core</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.PhoneNumbers.FluentValidation">FluentValidation</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.PhoneNumbers.Json">System.Text.Json</a>.</p>
<p>The <code>PhoneNumber</code> value object represents numbers in <strong>E.164 format</strong>:</p>
<ul>
<li><p>Parsing with region-aware support for local numbers</p>
</li>
<li><p>Validation and normalization to a single, canonical form</p>
</li>
<li><p>Helpers for formatting and comparison</p>
</li>
</ul>
<p>This gives you <strong>consistent phone numbers</strong> across your system:</p>
<ul>
<li><p>One normalized representation</p>
</li>
<li><p>Easier matching and comparisons</p>
</li>
<li><p>No more half-baked "+33" vs "0033" vs local format issues</p>
</li>
</ul>
<h3 id="heading-firstlast-name-value-objects">First/Last Name Value Objects</h3>
<p>Package: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.People">PosInformatique.Foundations.People</a><br />Plus integrations: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.People.DataAnnotations">DataAnnotations</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.People.FluentValidation">FluentValidation</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.People.FluentAssertions">FluentAssertions</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.People.EntityFramework">EF Core</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.People.Json">System.Text.Json</a>.</p>
<p>These packages provide:</p>
<ul>
<li><p><code>FirstName</code> and <code>LastName</code> value objects with normalization and validation</p>
</li>
<li><p>Integration with:</p>
<ul>
<li><p><strong>DataAnnotations</strong> for ASP.NET MVC / Blazor forms</p>
</li>
<li><p><strong>FluentValidation</strong> for more advanced validation rules</p>
</li>
<li><p><strong>Entity Framework Core</strong> for persistence</p>
</li>
<li><p><strong>System.Text.Json</strong> for serialization</p>
</li>
</ul>
</li>
</ul>
<p>Goal: stop using raw strings for user names and apply <strong>shared rules</strong> across your application with the following conventions:</p>
<ul>
<li><p>The last name are in uppercase and allows only one space as separator and alphabetic characters.</p>
</li>
<li><p>The first name starts with uppercase and the letters are in lower case. The hypen and one spaces are allowed for separators.</p>
</li>
</ul>
<h3 id="heading-mimetype-value-object">MimeType Value Object</h3>
<p>Package: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.MediaTypes">PosInformatique.Foundations.MediaTypes</a><br />Plus integrations: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.MediaTypes.EntityFramework">EF Core</a>, <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.MediaTypes.Json">System.Text.Json</a>.</p>
<p><code>MimeType</code> is an immutable value object that represents a media type like <code>image/png</code> or <code>application/pdf</code>, with:</p>
<ul>
<li><p>A list of well-known MIME types</p>
</li>
<li><p>Helpers to map between extensions and media types</p>
</li>
<li><p>Strong typing instead of <code>string</code> everywhere</p>
</li>
<li><p>Functional helpers to determine if a MIME type is an image, Auto CAD drawing,…</p>
</li>
</ul>
<h3 id="heading-text-templating-building-emails-and-more-from-models">Text Templating: Building Emails (and More) From Models</h3>
<p>Emailing is a <strong>simple but essential</strong> feature in almost every application. I wanted a way to:</p>
<ul>
<li><p>Define <strong>strongly-typed email templates</strong> with a model</p>
</li>
<li><p>Use different templating engines (Razor, Scriban, …)</p>
</li>
<li><p>Keep the email sending logic <strong>decoupled</strong> from the rendering engine</p>
</li>
</ul>
<p>This is why I introduced two building blocks:</p>
<ol>
<li><p><strong>Text templating abstractions</strong></p>
<ul>
<li><p>Package: <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.Text.Templating">PosInformatique.Foundations.Text.Templating</a></p>
</li>
<li><p>Provides:</p>
<ul>
<li><p><code>TextTemplate&lt;TModel&gt;</code> base class</p>
</li>
<li><p><code>ITextTemplateRenderContext</code></p>
</li>
</ul>
</li>
<li><p>Idea: define a clear contract for “take a model and render text”.</p>
</li>
</ul>
</li>
<li><p><strong>Concrete implementations</strong></p>
<ul>
<li><p><a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.Text.Templating.Razor">PosInformatique.Foundations.Text.Templating.Razor</a></p>
<ul>
<li><p>Razor-based templating using Blazor components</p>
</li>
<li><p>Strongly-typed models</p>
</li>
<li><p>Full dependency injection support</p>
</li>
</ul>
</li>
<li><p><a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.Text.Templating.Scriban">PosInformatique.Foundations.Text.Templating.Scriban</a></p>
<ul>
<li><p>Scriban-based templating with mustache-style syntax</p>
</li>
<li><p>Strongly-typed models mapped to template data</p>
</li>
</ul>
</li>
</ul>
</li>
</ol>
<p>On top of that, there is an <strong>emailing infrastructure</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.Emailing">PosInformatique.Foundations.Emailing</a></p>
</li>
<li><p>Plus providers:</p>
<ul>
<li><p><a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Azure">PosInformatique.Foundations.Emailing.Azure</a> (Azure Communication Service)</p>
</li>
<li><p><a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Foundations.Emailing.Graph">PosInformatique.Foundations.Emailing.Graph</a> (Microsoft Graph API)</p>
</li>
</ul>
</li>
</ul>
<p>You can:</p>
<ul>
<li><p>Register <strong>email templates</strong> (subject + body) as text templates</p>
</li>
<li><p>Render them from a model (e.g., <code>PasswordResetModel</code>, <code>WelcomeUserModel</code>, etc.)</p>
</li>
<li><p>Send them via a chosen provider</p>
</li>
</ul>
<p>The <strong>nice part</strong> is that this text templating mechanism is <strong>generic</strong>. It is not limited to emails:</p>
<ul>
<li><p>You can reuse it to generate:</p>
<ul>
<li><p>SMS content</p>
</li>
<li><p>Notifications</p>
</li>
<li><p>System messages</p>
</li>
<li><p>Any other text-based messages from a model</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-why-not-one-big-library">Why Not One Big Library?</h2>
<p>I intentionally avoid a single “mega package” that does everything.</p>
<p>Instead:</p>
<ul>
<li><p>Each package has a <strong>single responsibility</strong>.</p>
</li>
<li><p>There is <strong>no hard coupling</strong> between them (only logical relationships).</p>
</li>
<li><p>You choose:</p>
<ul>
<li><p>Only the value objects you need (email, phone, names, MIME types, …)</p>
</li>
<li><p>Only the integrations you need (EF, JSON, validation, …)</p>
</li>
<li><p>Only the emailing pieces you actually use.</p>
</li>
</ul>
</li>
</ul>
<p>This keeps your dependencies clean and your binaries smaller, and it avoids installing 98% of unused code <strong>just for one class</strong>. Also, because the library are very small, you can use it in Blazor WASM applications which requires binaries as small as possible for the startup of the application.</p>
<h2 id="heading-net-compatibility-and-dependencies">.NET Compatibility And Dependencies</h2>
<p>All <a target="_blank" href="https://www.nuget.org/packages?q=PosInformatique.Foundations">PosInformatique.Foundations</a> packages target:</p>
<ul>
<li><p><strong>.NET 8.0</strong></p>
</li>
<li><p><strong>.NET 9.0</strong></p>
</li>
<li><p><strong>.NET 10.0</strong></p>
</li>
</ul>
<p>For external dependencies, I intentionally target <strong>relatively old versions</strong> (for example <a target="_blank" href="https://www.nuget.org/packages/Microsoft.Graph">Microsoft.Graph</a>) to stay compatible with more projects.</p>
<p>If you need newer versions in your solution, you can simply:</p>
<ul>
<li><p>Add an explicit reference to the newer dependency in your application</p>
</li>
<li><p>Let NuGet resolve the latest version for that library</p>
</li>
<li><p>Still use <a target="_blank" href="https://www.nuget.org/packages?q=PosInformatique.Foundations">PosInformatique.Foundations</a> without issues</p>
</li>
</ul>
<p>This approach keeps the libraries flexible and avoids forcing a full update of your stack.</p>
<h2 id="heading-real-world-usage">Real-World Usage</h2>
<p>These libraries are not theoretical. I built them to solve real problems in real applications.</p>
<p><a target="_blank" href="https://github.com/PosInformatique/PosInformatique.Foundations">PosInformatique.Foundations</a> is currently used in the development of <strong>SaaS applications</strong> at:</p>
<ul>
<li><p><a target="_blank" href="https://www.chantier-connect.com/">Chantier Connect</a>: A 360° application for desktop, tablet, and phone, and a kiosk to track the progress of construction sites.</p>
</li>
<li><p><a target="_blank" href="https://www.artahe-solutions.com/">Artahe Solutions</a>: A software editor that allows the creation of activity tracking reports.</p>
</li>
</ul>
<p>The goal is to reuse the same reliable building blocks across multiple products, rather than copy-pasting the same pieces of code again and again.</p>
<h2 id="heading-getting-started">Getting Started</h2>
<p>All packages are available on NuGet.<br />The full list is in the GitHub repository: <a target="_blank" href="https://github.com/PosInformatique/PosInformatique.Foundations">PosInformatique.Foundations</a></p>
<p>From there you can:</p>
<ul>
<li><p>Browse each package README</p>
</li>
<li><p>Copy installation commands</p>
</li>
<li><p>See examples, supported scenarios, and integration details</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p><a target="_blank" href="https://www.nuget.org/packages?q=PosInformatique.Foundations">PosInformatique.Foundations</a> is my attempt to provide <strong>simple, reusable .NET foundations</strong> for everyday work:</p>
<ul>
<li><p>Strongly-typed value objects for <strong>email</strong>, <strong>phone numbers</strong>, <strong>names</strong>, <strong>MIME types</strong></p>
</li>
<li><p>A clean <strong>text templating</strong> abstraction</p>
</li>
<li><p>A flexible <strong>emailing</strong> infrastructure</p>
</li>
<li><p>Small, modular packages instead of one big framework</p>
</li>
<li><p>Based on <strong>standards</strong> and compatible with <strong>.NET 8–10</strong></p>
</li>
</ul>
<p>If you are a .NET developer who is tired of rewriting the same value objects and basic infrastructure, I hope these libraries will save you time and bring more consistency to your projects.</p>
<p>If you try them, I would be happy to hear your feedback and suggestions for future improvements.</p>
]]></content:encoded></item><item><title><![CDATA[Simplifying Data Conversion: A Testable Approach for Entity Models and DTOs]]></title><description><![CDATA[In many applications, converting data from one format to another is a common task. For instance, you might need to convert a business entity object into JSON or vice versa. Many developers use extension methods like ToJson() or ToModel() for this con...]]></description><link>https://gilles.tourreau.fr/simplifying-data-conversion-a-testable-approach-for-entity-models-and-dtos</link><guid isPermaLink="true">https://gilles.tourreau.fr/simplifying-data-conversion-a-testable-approach-for-entity-models-and-dtos</guid><category><![CDATA[dto]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[.NET]]></category><category><![CDATA[unit testing]]></category><category><![CDATA[Moq]]></category><dc:creator><![CDATA[Gilles TOURREAU]]></dc:creator><pubDate>Tue, 20 Aug 2024 12:17:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1724153326297/013e52cc-0048-4563-9895-6d53f186052b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In many applications, converting data from one format to another is a common task. For instance, you might need to convert a business entity object into JSON or vice versa. Many developers use extension methods like <code>ToJson()</code> or <code>ToModel()</code> for this conversion, which act on the JSON DTO object model or the entity.</p>
<p>For example, if we have the following business object:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id, <span class="hljs-keyword">string</span> firstName, <span class="hljs-keyword">string</span> lastName</span>)</span>
    {
        <span class="hljs-keyword">this</span>.Id = id;
        <span class="hljs-keyword">this</span>.FirstName = firstName;
        <span class="hljs-keyword">this</span>.LastName = lastName;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Id { <span class="hljs-keyword">get</span>; }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> FirstName { <span class="hljs-keyword">get</span>; }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> LastName { <span class="hljs-keyword">get</span>; }
}
</code></pre>
<p>And the JSON DTO version used to expose it as a Web API:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PersonJson</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PersonJson</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id, <span class="hljs-keyword">string</span> firstName, <span class="hljs-keyword">string</span> lastName</span>)</span>
    {
        <span class="hljs-keyword">this</span>.Id = id;
        <span class="hljs-keyword">this</span>.FirstName = firstName;
        <span class="hljs-keyword">this</span>.LastName = lastName;
    }

    [<span class="hljs-meta">JsonPropertyName(<span class="hljs-meta-string">"id"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Id { <span class="hljs-keyword">get</span>; }

    [<span class="hljs-meta">JsonPropertyName(<span class="hljs-meta-string">"firstName"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> FirstName { <span class="hljs-keyword">get</span>; }

    [<span class="hljs-meta">JsonPropertyName(<span class="hljs-meta-string">"lastName"</span>)</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> LastName { <span class="hljs-keyword">get</span>; }
}
</code></pre>
<p>The extension method that allows converting from <code>Person</code> to <code>PersonJson</code> could look like this:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PersonJsonExtensions</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> PersonJson <span class="hljs-title">ToJson</span>(<span class="hljs-params"><span class="hljs-keyword">this</span> Person person</span>)</span>
    {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> PersonJson(person.Id, person.FirstName, person.LastName);
    }
}
</code></pre>
<p>And the usage inside an ASP.NET Core controller is straightforward:</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">ApiController</span>]
[<span class="hljs-meta">Route(<span class="hljs-meta-string">"persons"</span>)</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PersonController</span> : <span class="hljs-title">ControllerBase</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IPersonManager manager;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PersonController</span>(<span class="hljs-params">IPersonManager manager</span>)</span>
    {
        <span class="hljs-keyword">this</span>.manager = manager;
    }

    [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"byId/{id}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> PersonJson <span class="hljs-title">GetById</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id</span>)</span>
    {
        <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">this</span>.manager.GetByID(id);
        <span class="hljs-keyword">var</span> personJson = person.ToJson();

        <span class="hljs-keyword">return</span> personJson;
    }

    [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"byName/{name}"</span>)</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> PersonJson <span class="hljs-title">GetByName</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> name</span>)</span>
    {
        <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">this</span>.manager.GetByName(name);
        <span class="hljs-keyword">var</span> personJson = person.ToJson();

        <span class="hljs-keyword">return</span> personJson;
    }
}
</code></pre>
<p>However, this approach can complicate unit testing. In this article, I'll explain an alternative method using an interface to decouple the code, which makes testing easier.</p>
<h2 id="heading-the-problem-with-extension-methods">The problem with extension methods</h2>
<p>While this approach works, the problem arises during unit testing. You need to test both the code that retrieves the business entity (the <code>GetById()</code> or <code>GetByName()</code> methods) and the code that converts it to JSON. This makes your tests more complex and harder to maintain.</p>
<p>For example, to test our <code>PersonController</code>, we would write the following unit tests:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PersonControllerTest</span>
{
    [<span class="hljs-meta">Fact</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">GetById</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Arrange</span>
        <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">new</span> Person(<span class="hljs-number">1</span>, <span class="hljs-string">"John"</span>, <span class="hljs-string">"DOE"</span>);

        <span class="hljs-keyword">var</span> manager = <span class="hljs-keyword">new</span> Mock&lt;IPersonManager&gt;(MockBehavior.Strict);
        manager.Setup(m =&gt; m.GetByID(<span class="hljs-number">1234</span>))
            .Returns(person);

        <span class="hljs-keyword">var</span> controller = <span class="hljs-keyword">new</span> PersonController(manager.Object);

        <span class="hljs-comment">// Act</span>
        <span class="hljs-keyword">var</span> json = controller.GetById(<span class="hljs-number">1234</span>);

        json.FirstName.Should().Be(<span class="hljs-string">"John"</span>);
        json.Id.Should().Be(<span class="hljs-number">1</span>);
        json.LastName.Should().Be(<span class="hljs-string">"DOE"</span>);

        <span class="hljs-comment">// Assert</span>
        manager.VerifyAll();
    }

    [<span class="hljs-meta">Fact</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">GetByName</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Arrange</span>
        <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">new</span> Person(<span class="hljs-number">1</span>, <span class="hljs-string">"John"</span>, <span class="hljs-string">"DOE"</span>);

        <span class="hljs-keyword">var</span> manager = <span class="hljs-keyword">new</span> Mock&lt;IPersonManager&gt;(MockBehavior.Strict);
        manager.Setup(m =&gt; m.GetByName(<span class="hljs-string">"Someone"</span>))
            .Returns(person);

        <span class="hljs-keyword">var</span> controller = <span class="hljs-keyword">new</span> PersonController(manager.Object);

        <span class="hljs-comment">// Act</span>
        <span class="hljs-keyword">var</span> json = controller.GetByName(<span class="hljs-string">"Someone"</span>);

        <span class="hljs-comment">// Assert</span>
        json.FirstName.Should().Be(<span class="hljs-string">"John"</span>);
        json.Id.Should().Be(<span class="hljs-number">1</span>);
        json.LastName.Should().Be(<span class="hljs-string">"DOE"</span>);

        manager.VerifyAll();
    }
}
</code></pre>
<p>As you can see, in these unit tests, for each use of the <code>ToJson()</code> extension method, we have to test the mapping of each property. These unit tests are quite simple, but imagine a controller that makes many different calls to the <code>ToJson()</code> extension method, especially if the <code>Person</code>/<code>PersonJson</code> objects have many properties.</p>
<h2 id="heading-the-solution-create-an-external-mapper">The solution: Create an external mapper</h2>
<p>To simplify testing, we can move the conversion logic into a separate class by introducing a simple interface called <code>IPersonJsonMapper</code>. Here's how:</p>
<ol>
<li><p>Define the interface:</p>
<pre><code class="lang-csharp"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title">IPersonJsonMapper</span>
 {
     <span class="hljs-function">PersonJson <span class="hljs-title">ToJson</span>(<span class="hljs-params">Person person</span>)</span>;
 }
</code></pre>
</li>
<li><p>Implement the interface:</p>
<pre><code class="lang-csharp"> <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PersonJsonMapper</span> : <span class="hljs-title">IPersonJsonMapper</span>
 {
     <span class="hljs-function"><span class="hljs-keyword">public</span> PersonJson <span class="hljs-title">ToJson</span>(<span class="hljs-params">Person person</span>)</span>
     {
         <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> PersonJson(person.Id, person.FirstName, person.LastName);
     }
 }
</code></pre>
</li>
<li><p>Use the interface in our controller:</p>
<pre><code class="lang-csharp"> [<span class="hljs-meta">ApiController</span>]
 [<span class="hljs-meta">Route(<span class="hljs-meta-string">"persons"</span>)</span>]
 <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PersonController</span> : <span class="hljs-title">ControllerBase</span>
 {
     <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IPersonManager manager;

     <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> IPersonJsonMapper jsonMapper;

     <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">PersonController</span>(<span class="hljs-params">IPersonManager manager, IPersonJsonMapper jsonMapper</span>)</span>
     {
         <span class="hljs-keyword">this</span>.manager = manager;
         <span class="hljs-keyword">this</span>.jsonMapper = jsonMapper;
     }

     [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"byId/{id}"</span>)</span>]
     <span class="hljs-function"><span class="hljs-keyword">public</span> PersonJson <span class="hljs-title">GetById</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> id</span>)</span>
     {
         <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">this</span>.manager.GetByID(id);
         <span class="hljs-keyword">var</span> personJson = <span class="hljs-keyword">this</span>.jsonMapper.ToJson(person);

         <span class="hljs-keyword">return</span> personJson;
     }

     [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"byName/{name}"</span>)</span>]
     <span class="hljs-function"><span class="hljs-keyword">public</span> PersonJson <span class="hljs-title">GetByName</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> name</span>)</span>
     {
         <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">this</span>.manager.GetByName(name);
         <span class="hljs-keyword">var</span> personJson = <span class="hljs-keyword">this</span>.jsonMapper.ToJson(person);

         <span class="hljs-keyword">return</span> personJson;
     }
 }
</code></pre>
</li>
<li><p>Register the mapper as service in the <code>Program.cs</code> file:</p>
</li>
</ol>
<pre><code class="lang-csharp">builder.Services.AddSingleton&lt;IPersonJsonMapper, PersonJsonMapper&gt;();
</code></pre>
<p>The code of the controller remains as simple as when using the <code>ToJson()</code> extension method, but now the unit test becomes easier:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PersonControllerTest</span>
{
    [<span class="hljs-meta">Fact</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">GetById</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Arrange</span>
        <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">new</span> Person(<span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>);
        <span class="hljs-keyword">var</span> personJson = <span class="hljs-keyword">new</span> PersonJson(<span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>);

        <span class="hljs-keyword">var</span> manager = <span class="hljs-keyword">new</span> Mock&lt;IPersonManager&gt;(MockBehavior.Strict);
        manager.Setup(m =&gt; m.GetByID(<span class="hljs-number">1234</span>))
            .Returns(person);

        <span class="hljs-keyword">var</span> mapper = <span class="hljs-keyword">new</span> Mock&lt;IPersonJsonMapper&gt;(MockBehavior.Strict);
        mapper.Setup(m =&gt; m.ToJson(person))
            .Returns(personJson);

        <span class="hljs-keyword">var</span> controller = <span class="hljs-keyword">new</span> PersonController(manager.Object, mapper.Object);

        <span class="hljs-comment">// Act</span>
        <span class="hljs-keyword">var</span> json = controller.GetById(<span class="hljs-number">1234</span>);

        <span class="hljs-comment">// Assert</span>
        json.Should().BeSameAs(personJson);

        manager.VerifyAll();
        mapper.VerifyAll();
    }

    [<span class="hljs-meta">Fact</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">GetByName</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Arrange</span>
        <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">new</span> Person(<span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>);
        <span class="hljs-keyword">var</span> personJson = <span class="hljs-keyword">new</span> PersonJson(<span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>);

        <span class="hljs-keyword">var</span> manager = <span class="hljs-keyword">new</span> Mock&lt;IPersonManager&gt;(MockBehavior.Strict);
        manager.Setup(m =&gt; m.GetByName(<span class="hljs-string">"Someone"</span>))
            .Returns(person);

        <span class="hljs-keyword">var</span> mapper = <span class="hljs-keyword">new</span> Mock&lt;IPersonJsonMapper&gt;(MockBehavior.Strict);
        mapper.Setup(m =&gt; m.ToJson(person))
            .Returns(personJson);

        <span class="hljs-keyword">var</span> controller = <span class="hljs-keyword">new</span> PersonController(manager.Object, mapper.Object);

        <span class="hljs-comment">// Act</span>
        <span class="hljs-keyword">var</span> json = controller.GetByName(<span class="hljs-string">"Someone"</span>);

        <span class="hljs-comment">// Assert</span>
        json.Should().BeSameAs(personJson);

        manager.VerifyAll();
        mapper.VerifyAll();
    }
}
</code></pre>
<p>As you can see, now we don't need to assert the content of the <code>PersonJson</code> object because it's not the controller's responsibility. Also, I intentionally instantiate the <code>Person</code> and <code>PersonJson</code> objects with default values, since the code being tested will not use them. Of course, we could use a library like <a target="_blank" href="https://github.com/AutoFixture/AutoFixture">AutoFixture</a> to easily instantiate these objects.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> person = <span class="hljs-keyword">new</span> Person(<span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>);
<span class="hljs-keyword">var</span> personJson = <span class="hljs-keyword">new</span> PersonJson(<span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>);
</code></pre>
<h3 id="heading-unit-test-the-mapper">Unit test the mapper</h3>
<p>Even though we don't need to assert the content of the <code>PersonJson</code> instance in the controllers, we should still assert the conversion from a <code>Person</code> instance to a <code>PersonJson</code> by adding a unit test for the <code>PersonJsonMapper</code> class:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">PersonJsonMappingTest</span>
{
    [<span class="hljs-meta">Fact</span>]
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ToJson</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-comment">// Arrange</span>
        <span class="hljs-keyword">var</span> person = <span class="hljs-keyword">new</span> Person(<span class="hljs-number">1234</span>, <span class="hljs-string">"John"</span>, <span class="hljs-string">"DOE"</span>);

        <span class="hljs-keyword">var</span> mapper = <span class="hljs-keyword">new</span> PersonJsonMapper();

        <span class="hljs-comment">// Act</span>
        <span class="hljs-keyword">var</span> json = mapper.ToJson(person);

        <span class="hljs-comment">// Assert</span>
        json.FirstName.Should().Be(<span class="hljs-string">"John"</span>);
        json.Id.Should().Be(<span class="hljs-number">1234</span>);
        json.LastName.Should().Be(<span class="hljs-string">"DOE"</span>);
    }
}
</code></pre>
<h3 id="heading-change-the-implementation-of-the-mapper">Change the implementation of the mapper</h3>
<p>By delegating the conversion to a dedicated class, we can also easily change the implementation using another mapper library, such as <a target="_blank" href="https://docs.automapper.org/">AutoMapper</a>.</p>
<p>Using this approach allows you to change the library or the mapping logic easily without altering the code in the controller.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Delegating data conversion to another class makes your code more testable and maintainable. This approach can be applied at various levels, whether in controllers to convert XML/JSON to entities or in the data access layer for converting Entity Framework entities to business entities. By using this approach, you also respect the "Single Responsibility" principle of the <a target="_blank" href="https://en.wikipedia.org/wiki/SOLID">S.O.L.I.D. principles</a>.</p>
<p>A complete example of the source of this article is available within one of my public GitHub projects: GillesTourreau/<a target="_blank" href="https://github.com/GillesTourreau/GillesTourreau.ModelMapper">GillesTourreau.ModelMapper</a><a target="_blank" href="https://github.com/GillesTourreau/GillesTourreau.ModelMapper">: Example project to delegate the conversion of entity model to JSON in other class (github.com).</a></p>
]]></content:encoded></item><item><title><![CDATA[Change the ClaimsIdentity.AuthenticationType in ASP.NET Core with multiple Entra ID schemes.]]></title><description><![CDATA[Introduction
When building modern web applications, security is always a top priority. In ASP.NET Core, authentication is a key part of ensuring that only authorized users can access specific parts of your application. You may often need to support m...]]></description><link>https://gilles.tourreau.fr/change-the-claims-identity-authentication-type-in-aspnet-core-with-multiple-entra-id-schemes</link><guid isPermaLink="true">https://gilles.tourreau.fr/change-the-claims-identity-authentication-type-in-aspnet-core-with-multiple-entra-id-schemes</guid><category><![CDATA[Claims Identity]]></category><category><![CDATA[.NET]]></category><category><![CDATA[Entra ID]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[authentication]]></category><category><![CDATA[Microsoft]]></category><dc:creator><![CDATA[Gilles TOURREAU]]></dc:creator><pubDate>Fri, 16 Aug 2024 11:02:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/RMIsZlv8qv4/upload/9229558c6b5e71abf19064bd4182c3c9.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction">Introduction</h3>
<p>When building modern web applications, security is always a top priority. In ASP.NET Core, authentication is a key part of ensuring that only authorized users can access specific parts of your application. You may often need to support multiple authentication schemes, such as different Azure Entra ID (formerly Azure AD) configurations, within the same application.</p>
<p>One challenge when using multiple authentication schemes is identifying which scheme authenticated a user. This is where the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype?view=net-8.0"><code>ClaimsIdentity.AuthenticationType</code></a> property comes into play. Setting this property correctly can help you easily determine the authentication source for a user.</p>
<h3 id="heading-understanding-httpcontextuser">Understanding <code>HttpContext.User</code></h3>
<p>In ASP.NET Core, the <code>HttpContext.User</code> property represents the current authenticated user. This user is represented by a <code>ClaimsPrincipal</code> object, which contains one or more <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity?view=net-8.0"><code>ClaimsIdentity</code></a> objects. Each <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity?view=net-8.0"><code>ClaimsIdentity</code></a> represents a specific identity associated with the user, such as a name, roles, and other claims.</p>
<p>By default, the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype?view=net-8.0"><code>AuthenticationType</code></a> is set to <code>"AuthenticationTypes.Federation"</code>. However, when working with multiple authentication schemes, you might want to know exactly which authentication scheme was used to create a particular <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity?view=net-8.0"><code>ClaimsIdentity</code></a>. This is where setting a custom <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype"><code>AuthenticationType</code></a> can be very useful.</p>
<p>For example, let’s say you want to retrieve the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype"><code>AuthenticationType</code></a> of the currently authenticated user to determine how they were authenticated:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">GetAuthenticationType</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">var</span> identity = HttpContext.User.Identity <span class="hljs-keyword">as</span> ClaimsIdentity;

    <span class="hljs-keyword">if</span> (identity != <span class="hljs-literal">null</span>)
    {
        <span class="hljs-keyword">string</span> authenticationType = identity.AuthenticationType;
        <span class="hljs-keyword">return</span> Ok(<span class="hljs-string">$"User authenticated using: <span class="hljs-subst">{authenticationType}</span>"</span>);
    }

    <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-string">"No identity found."</span>);
}
</code></pre>
<p>This example demonstrates how you can access the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype"><code>AuthenticationType</code></a> in your controller to gain insights into the user's authentication method.</p>
<h3 id="heading-the-problem-with-multiple-authentication-schemes">The Problem with Multiple Authentication Schemes</h3>
<p>When you have multiple authentication schemes, such as two different configurations for Azure Entra ID, it's not always clear which scheme authenticated the user. Without setting the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype"><code>AuthenticationType</code></a>, you may not be able to distinguish between the identities created by different schemes. This can be problematic in scenarios where your application's logic depends on the authentication source.</p>
<h3 id="heading-setting-the-authenticationtype">Setting the <code>AuthenticationType</code></h3>
<p>To set the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype"><code>AuthenticationType</code></a> in ASP.NET Core, you need to configure it in the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters"><code>TokenValidationParameters</code></a> when setting up your authentication schemes. The <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters.authenticationtype"><code>TokenValidationParameters.AuthenticationType</code></a> property allows you to specify a unique identifier for the authentication scheme, which is then assigned to the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype"><code>ClaimsIdentity.AuthenticationType</code></a>.</p>
<p>For example, let's say you have two Azure Entra ID configurations: one for internal users and another for external partners. You can set up your authentication schemes as follows:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">ConfigureServices</span>(<span class="hljs-params">IServiceCollection services</span>)</span>
{
    <span class="hljs-comment">// Internal users authentication scheme</span>
    services.AddAuthentication(<span class="hljs-string">"InternalScheme"</span>)
        .AddMicrosoftIdentityWebApi(options =&gt;
        {
            options.Instance = <span class="hljs-string">"https://login.microsoftonline.com/"</span>;
            options.Domain = <span class="hljs-string">"internaldomain.com"</span>;
            options.ClientId = <span class="hljs-string">"your-client-id"</span>;
            options.TenantId = <span class="hljs-string">"your-tenant-id"</span>;

            <span class="hljs-comment">// Set the AuthenticationType for the internal scheme</span>
            options.TokenValidationParameters.AuthenticationType = <span class="hljs-string">"Internal"</span>;
        });

    <span class="hljs-comment">// External partners authentication scheme</span>
    services.AddAuthentication(<span class="hljs-string">"ExternalScheme"</span>)
        .AddMicrosoftIdentityWebApi(options =&gt;
        {
            options.Instance = <span class="hljs-string">"https://login.microsoftonline.com/"</span>;
            options.Domain = <span class="hljs-string">"externaldomain.com"</span>;
            options.ClientId = <span class="hljs-string">"your-client-id"</span>;
            options.TenantId = <span class="hljs-string">"your-tenant-id"</span>;

            <span class="hljs-comment">// Set the AuthenticationType for the external scheme</span>
            options.TokenValidationParameters.AuthenticationType = <span class="hljs-string">"External"</span>;
        });
}
</code></pre>
<h3 id="heading-retrieving-the-authenticationtype">Retrieving the <code>AuthenticationType</code></h3>
<p>Now that you've configured the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.security.claims.claimsidentity.authenticationtype"><code>AuthenticationType</code></a> for each scheme, you can retrieve it later in your code to determine which scheme authenticated the user:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> IActionResult <span class="hljs-title">GetUserIdentity</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">var</span> identity = HttpContext.User.Identity <span class="hljs-keyword">as</span> ClaimsIdentity;

    <span class="hljs-keyword">if</span> (identity != <span class="hljs-literal">null</span>)
    {
        <span class="hljs-keyword">string</span> authenticationType = identity.AuthenticationType;
        <span class="hljs-keyword">return</span> Ok(<span class="hljs-string">$"User authenticated using: <span class="hljs-subst">{authenticationType}</span>"</span>);
    }

    <span class="hljs-keyword">return</span> BadRequest(<span class="hljs-string">"No identity found."</span>);
}
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>By setting the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters.authenticationtype"><code>AuthenticationType</code></a> in the <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.identitymodel.tokens.tokenvalidationparameters"><code>TokenValidationParameters</code></a>, you can clearly distinguish between different authentication schemes in ASP.NET Core. This approach is especially useful when your application needs to support multiple authentication sources, such as different Azure Entra ID configurations. With this setup, you'll be able to write more precise and secure authentication logic in your application.</p>
]]></content:encoded></item><item><title><![CDATA[Strengthening Moq based unit tests with PosInformatique.Moq.Analyzers]]></title><description><![CDATA[As a passionate advocate for robust unit testing and code quality, I've invested heavily in leveraging the Moq library within my .NET projects. To ensure reliability and catch potential errors early, I developed a .NET analyzer tool specifically tail...]]></description><link>https://gilles.tourreau.fr/strengthening-moq-based-unit-tests-with-posinformatiquemoqanalyzers</link><guid isPermaLink="true">https://gilles.tourreau.fr/strengthening-moq-based-unit-tests-with-posinformatiquemoqanalyzers</guid><category><![CDATA[.NET]]></category><category><![CDATA[C#]]></category><category><![CDATA[roslyn]]></category><category><![CDATA[Moq]]></category><category><![CDATA[unit testing]]></category><category><![CDATA[Nuget]]></category><category><![CDATA[Code Quality]]></category><category><![CDATA[code analyzer]]></category><dc:creator><![CDATA[Gilles TOURREAU]]></dc:creator><pubDate>Tue, 05 Dec 2023 20:32:24 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/wt5jg8_WrJg/upload/2dea33f8e7322d44c5cc4b4d1b8c4545.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a passionate advocate for robust unit testing and code quality, I've invested heavily in leveraging the <a target="_blank" href="https://github.com/devlooped/moq">Moq</a> library within my .NET projects. To ensure reliability and catch potential errors early, I developed a .NET analyzer tool specifically tailored for Moq based unit tests. This analyzer is called <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Moq.Analyzers">PosInformatique.Moq.Analyzers</a> and available on <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Moq.Analyzers">nuget.org</a> web site.</p>
<h3 id="heading-origin-and-purpose"><strong>Origin and Purpose</strong></h3>
<p>This analyzer was born from the need to fortify unit tests by detecting discrepancies during the coding phase. I wanted to preemptively identify errors in my <a target="_blank" href="https://github.com/devlooped/moq">Moq</a> based tests to ensure their coherence and correctness.</p>
<p>For that I used the .NET Compiler Platform SDK to create an analyzer packaged inside a NuGet package.</p>
<h3 id="heading-whats-new-in-the-version-130"><strong>What's new in the version 1.3.0?</strong></h3>
<p>The recent release, version <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Moq.Analyzers/1.3.0">1.3.0</a>, brings a significant advancement: the <a target="_blank" href="https://posinformatique.github.io/PosInformatique.Moq.Analyzers/docs/Compilation/PosInfoMoq2003.html">PosInfoMoq2003</a> rule. This rule inspects method signature within <code>Callback()</code> to validate their alignment with <code>Setup()</code> method.</p>
<p>For exemple, in the following mocked method <code>UpdateAsync()</code>, the analyzer check that the <code>Callback()</code> method take a lambda expression with exactly the same signature.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> repository = <span class="hljs-keyword">new</span> Mock&lt;ITaskRepository&gt;(MockBehavior.Strict);
repository.Setup(r =&gt; r.UpdateAsync(task, It.IsAny&lt;TaskChangeTracking&gt;()))
    .Callback((TaskUpdate _, TaskChangeTracking updated) =&gt;
    {
        updated.DateTime.Should().Be(<span class="hljs-keyword">new</span> DateTime(<span class="hljs-number">2023</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>)).And.BeIn(DateTimeKind.Utc);
        updated.UserId.Should().Be(<span class="hljs-string">"55555555-5555-5555-5555-555555555555"</span>);
    })
    .Returns(Task.CompletedTask);
</code></pre>
<p>This enhancement significantly boosts the analyzer's ability to ensure method coherence within Moq setups.</p>
<h3 id="heading-a-quick-recap-of-the-previous-versions"><strong>A quick recap of the previous versions</strong></h3>
<p>Let's recall the enhancements of the previous versions. They introduced rules like <a target="_blank" href="https://posinformatique.github.io/PosInformatique.Moq.Analyzers/docs/Design/PosInfoMoq1000.html">PosInfoMoq1000</a> and <a target="_blank" href="https://posinformatique.github.io/PosInformatique.Moq.Analyzers/docs/Design/PosInfoMoq1001.html">PosInfoMoq1001</a>, emphasizing the importance of invoking <code>Verify()</code> or <code>VerifyAll()</code> methods and defining <code>Mock&lt;T&gt;</code> instances to <code>Strict</code> mode.</p>
<p>Also, other additional rules was added, to perform immediate <strong>compilation validation</strong>, aiming to catch errors before runtime execution, ensuring higher code quality and mitigating potential issues during the testing phase.</p>
<ul>
<li><p><a target="_blank" href="https://posinformatique.github.io/PosInformatique.Moq.Analyzers/docs/Compilation/PosInfoMoq2000.html">PosInfoMoq2000</a>: Requires the use of <code>Returns()</code> or <code>ReturnsAsync()</code> methods for <code>Strict</code> mocks. This rule ensures that when defining a <code>Mock&lt;T&gt;</code> with <code>Strict</code> behavior, these methods are invoked when setting up a method to mock returning a value.</p>
</li>
<li><p><a target="_blank" href="https://posinformatique.github.io/PosInformatique.Moq.Analyzers/docs/Compilation/PosInfoMoq2001.html">PosInfoMoq2001</a>: Check the usage of the <code>Setup()</code> method to be use on overridable members (not extension method, not sealed).</p>
</li>
<li><p><a target="_blank" href="https://posinformatique.github.io/PosInformatique.Moq.Analyzers/docs/Compilation/PosInfoMoq2002.html">PosInfoMoq2002</a><strong>:</strong> Specifies that the <code>Mock&lt;T&gt;</code> class can only be used to mock non-sealed classes (interfaces of abstract classes).</p>
</li>
</ul>
<p>For instance, this is a simple unit test which matches four of the previous rules of the <a target="_blank" href="https://www.nuget.org/packages/PosInformatique.Moq.Analyzers">PosInformatique.Moq.Analyzers</a> analyzer.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">Fact</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">GetAsync</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">var</span> visits = <span class="hljs-keyword">new</span>[]
    {
        <span class="hljs-keyword">new</span> Visit(<span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>, <span class="hljs-keyword">default</span>),
    };

    <span class="hljs-keyword">var</span> manager = <span class="hljs-keyword">new</span> Mock&lt;IVisitManager&gt;(MockBehavior.Strict);  <span class="hljs-comment">// PosInfoMoq1001 : Check that mock are defined to Strict mode.</span>
    manager.Setup(m =&gt; m.FindAsync(It.IsAny&lt;VisitQuery&gt;()))
        .Callback((VisitQuery q) =&gt;  <span class="hljs-comment">// PosInfoMoq2003: Check the signature to match with the Setup() mocked method.</span>
        {
            q.Should().BeEquivalentTo(<span class="hljs-keyword">new</span> VisitQuery()
            {
                Id = <span class="hljs-keyword">new</span> Guid(<span class="hljs-string">"11111111-1111-1111-1111-111111111111"</span>),
            });
        })
        .ReturnsAsync(visits);  <span class="hljs-comment">// PosInfoMoq2000: Returns() or ReturnsAsync() is required.</span>

    <span class="hljs-keyword">var</span> result = <span class="hljs-keyword">await</span> manager.Object.GetAsync(<span class="hljs-keyword">new</span> Guid(<span class="hljs-string">"11111111-1111-1111-1111-111111111111"</span>));

    result.Should().BeSameAs(visits[<span class="hljs-number">0</span>]);

    manager.VerifyAll();  <span class="hljs-comment">// PosInfoMoq1000 : Check that the Verify() / VerifyAll() method is called in the unit test.</span>
}
</code></pre>
<p>For detailed installation instructions and a comprehensive list of rules, refer to the official documentation available on the <a target="_blank" href="https://posinformatique.github.io/PosInformatique.Moq.Analyzers/">github.io website</a>.</p>
<h3 id="heading-useful-links"><strong>Useful Links</strong></h3>
<ul>
<li><p><strong>Official Documentation:</strong> Access the detailed documentation for <a target="_blank" href="https://posinformatique.github.io/PosInformatique.Moq.Analyzers/">PosInformatique.Moq.Analyzers</a>.</p>
</li>
<li><p><strong>GitHub Repository:</strong> Explore and contribute to the analyzer's development on <a target="_blank" href="https://github.com/PosInformatique/PosInformatique.Moq.Analyzers">PosInformatique.Moq.Analyzers GitHub repository</a>.</p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Detect ongoing .NET exceptions]]></title><description><![CDATA[Sometimes it can be useful to detect if an exception is ongoing.
For instance, in a Dispose() method, it's valuable to ascertain if an exception is already in progress to avoid throwing a new exception and losing the original one.
Problem encountered...]]></description><link>https://gilles.tourreau.fr/detect-ongoing-net-exceptions</link><guid isPermaLink="true">https://gilles.tourreau.fr/detect-ongoing-net-exceptions</guid><category><![CDATA[.NET]]></category><category><![CDATA[exceptions]]></category><category><![CDATA[trycatch]]></category><category><![CDATA[C#]]></category><dc:creator><![CDATA[Gilles TOURREAU]]></dc:creator><pubDate>Mon, 04 Dec 2023 14:38:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/SP5odY8jGLA/upload/bcbbb67bc04004c3d76bff0f773d4fbe.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Sometimes it can be useful to detect if an exception is ongoing.</p>
<p>For instance, in a <code>Dispose()</code> method, it's valuable to ascertain if an exception is already in progress to avoid throwing a new exception and losing the original one.</p>
<h1 id="heading-problem-encountered">Problem encountered</h1>
<p>I encountered this issue in a complex scenario within my unit tests. In a mocked <code>Dispose()</code> method, I aimed to throw an exception if an assertion had failed. However, the problem arose when an exception occurred within a using block of my disposable object, triggering the <code>Dispose()</code> method. This prevented me from retrieving the original exception in the log during the unit test execution in the CI process.</p>
<blockquote>
<p><strong>NOTE:</strong> Belong the Microsoft <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1065">CA1065 recommandation</a>, a <code>Dispose()</code> method must not throw an exception.</p>
</blockquote>
<p>Below is a simplified example code depicting this scenario:</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyCode</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Example</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> obj = <span class="hljs-keyword">new</span> DisposableObject())
        {
            <span class="hljs-keyword">var</span> divisor = <span class="hljs-number">0</span>;
            <span class="hljs-keyword">var</span> result = <span class="hljs-number">10</span> / divisor;
        }
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">DisposableObject</span> : <span class="hljs-title">IDisposable</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">bool</span> methodCalled;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CallBeforeDispose</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">this</span>.methodCalled = <span class="hljs-literal">true</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Dispose</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.methodCalled)
        {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> XunitException(<span class="hljs-string">"The CallBeforeDispose() has not been called."</span>);
        }
    }
}
</code></pre>
<p>As you can see, the <code>Example()</code> method will throw an exception because we did not call the <code>CallBeforeDispose()</code> method. In this scenario, an exception is thrown inside the <code>using</code> block code, leading to the invocation of the <code>Dispose()</code> method of the <code>DisposableObject</code>. This invocation will raise another <code>XunitException</code> exception. Consequently, in this situation, we will lose the original <code>DivideByZeroException</code> exception.</p>
<h1 id="heading-the-marshalgetexceptionpointers-method">The Marshal.GetExceptionPointers() method.</h1>
<p>To determine if an exception is ongoing, the .NET provides a straightforward static method called <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getexceptionpointers">Marshal.GetExceptionPointers()</a> which returns an unmanaged pointer to the ongoing exception.</p>
<ul>
<li><p>A zero pointer returned by this method indicates that no exception is ongoing.</p>
</li>
<li><p>Conversely, a non-zero pointer returned by the method indicates an ongoing exception.</p>
</li>
</ul>
<p>We can leverage this behavior to detect if an exception is ongoing within our <code>Dispose()</code> method:</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Dispose</span>(<span class="hljs-params"></span>)</span>
{
    <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.methodCalled)
    {
        <span class="hljs-comment">// Do not thrown an exception, if an exception is currently ongoing.</span>
        <span class="hljs-keyword">if</span> (Marshal.GetExceptionPointers() == IntPtr.Zero)
        {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> XunitException(<span class="hljs-string">"The CallBeforeDispose() has not been called."</span>);
        }
    }
}
</code></pre>
<h1 id="heading-net-standard-and-marshalgetexceptionpointers">.NET Standard and Marshal.GetExceptionPointers()</h1>
<p>If you refer to the table "Applies to" table at the bottom of <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getexceptionpointers?view=net-8.0#applies-to">Marshal.GetExceptionPointers() documentation page</a>, you'll notice that this method is available in .NET Core and .NET Framework libraries but not in the .NET Standard.</p>
<p>To overcome this limitation, we simply employ reflection to access the static <code>GetExceptionPointers()</code> method within the <code>Marshal</code> class.</p>
<p>I've created a straightforward helper class that can be utilized in projects targeting both .NET Standard and non-.NET Standard frameworks (especially useful for building libraries intended for various frameworks).</p>
<p>When incorporating the helper into a .NET Standard library, I use expressions to dynamically compile a call, avoiding reflection and enhancing performance when invoking the <code>IsExceptionOnGoing()</code> method.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> NETSTANDARD</span>
<span class="hljs-keyword">using</span> System.Linq.Expressions;
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
<span class="hljs-keyword">using</span> System.Runtime.InteropServices;

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ExceptionHelper</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">bool</span> <span class="hljs-title">IsExceptionOnGoing</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">var</span> ptr = GetExceptionPointers();

        <span class="hljs-keyword">if</span> (ptr == IntPtr.Zero)
        {
            <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
        }

        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    }

<span class="hljs-meta">#<span class="hljs-meta-keyword">if</span> NETSTANDARD</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">readonly</span> Func&lt;IntPtr&gt; GetExceptionPointers = BuildGetExceptionPointersFunc();

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Func&lt;IntPtr&gt; <span class="hljs-title">BuildGetExceptionPointersFunc</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">var</span> memberAccess = Expression.Call(<span class="hljs-keyword">typeof</span>(Marshal).GetMethod(<span class="hljs-string">"GetExceptionPointers"</span>));

        <span class="hljs-keyword">var</span> lambda = Expression.Lambda&lt;Func&lt;IntPtr&gt;&gt;(memberAccess);

        <span class="hljs-keyword">return</span> lambda.Compile();
    }
<span class="hljs-meta">#<span class="hljs-meta-keyword">else</span></span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> IntPtr <span class="hljs-title">GetExceptionPointers</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">return</span> Marshal.GetExceptionPointers();
    }
<span class="hljs-meta">#<span class="hljs-meta-keyword">endif</span></span>
}
</code></pre>
<p>A complete example of this helper class is available within one of my public GitHub projects: <a target="_blank" href="https://github.com/GillesTourreau/GillesTourreau.AmbientException">GillesTourreau/GillesTourreau.AmbientException: Example and helper class to detect ongoing .NET exceptions (github.com)</a></p>
]]></content:encoded></item><item><title><![CDATA[Revived and Tech-Ready: A New Blog Era Begins!]]></title><description><![CDATA[Hey there, everyone!
I've hit refresh on my blog, clearing out the cobwebs of a site stuck in 2014! For those familiar with my old space, it's time for a brand-new journey. This blog remains dedicated to Microsoft technologies – delving deep into the...]]></description><link>https://gilles.tourreau.fr/revived-and-tech-ready-a-new-blog-era-begins</link><guid isPermaLink="true">https://gilles.tourreau.fr/revived-and-tech-ready-a-new-blog-era-begins</guid><category><![CDATA[.NET]]></category><category><![CDATA[Azure]]></category><dc:creator><![CDATA[Gilles TOURREAU]]></dc:creator><pubDate>Sun, 03 Dec 2023 23:35:26 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/1SsUquHPNT8/upload/085780c3712bd3235ced838b0e32b91d.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey there, everyone!</p>
<p>I've hit refresh on my blog, clearing out the cobwebs of a site stuck in 2014! For those familiar with my old space, it's time for a brand-new journey. This blog remains dedicated to Microsoft technologies – delving deep into the realms of .NET and Azure.</p>
<p>Why the reboot? It's simple. My burning desire lies in sharing. I'm passionate about unraveling the intricacies of my daily tech encounters, the problems I solve, and the knowledge I gather. And when it comes to crafting articles, HashCode has become my trusty companion, speeding up the process compared to WordPress.</p>
<p>One significant change – while the previous blog was in French, this time, it's all about English. Here's to a new language and a fresh tech adventure!</p>
<p>Let's dive in together!</p>
<p>PS: Don't hesitate to join me on this journey. Let's dive in together!</p>
]]></content:encoded></item></channel></rss>