<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>ASP.net on Techformist</title>
    <link>https://techformist.com/categories/asp.net/</link>
    <description>Recent content in ASP.net on Techformist</description>
    <image>
      <url>https://techformist.com/logo.svg</url>
      <link>https://techformist.com/logo.svg</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Tue, 01 Oct 2024 06:30:00 +0000</lastBuildDate><atom:link href="https://techformist.com/categories/asp.net/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Identity in .NET API Makes Auth Easy</title>
      <link>https://techformist.com/2024-10-01-identity-dotnet-api-auth-made-easy/</link>
      <pubDate>Tue, 01 Oct 2024 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/2024-10-01-identity-dotnet-api-auth-made-easy/</guid>
      <description>&lt;p&gt;There was a time to be scared of the auth in ASP.NET. Identity really makes it easy.
But before delving any further, let&amp;rsquo;s keep the tradition alive by knowing the ancient Roman history of auth in ASP.NET.&lt;/p&gt;
&lt;h2 id=&#34;how-auth-was-done-earlier&#34;&gt;How Auth was done earlier?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Manual Token Generation: Developers manually created JWT tokens using libraries like System.IdentityModel.Tokens.Jwt and hardcoded key management.&lt;/li&gt;
&lt;li&gt;No Built-in User Management: Handling user registration, login, password hashing, and role management required custom code.&lt;/li&gt;
&lt;li&gt;Manual Claims Management: Claims (roles, permissions) were added to JWT tokens manually, increasing the risk of errors.&lt;/li&gt;
&lt;li&gt;Token Validation: Developers manually validated JWT tokens in each request, including signature, expiration, and claims validation.&lt;/li&gt;
&lt;li&gt;No Built-in Features for Role Management: Handling user roles and claims for authorization were complex&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s not uncommon to see code like this even today (there continue to be valid use cases, of course).&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>There was a time to be scared of the auth in ASP.NET. Identity really makes it easy.
But before delving any further, let&rsquo;s keep the tradition alive by knowing the ancient Roman history of auth in ASP.NET.</p>
<h2 id="how-auth-was-done-earlier">How Auth was done earlier?</h2>
<ul>
<li>Manual Token Generation: Developers manually created JWT tokens using libraries like System.IdentityModel.Tokens.Jwt and hardcoded key management.</li>
<li>No Built-in User Management: Handling user registration, login, password hashing, and role management required custom code.</li>
<li>Manual Claims Management: Claims (roles, permissions) were added to JWT tokens manually, increasing the risk of errors.</li>
<li>Token Validation: Developers manually validated JWT tokens in each request, including signature, expiration, and claims validation.</li>
<li>No Built-in Features for Role Management: Handling user roles and claims for authorization were complex</li>
</ul>
<p>It&rsquo;s not uncommon to see code like this even today (there continue to be valid use cases, of course).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">key</span> <span class="p">=</span> <span class="k">new</span> <span class="n">SymmetricSecurityKey</span><span class="p">(</span><span class="n">Encoding</span><span class="p">.</span><span class="n">UTF8</span><span class="p">.</span><span class="n">GetBytes</span><span class="p">(</span><span class="s">&#34;YourSecretKey&#34;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">creds</span> <span class="p">=</span> <span class="k">new</span> <span class="n">SigningCredentials</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">SecurityAlgorithms</span><span class="p">.</span><span class="n">HmacSha256</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">claims</span> <span class="p">=</span> <span class="k">new</span><span class="p">[]</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">new</span> <span class="n">Claim</span><span class="p">(</span><span class="n">JwtRegisteredClaimNames</span><span class="p">.</span><span class="n">Sub</span><span class="p">,</span> <span class="s">&#34;username&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="k">new</span> <span class="n">Claim</span><span class="p">(</span><span class="n">JwtRegisteredClaimNames</span><span class="p">.</span><span class="n">Jti</span><span class="p">,</span> <span class="n">Guid</span><span class="p">.</span><span class="n">NewGuid</span><span class="p">().</span><span class="n">ToString</span><span class="p">())</span>
</span></span><span class="line"><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">token</span> <span class="p">=</span> <span class="k">new</span> <span class="n">JwtSecurityToken</span><span class="p">(</span>
</span></span><span class="line"><span class="cl">    <span class="n">issuer</span><span class="p">:</span> <span class="s">&#34;yourdomain.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">audience</span><span class="p">:</span> <span class="s">&#34;yourdomain.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">claims</span><span class="p">:</span> <span class="n">claims</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="n">expires</span><span class="p">:</span> <span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">.</span><span class="n">AddMinutes</span><span class="p">(</span><span class="m">30</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">    <span class="n">signingCredentials</span><span class="p">:</span> <span class="n">creds</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// create token</span>
</span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">tokenString</span> <span class="p">=</span> <span class="k">new</span> <span class="n">JwtSecurityTokenHandler</span><span class="p">().</span><span class="n">WriteToken</span><span class="p">(</span><span class="n">token</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// time passes..</span>
</span></span><span class="line"><span class="cl"><span class="c1">//</span>
</span></span><span class="line"><span class="cl"><span class="c1">// time now to validate in another part of the code..</span>
</span></span><span class="line"><span class="cl"><span class="c1">// validate token</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">services</span><span class="p">.</span><span class="n">AddAuthentication</span><span class="p">(</span><span class="n">options</span> <span class="p">=&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">options</span><span class="p">.</span><span class="n">DefaultAuthenticateScheme</span> <span class="p">=</span> <span class="n">JwtBearerDefaults</span><span class="p">.</span><span class="n">AuthenticationScheme</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">options</span><span class="p">.</span><span class="n">DefaultChallengeScheme</span> <span class="p">=</span> <span class="n">JwtBearerDefaults</span><span class="p">.</span><span class="n">AuthenticationScheme</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">})</span>
</span></span><span class="line"><span class="cl">    <span class="p">.</span><span class="n">AddJwtBearer</span><span class="p">(</span><span class="n">options</span> <span class="p">=&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">options</span><span class="p">.</span><span class="n">TokenValidationParameters</span> <span class="p">=</span> <span class="k">new</span> <span class="n">TokenValidationParameters</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">ValidateIssuer</span> <span class="p">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ValidateAudience</span> <span class="p">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ValidateLifetime</span> <span class="p">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ValidateIssuerSigningKey</span> <span class="p">=</span> <span class="kc">true</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ValidIssuer</span> <span class="p">=</span> <span class="s">&#34;yourdomain.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">ValidAudience</span> <span class="p">=</span> <span class="s">&#34;yourdomain.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="n">IssuerSigningKey</span> <span class="p">=</span> <span class="k">new</span> <span class="n">SymmetricSecurityKey</span><span class="p">(</span><span class="n">Encoding</span><span class="p">.</span><span class="n">UTF8</span><span class="p">.</span><span class="n">GetBytes</span><span class="p">(</span><span class="s">&#34;YourSecretKey&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span></code></pre></div><h2 id="roll-in-identity">Roll-in Identity</h2>
<ul>
<li>Built-in User and Role Management
<ul>
<li>Identity provides a complete user management system with built-in support for user registration, login, password hashing, and role management.</li>
<li>No need to manually store user credentials or roles in the database; Identity handles it through its own entity models (e.g., IdentityUser, IdentityRole).</li>
</ul>
</li>
<li>Automatic Token Generation and Validation
<ul>
<li>Identity integrates easily with JWT authentication, automatically handling token generation, validation, and expiration management.</li>
<li>Developers no longer need to manually create or validate tokens using JwtSecurityTokenHandler.</li>
</ul>
</li>
<li>Claims and Role Management: Manage claims and roles through simple, high-level APIs (UserManager, RoleManager), which abstract away the complexity of managing claims in the token payload manually.</li>
<li>Out-of-the-Box (&ldquo;OOB&rdquo;) Security
<ul>
<li>OOB industry-standard security practices such as password hashing (with customizable password policies) and token expiration management - reduce security risks.</li>
<li>Built-in support for multi-factor authentication (MFA), account lockout, and password recovery without custom implementations.</li>
</ul>
</li>
<li>Simplified Middleware Integration
<ul>
<li>Easily integrated into the ASP.NET middleware pipeline - no need to manually configure authentication schemes or token validation parameters.</li>
<li>Built-in Identity middleware automatically manages authentication cookies and tokens.</li>
</ul>
</li>
<li>Flexible Data Store: Work with multiple data stores (SQL Server, MySQL, etc.) by default</li>
<li>Support for External Authentication Providers: Integrating OAuth providers like Google, Facebook, and Microsoft is simplified</li>
</ul>
<h2 id="identity-in-action-a-simple-demo">Identity in Action: A Simple Demo</h2>
<p>Create a new project..</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">dotnet new webapi -n dotnet-api-auth-demo
</span></span></code></pre></div><p>Add the below packages..</p>
<ul>
<li>Microsoft.EntityFrameworkCore.Sqlite</li>
<li>Microsoft.EntityFrameworkCore.Design</li>
<li>Microsoft.EntityFrameworkCore.Tools</li>
<li>Microsoft.AspNetCore.Identity.EntityFrameworkCore</li>
</ul>
<p>The first three are for Entity Framework Core and for using a SQLite database. The last one is for Identity.</p>
<p>Create the <code>ApplicationDbContext</code> class like as God intended. However, inherit from <code>IdentityDbContext</code> this time.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">Microsoft.AspNetCore.Identity</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">Microsoft.AspNetCore.Identity.EntityFrameworkCore</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">using</span> <span class="nn">Microsoft.EntityFrameworkCore</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">public</span> <span class="k">class</span> <span class="nc">ApplicationDbContext</span> <span class="p">:</span> <span class="n">IdentityDbContext</span><span class="p">&lt;</span><span class="n">IdentityUser</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">public</span> <span class="n">ApplicationDbContext</span><span class="p">(</span><span class="n">DbContextOptions</span><span class="p">&lt;</span><span class="n">ApplicationDbContext</span><span class="p">&gt;</span> <span class="n">options</span><span class="p">)</span> <span class="p">:</span> <span class="k">base</span><span class="p">(</span><span class="n">options</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p><code>IdentityDbContext</code> will add magic that we are about to experience.</p>
<p>Add three lines of code in <code>Program.cs</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="n">builder</span><span class="p">.</span><span class="n">Services</span><span class="p">.</span><span class="n">AddAuthorization</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">builder</span><span class="p">.</span><span class="n">Services</span><span class="p">.</span><span class="n">AddIdentityApiEndpoints</span><span class="p">&lt;</span><span class="n">IdentityUser</span><span class="p">&gt;().</span><span class="n">AddEntityFrameworkStores</span><span class="p">&lt;</span><span class="n">ApplicationDbContext</span><span class="p">&gt;();</span>
</span></span><span class="line"><span class="cl"><span class="c1">// add the above lines before initializing `app`</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">app</span> <span class="p">=</span> <span class="n">builder</span><span class="p">.</span><span class="n">Build</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// add the below line after `app` is initialized</span>
</span></span><span class="line"><span class="cl"><span class="n">app</span><span class="p">.</span><span class="n">MapIdentityApi</span><span class="p">&lt;</span><span class="n">IdentityUser</span><span class="p">&gt;();</span>
</span></span></code></pre></div><ul>
<li><code>AddEntityFrameworkStores</code> shows which database to use. In this case, we are using SQLite and using the main <code>ApplicationDbContext</code> itself. We could have used a different auth database as easily.</li>
<li><code>MapIdentityApi</code> automatically adds the necessary routes for Identity.</li>
</ul>
<p>Since we have no other endpoints, add auth to the default <code>weatherforecast</code> endpoint using <code>RequireAuthorization()</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="n">app</span><span class="p">.</span><span class="n">MapGet</span><span class="p">(</span><span class="s">&#34;/weatherforecast&#34;</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kt">var</span> <span class="n">forecast</span> <span class="p">=</span> <span class="n">Enumerable</span><span class="p">.</span><span class="n">Range</span><span class="p">(</span><span class="m">1</span><span class="p">,</span> <span class="m">5</span><span class="p">).</span><span class="n">Select</span><span class="p">(</span><span class="n">index</span> <span class="p">=&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="k">new</span> <span class="n">WeatherForecast</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span>
</span></span><span class="line"><span class="cl">            <span class="n">DateOnly</span><span class="p">.</span><span class="n">FromDateTime</span><span class="p">(</span><span class="n">DateTime</span><span class="p">.</span><span class="n">Now</span><span class="p">.</span><span class="n">AddDays</span><span class="p">(</span><span class="n">index</span><span class="p">)),</span>
</span></span><span class="line"><span class="cl">            <span class="n">Random</span><span class="p">.</span><span class="n">Shared</span><span class="p">.</span><span class="n">Next</span><span class="p">(-</span><span class="m">20</span><span class="p">,</span> <span class="m">55</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">            <span class="n">summaries</span><span class="p">[</span><span class="n">Random</span><span class="p">.</span><span class="n">Shared</span><span class="p">.</span><span class="n">Next</span><span class="p">(</span><span class="n">summaries</span><span class="p">.</span><span class="n">Length</span><span class="p">)]</span>
</span></span><span class="line"><span class="cl">        <span class="p">))</span>
</span></span><span class="line"><span class="cl">        <span class="p">.</span><span class="n">ToArray</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="n">forecast</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="n">WithName</span><span class="p">(</span><span class="s">&#34;GetWeatherForecast&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="n">WithOpenApi</span><span class="p">().</span><span class="n">RequireAuthorization</span><span class="p">();</span>
</span></span></code></pre></div><p>Do a build to ensure there are no errors.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">dotnet build
</span></span></code></pre></div><p>Migrate the database.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">dotnet ef migrations add InitAuth -o Data/Migrations
</span></span><span class="line"><span class="cl">dotnet ef database update
</span></span></code></pre></div><p>Run the application.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">dotnet run
</span></span></code></pre></div><p>Navigate to <code>http://localhost:5001/swagger/index.html</code> to see the Identity endpoints.</p>
<p><img loading="lazy" src="/2024/swagger-dotnet-identity-endpoints.png" type="" alt="swagger-dotnet-identity-endpoints"  /></p>
<p>You can test the auth endpoints using Swagger, or as I prefer - Insomnia/Postman REST clients.</p>
<p>First, do a GET to <code>http://localhost:5001/weatherforecast</code> to see a 401 Unauthorized response.</p>
<p><img loading="lazy" src="/2024/unauthorized-identity-endpoint.png" type="" alt="unauthorized-identity-endpoints"  /></p>
<p>Now, call the <code>register</code> to create a user, and subsequently, the <code>login</code> endpoint to get a token.</p>
<p>POST http://localhost:5001/register</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;email&#34;</span><span class="p">:</span> <span class="s2">&#34;a1@a.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;password&#34;</span><span class="p">:</span> <span class="s2">&#34;Pass@123&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>POST http://localhost:5001/login</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;email&#34;</span><span class="p">:</span> <span class="s2">&#34;a1@a.com&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;password&#34;</span><span class="p">:</span> <span class="s2">&#34;Pass@123&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>You should get the token response.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;tokenType&#34;</span><span class="p">:</span> <span class="s2">&#34;Bearer&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;accessToken&#34;</span><span class="p">:</span> <span class="s2">&#34;CfDJ8AcfSlDrZbhNlphsDvuO8gDgQty5M...&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;expiresIn&#34;</span><span class="p">:</span> <span class="mi">3600</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;refreshToken&#34;</span><span class="p">:</span> <span class="s2">&#34;CfDJ8AcfSlDrZbhNlphsDvuO8gD60O...&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Use the access token to call the <code>weatherforecast</code> endpoint and see the glorious response.</p>
<p><img loading="lazy" src="/2024/identity-asp-dotnet-token-api-call.png" type="" alt="identity-asp-dotnet-token-api-call"  /></p>
<p>We have just scratched the surface of Identity in .NET. There is a lot more to explore, including:</p>
<ul>
<li>Account lockout/ recovery</li>
<li>Password policies</li>
<li>Claims and roles management</li>
<li>Customizing Identity</li>
<li>Using external providers</li>
<li>Role-based authorization</li>
<li>Multi-factor authentication</li>
</ul>
<h2 id="conclusion">Conclusion</h2>
<p>Check out the full code on <a href="https://github.com/techformist/dotnet-api-auth-demo/">GitHub</a>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Dotnet 6 is Refreshingly Simple</title>
      <link>https://techformist.com/dotnet6-refreshingly-simple/</link>
      <pubDate>Mon, 07 Feb 2022 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/dotnet6-refreshingly-simple/</guid>
      <description>&lt;p&gt;There are numerous things to love about the new .NET 6, but for me one key thing stands out - .NET now seems more approachable than ever!&lt;/p&gt;
&lt;p&gt;Take a straight-forward example. A new .NET Web API project would look like this -&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;code&gt;startup.cs&lt;/code&gt; file with generated code&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Program.cs&lt;/code&gt; file with more lines of code&lt;/li&gt;
&lt;li&gt;A lot of other files&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The two file dependencies induced that warm fuzzy feeling in ASP.NET developers for sometime now.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>There are numerous things to love about the new .NET 6, but for me one key thing stands out - .NET now seems more approachable than ever!</p>
<p>Take a straight-forward example. A new .NET Web API project would look like this -</p>
<ol>
<li>A <code>startup.cs</code> file with generated code</li>
<li>A <code>Program.cs</code> file with more lines of code</li>
<li>A lot of other files</li>
</ol>
<p>The two file dependencies induced that warm fuzzy feeling in ASP.NET developers for sometime now.</p>
<p>In addition, you have code that uses a wierd <code>using</code> syntax everywhere with brackets. Sure, it creates better compartmentalized &amp; namespaced code, but did not help calm my nerves when I was evaluating ten different back end technologies to make a quick start (a while ago).</p>
<p>C# 10 and the new ASP.NET 6 will do wonders in the &ldquo;make code look deceptively simple&rdquo; area.</p>
<p>There is no <code>startup.cs</code>. The <code>Program.cs</code> file now looks cool with the new features -</p>
<ul>
<li>top-level statements</li>
<li>global <code>using</code> directives</li>
<li>file scope namespace declarations (bear with me here)</li>
</ul>
<p>A minimal API structure now looks like this (<code>Program.cs</code> file) -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">builder</span> <span class="p">=</span> <span class="n">WebApplication</span><span class="p">.</span><span class="n">CreateBuilder</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">app</span> <span class="p">=</span> <span class="n">builder</span><span class="p">.</span><span class="n">Build</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span><span class="p">.</span><span class="n">MapGet</span><span class="p">(</span><span class="s">&#34;/&#34;</span><span class="p">,</span> <span class="p">()</span> <span class="p">=&gt;</span> <span class="s">&#34;Hello World!&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span><span class="p">.</span><span class="n">Run</span><span class="p">();</span>
</span></span></code></pre></div><p>A full-blown MVC web API application from the new template in .NET 6 looks like this..</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">builder</span> <span class="p">=</span> <span class="n">WebApplication</span><span class="p">.</span><span class="n">CreateBuilder</span><span class="p">(</span><span class="n">args</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// Add services to the container.</span>
</span></span><span class="line"><span class="cl"><span class="n">builder</span><span class="p">.</span><span class="n">Services</span><span class="p">.</span><span class="n">AddControllers</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">builder</span><span class="p">.</span><span class="n">Services</span><span class="p">.</span><span class="n">AddEndpointsApiExplorer</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kt">var</span> <span class="n">app</span> <span class="p">=</span> <span class="n">builder</span><span class="p">.</span><span class="n">Build</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span><span class="p">.</span><span class="n">UseHttpsRedirection</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">app</span><span class="p">.</span><span class="n">UseAuthorization</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="n">app</span><span class="p">.</span><span class="n">MapControllers</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="n">app</span><span class="p">.</span><span class="n">Run</span><span class="p">();</span>
</span></span></code></pre></div><p>&ldquo;Whoa..!&rdquo; is right.</p>
<p>I am not proud of the fact that the additional statements &amp; brackets were putting me off a long time. While I love C# for what it can do, I seldom choose C# for personal projects for all the silly reasons - I did not need the complexity, did not like to do lot of typing or &ldquo;auto filling&rdquo;, and did not have a lot of patience for code scrolling tens of pages.</p>
<p>NodeJS simply offered a better alternative, was way simpler to start (especially in Fastify or Express), and came at a cost that did not quite matter to me. And, I am a happy Javascript user - no one will take that away from me.</p>
<p>I am a fan of the new ASP.NET structure - for probably all the wrong reasons for a &ldquo;real&rdquo; developer. I will probably delve more into how a further &ldquo;simplified&rdquo; folder structure can make the ASP.NET world more exciting to work on. The &ldquo;traditional&rdquo; structure has been full of folders and a lot of files. See the <a href="https://github.com/dotnet-architecture/eShopOnWeb/tree/main/src/Web">eShopOnWeb example on Github</a>. The <a href="https://gist.github.com/davidfowl/ff1addd02d239d2d26f4648a06158727">minimal API structure at a glance by Martin Fowler</a> is a good start for a new approach to build Web APIs on .NET 6, but what is even more interesting to me is the <a href="https://timdeschryver.dev/blog/maybe-its-time-to-rethink-our-project-structure-with-dot-net-6">module-based architecture</a> outlined in this post by Tim Deschryver.</p>
<pre tabindex="0"><code>WebApplication
│   appsettings.json
│   Program.cs
│   GlobalImports.cs
│   WebApplication.csproj
│
├───Modules
│   ├───Cart
│   │      CartModule.cs
│   └───Orders
│       │   OrdersModule.cs
│       ├───Endpoints
│       │       GetOrders.cs
│       │       PostOrder.cs
│       ├───Core
│       │       Order.cs
│       │───Ports
│       │       IOrdersRepository.cs
│       │       IPaymentService.cs
│       └───Adapters
│               OrdersRepository.cs
│               PaymentService.cs
</code></pre><p>Awesome time this.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>A quick start on ASP.NET Core Razor Pages</title>
      <link>https://techformist.com/asp-net-razor-pages-quick-start/</link>
      <pubDate>Wed, 05 Feb 2020 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/asp-net-razor-pages-quick-start/</guid>
      <description>&lt;p&gt;Here&amp;rsquo;s a quick introduction to Razor pages in ASP.NET core, and an opinionated way to quickly start building applications using Razor pages. And yes, there is a case for using Razor pages even in 2020.&lt;/p&gt;
&lt;h3 id=&#34;so-aspnet&#34;&gt;So.. ASP.net?&lt;/h3&gt;
&lt;p&gt;Yes, indeed. I have had a love-hate relationship with ASP.NET through years. I am way less productive using ASP.net but cannot ignore the speed that a dotnet web server provides. Take into account the super debugging capabilities/tooling and the sizeable market that keeps providing projects on the platform, we surely have more than a winner in ASP.NET.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Here&rsquo;s a quick introduction to Razor pages in ASP.NET core, and an opinionated way to quickly start building applications using Razor pages. And yes, there is a case for using Razor pages even in 2020.</p>
<h3 id="so-aspnet">So.. ASP.net?</h3>
<p>Yes, indeed. I have had a love-hate relationship with ASP.NET through years. I am way less productive using ASP.net but cannot ignore the speed that a dotnet web server provides. Take into account the super debugging capabilities/tooling and the sizeable market that keeps providing projects on the platform, we surely have more than a winner in ASP.NET.</p>
<p>And oh, it immensely helps that innovations like Blazor are exciting options to make web development arguably more productive and easier.</p>
<h2 id="why-yet-another-introduction">Why yet another introduction?</h2>
<p>There are a million other introductions to ASP.NET platform. Microsoft&rsquo;s own documentation and guides are immensely helpful for beginners at all stages. But, what I love to see is a quick way to create an app (or two) and make new developers comfortable with the ecosystem. At least that&rsquo;s how I learn stuff and I found some of the tutorials I glanced through to be either too detailed, or at a superficially high level.</p>
<p>This introduction is more for developers who use a different language for web development. It is not quite intended for absolute beginners, but anyone should be able to follow along.</p>
<h2 id="firing-off-with-aspnet">Firing off with ASP.net</h2>
<p>There are two main ways to get started on development using ASP.net platform.</p>
<ol>
<li>Use Visual Studio: proven way that has been forever</li>
<li>Use Visual Studio Code or your favourite editor and dotnet core CLI</li>
</ol>
<p>Both ways deserve all the love they can get. I prefer VSCode, but will use Visual Studio in this tutorial because - why not. Going forward I will be basing discussions primarily on Visual Studio 2019 and dotnet Core 3.1.</p>
<p>Installation is somewhat boring and works on expected lines.</p>
<ol>
<li>Download Visual Studio from <a href="https://visualstudio.microsoft.com/">https://visualstudio.microsoft.com/</a></li>
<li>Click, click, click to install</li>
</ol>
<p>Visual Studio comes with dotnet SDK, and you should be all set by now. If you decide to use VSCode, just install the dotnet SDK separately. You should then be able to use all the command line goodness on the best code editor ever(tm).</p>
<p>See the <a href="https://dotnet.microsoft.com/learn/dotnet/hello-world-tutorial/install">install docs</a> if you are stuck. (Stuck during install, really?)</p>
<p>Once everything&rsquo;s ready, just create a new project.</p>
<p><img loading="lazy" src="/misc/dotnet-razor-pages-new-project.jpg" type="" alt="dotnet-razor-pages-new-project"  /></p>
<p>Select &ldquo;ASP.NET Core Web Application&rdquo;. Hit next and name your project. You will get another screen where you can select an &ldquo;Web Application&rdquo; template. This option will instruct Visual Studio to scaffold a few things when the project is created.</p>
<h2 id="the-structure">The Structure</h2>
<p>As any modern web development stack, the files generated can be overwhelming at the beginning. We can break the structure down to basics.</p>
<p>A typical ASP.net project consists of one solution (which is a container for projects), and one or more projects. It will have at least one project (of course), anything else is optional and enables you to build stuff incrementally.</p>
<p><img loading="lazy" src="/misc/project-structure-visual-studio-asp-net-core-razor.jpg" type="" alt="project-structure-visual-studio-asp-net-core-razor"  /></p>
<h3 id="beginning-of-everything-startupcs-and-programcs">Beginning of everything: <code>Startup.cs</code> and <code>Program.cs</code></h3>
<p>These are the two files that bootstrap our app and give it ASP powers. When our app starts, the runtime calls <code>Main</code> method defined in <code>Program.cs</code>, which configures itself and starts running as an ASP app.</p>
<p>If you were so far wondering how our humble app came to acquire ASP powers, <code>IHostBuilder</code> is to blame. That interface provides our function <code>CreateHostBuilder</code> abilities to assume the powers of ASP.net, configure itself and start running - all in a simple one-line statement..</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="n">CreateHostBuilder</span><span class="p">(</span><span class="n">args</span><span class="p">).</span><span class="n">Build</span><span class="p">().</span><span class="n">Run</span><span class="p">();</span>
</span></span></code></pre></div><p>More code in <code>Program.cs</code> uses <a href="https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/statements-expressions-operators/lambda-expressions">C# lambdas</a> and <a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1">Dependency Injection</a> (&ldquo;DI&rdquo;) to apply configuration parameters and methods defined in <code>Startup.cs</code> to our application.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="kd">public</span> <span class="kd">static</span> <span class="n">IHostBuilder</span> <span class="n">CreateHostBuilder</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span> <span class="n">args</span><span class="p">)</span> <span class="p">=&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="n">Host</span><span class="p">.</span><span class="n">CreateDefaultBuilder</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">            <span class="p">.</span><span class="n">ConfigureWebHostDefaults</span><span class="p">(</span><span class="n">webBuilder</span> <span class="p">=&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="n">webBuilder</span><span class="p">.</span><span class="n">UseStartup</span><span class="p">&lt;</span><span class="n">Startup</span><span class="p">&gt;();</span>
</span></span><span class="line"><span class="cl">            <span class="p">});</span>
</span></span></code></pre></div><p>Further, <code>ConfigureServices</code> in <code>Startup.cs</code> has a specific block that enables Razor pages in your app.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="kd">public</span> <span class="k">void</span> <span class="n">ConfigureServices</span><span class="p">(</span><span class="n">IServiceCollection</span> <span class="n">services</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">services</span><span class="p">.</span><span class="n">AddRazorPages</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The <code>Configure</code> method in <code>Startup.cs</code> enables a pipeline to include middleware, which in-turn enables various features for your app - all without needing you to code them in.</p>
<p>For e.g. -</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="kd">public</span> <span class="k">void</span> <span class="n">Configure</span><span class="p">(</span><span class="n">IApplicationBuilder</span> <span class="n">app</span><span class="p">,</span> <span class="n">IWebHostEnvironment</span> <span class="n">env</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...</span>
</span></span><span class="line"><span class="cl">    <span class="n">app</span><span class="p">.</span><span class="n">UseHttpsRedirection</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// ...</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>&hellip; tells runtime to redirect HTTP requests to HTTPS.</p>
<p>We will deal with lambda functions, DI etc. in more detail some other time. For now, we will move on and find out how we can quickly create our app on ASP.net.</p>
<h3 id="before-we-dig-in-settings-and-launchsettingsjson">Before we dig-in: settings and <code>launchSettings.json</code></h3>
<p>We have created a web application that runs as a command line app. The server is just serving content defined in web stuff like HTML/JS/CSS etc and in Razor pages, but does not render UI on its own.</p>
<p>Configuration parameters for our app is defined in <code>launchSettings.json</code>.</p>
<p>You can see the values defined in settings file in a nice user interface - right-click on the project (not the solution) in the right-hand-side bar, and select properties. Any change in one place is reflected in the other - just sayin'.</p>
<p>You may also notice the word &ldquo;development&rdquo; in the configuration file. We can provide parameters for any number of environments including development, and the start-up logic figures out the settings to apply. Further, secrets can be managed quite efficiently and made accessible to those who &ldquo;need to know&rdquo;. This is super helpful as you might imagine.</p>
<p>By default, the app uses IISExpress but there are options to use Kestrel, which is a light-weight (&amp; a more modern) server by Microsoft. You will see these configuration options selected in the Toolbar as well. Typically, I prefer Kestrel since it is fast, and I end up hosting dotnet on Linux (where IIS is not available).</p>
<h3 id="the-client-facing-wwwroot">The &lsquo;client-facing&rsquo; <code>wwwroot</code></h3>
<p>All the client-facing assets are stored in the <code>www</code> folder. This includes CSS, JS (custom and any libraries), static HTML, and anything else that finds its way to the browser.</p>
<p>Right off the bat, you see a sample CSS and JS, bootstrap and JQuery in the scaffolded files. Any and all of this can be changed or replaced. For e.g. you can replace Bootstrap with Bulma and chug along a different path.</p>
<h3 id="pages-folder"><code>Pages</code> folder</h3>
<p>Most of the action takes place here. <code>Pages</code> is where you place razor pages created using C#. The pages in C# get converted to something that the browser can understand by ASP.NET – we will see way more of pages in a few moments. Razor pages have the extension &lsquo;cshtml&rsquo; files</p>
<p>You also see a <code>Shared</code> folder and a bunch of files starting with <code>_</code>. Shared folder is used to contain assets shared across the project, and the <code>_</code> is a convention to create something called a &lsquo;partial&rsquo;. A partial is not a &lsquo;complete&rsquo; page in itself, but comes together with other partials or pages to form complete pages.</p>
<p><code>Layout.cshtml</code> is an example of a partial. In this file we have the header (which forms the header in the pages using this layout), a container (which will contain data), and the footer. The file also has references to script and HTML.</p>
<p>Of course, you can use different layouts, or decide not to use layouts at all – but building pages like this will make the entire process easy to build and to maintain.</p>
<p>In other notes, take a look at -</p>
<ul>
<li><code>_ViewImports.cshtml</code>: enables tag helpers globally</li>
<li><code>_ViewStart.cshtml</code>: base/master page</li>
</ul>
<p>Error, Index and Privacy pages are the actual Razor pages. You will create something on these lines to for adding more pages to your app.</p>
<p>Expand <code>Index.cshtml</code> page to find a file called <code>Index.cshtml.cs</code>. This file has the C# code to go along with the mark-up page. You can refer to the variables, methods, etc. from this c# page in the mark-up <code>cshtml</code> page. This arrangement is akin to mark-up + code arrangement in any Vue/React/Svelte application. In Blazor, you can have mark-up + code in same or different files - but that is for a different day.</p>
<p>This structure is different from a typical MVC model that touts a distinct controller, model and view layer. These functions are present in the Razor page app, but not fashioned in MVC style.</p>
<h2 id="more-about-the-internals-and-workings-of-an-aspnet-app">More about the internals and workings of an ASP.net app</h2>
<p>We are now masters of the structure of ASP.net core razor page project, and it is time to move on and see how everything comes together.</p>
<p>If you&rsquo;re serious about your trade, you will skip this section altogether. The terms here just help you speak the same language - you will probably figure this out by yourself while building the actual app.</p>
<h3 id="routing">Routing</h3>
<p>The <code>Pages</code> folder takes care of routing in our application. The files in the folder represent the URLs served by your application.</p>
<p>Let&rsquo;s see how..</p>
<ul>
<li><code>Privacy.cshtml</code> is a file in the <code>Pages</code> folder</li>
<li><code>baseurl.com/privacy</code> will request the page named &lsquo;privacy.cshtml&rsquo; in the folder. ASP.net serves the HTML generated from the razor page.</li>
<li>Any sub-folder will also get included in the path. For e.g. a <code>blog/Hello.cshtml</code> is rendered on <code>baseurl.com/blog/Hello</code></li>
<li>If the requested page does not exist, a &lsquo;page cannot be found&rsquo; error is displayed by default. You can configure the application to redirect requests to any other page (e.g. <code>index</code>) if the page cannot be located</li>
</ul>
<p>You can override the default routing using the <code>@Page</code> tag.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cs" data-lang="cs"><span class="line"><span class="cl"><span class="n">@page</span> <span class="s">&#34;/privacy1&#34;</span>
</span></span></code></pre></div><p>.. will enable the link to <code>baseurl.com/privacy1</code> and the previously used <code>/privacy</code> page disappears into oblivion.</p>
<h2 id="start-tinkering">Start Tinkering</h2>
<p>Run your app by hitting <code>Ctrl + F5</code>. Visual Studio opens the browser (or allows you to configure browser) and serves the application. You can see the starter page and navigate through the links provided in the scaffolded application.</p>
<p>You will see that any changes will require you to build/restart app. We can avoid that by executing our app in watch mode..</p>
<pre tabindex="0"><code>cd &lt;project-folder&gt;
dotnet run watch
</code></pre>]]></content:encoded>
    </item>
    
    <item>
      <title>Hosting Models for Blazor</title>
      <link>https://techformist.com/hosting-models-blazor/</link>
      <pubDate>Tue, 13 Aug 2019 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/hosting-models-blazor/</guid>
      <description>&lt;p&gt;Blazor has three hosting models - as I see it :)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Server&lt;/li&gt;
&lt;li&gt;Client&lt;/li&gt;
&lt;li&gt;Client++&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will look at them in brief below.&lt;/p&gt;
&lt;h3 id=&#34;server&#34;&gt;Server&lt;/h3&gt;
&lt;p&gt;Server hosted implies the entire application being hosted on server. A razor-thin (no pun) app is delivered to client and there on client relies on server for everything.&lt;/p&gt;
&lt;p&gt;I mean everything -&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All clicks, user input, gestures etc. will be transferred to server through a SignalR connection. Server figures out what to do&lt;/li&gt;
&lt;li&gt;Server does DOM diffing, keeps track of updates that are done client-side and what should be sent to client. Server delivers those changes to client over the ever-persistent SignalR&lt;/li&gt;
&lt;li&gt;Server sees any connection drops and maintains state if client reconnects&lt;/li&gt;
&lt;li&gt;Client reacts, and keeps reacting with help from server&lt;/li&gt;
&lt;li&gt;Can work on older browsers (though, to be frank, if you are using old browsers - you should be upgrading old browsers and the apps rather than reading this article)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Though this may sound primitive, but works wonderfully well - provided you have good connectivity to server and a fast-enough server.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Blazor has three hosting models - as I see it :)</p>
<ul>
<li>Server</li>
<li>Client</li>
<li>Client++</li>
</ul>
<p>We will look at them in brief below.</p>
<h3 id="server">Server</h3>
<p>Server hosted implies the entire application being hosted on server. A razor-thin (no pun) app is delivered to client and there on client relies on server for everything.</p>
<p>I mean everything -</p>
<ul>
<li>All clicks, user input, gestures etc. will be transferred to server through a SignalR connection. Server figures out what to do</li>
<li>Server does DOM diffing, keeps track of updates that are done client-side and what should be sent to client. Server delivers those changes to client over the ever-persistent SignalR</li>
<li>Server sees any connection drops and maintains state if client reconnects</li>
<li>Client reacts, and keeps reacting with help from server</li>
<li>Can work on older browsers (though, to be frank, if you are using old browsers - you should be upgrading old browsers and the apps rather than reading this article)</li>
</ul>
<p>Though this may sound primitive, but works wonderfully well - provided you have good connectivity to server and a fast-enough server.</p>
<ul>
<li>We have no business logic going to the client - server takes care of everything</li>
<li>Infrastructure is under tight control and you can do whatever you please (well, it&rsquo;s <em>our</em> server)</li>
</ul>
<p>At the same time -</p>
<ul>
<li>There will be delays. It is better to do processing locally than on the server. It will be interesting to see real-world performance, but I do not expect this to be fast</li>
<li>Everything is dependent on server - so strictly online feature set</li>
<li>Client-side connections and all that work will put significant stress on servers (I was not a fan of such <a href="/universal-apps-meteorjs-2019/">client connections in MeteorJS</a>, I really doubt server-side Blazor will change my mind)</li>
</ul>
<p>I think server-hosted models will be a boon to a whole lot of stupid enterprise applications that have been begging for an upgrade since Y2000. I see server-hosted Blazor as the new client-server - only that we now follow universal standards :).</p>
<p>Server-side hosting is also easier to control and implement - Microsoft plans to deliver these as part of the .NET Core v3 full release later this year. The only positive I see here is the web-socket like SignalR. We do not need to write a lot of boiler-plate to control those server-client interactions but let the underlying framework handle them.</p>
<h3 id="client">Client</h3>
<p>Client-side hosting falls to the other extreme. The app delivers itself to the client and runs as a full-fledged .NET application using Mono within the browser.</p>
<p>Once the app DLLs (yes, DLLs) and WASM running infrastructure is downloaded to client, the client does not need the server anymore.</p>
<ul>
<li>All processing happens on the client side (except online connections and updates to server DB, of course)</li>
<li>UI generation, reacting to changes and events happen on the client side</li>
</ul>
<p>I could also deliver this blog entirely to your desktop - take that, Blogspot.</p>
<p>On the flip side -</p>
<ul>
<li>There is much more dependence on browser to stick to WASM standards and get everything done</li>
<li>Initial download size is larger. It is not so large to cause a commotion - we see MBs getting downloaded from style libraries even today</li>
<li>WASM is comparatively young technology, and may not be the best choice today for applications with stability as a requirement</li>
</ul>
<h3 id="the--sub-division-and-selecting-a-hosting-model">The <code>++</code> Sub-division and Selecting a Hosting Model</h3>
<p>When you click on <code>New Project</code> in Visual Studio, and select <code>Blazor</code> template, you will see the exact two options outlined above.</p>
<p><img loading="lazy" src="/misc/blazor-template-hosting-model.jpg" type="" alt=""  /></p>
<p>In addition to the options, you will also see a checkbox called <code>ASP.NET Core Hosted</code> for <code>Blazor WebAssembly App</code>. This is the result of a simplified model in Preview 8, and which I have come to appreciate.</p>
<p>By selecting the box, you are instructing the the scaffolding to create -</p>
<ol>
<li>Client-side code</li>
<li>Server-side code that can enable your app to have server-side logic including those done by services/controllers in a MVC model</li>
<li>Shared code, which can be shared by client and server</li>
</ol>
<p>Any web app is not an island by itself. Using a core hosted model with WASM, we can create applications that do most of the work on the client-side, but can also fall back on server for sensitive/proprietary business logic, maintaining centralized data store, and other such use cases.</p>
<p>I am personally excited about the server-hosted WASM. That is the future, folks - does not matter whether you mark or unmark my words.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Blazor for Production Anyone? Preview 7 is Released</title>
      <link>https://techformist.com/blazor-for-production-preview7/</link>
      <pubDate>Wed, 31 Jul 2019 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/blazor-for-production-preview7/</guid>
      <description>&lt;p&gt;Blazor is a big part of why I am looking forward to .NET 3.0. That&amp;rsquo;s one of the reasons I try to play around with the individual releases.&lt;/p&gt;
&lt;p&gt;Though Release 6 (I think ) caused some pain, the release schedules seem to be good as previews. As I understand - the ASP.NET Core team had been working on ironing out issues and making the application ready. That has come to a larger milestone since &lt;a href=&#34;https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-7/&#34;&gt;Release 7 has been out for a week&lt;/a&gt; and it is said to be ready for production.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Blazor is a big part of why I am looking forward to .NET 3.0. That&rsquo;s one of the reasons I try to play around with the individual releases.</p>
<p>Though Release 6 (I think ) caused some pain, the release schedules seem to be good as previews. As I understand - the ASP.NET Core team had been working on ironing out issues and making the application ready. That has come to a larger milestone since <a href="https://devblogs.microsoft.com/dotnet/announcing-net-core-3-0-preview-7/">Release 7 has been out for a week</a> and it is said to be ready for production.</p>
<p>I created multiple versions of a standard &rsquo;to do&rsquo; app through the versions using both client and server-side Blazor - loving the development so far. Though Materialize CSS is a good option, I still do not believe that is not at the same level as Bootstrap within the .NET world. Again, that may be how I see the world and that can be totally wrong.</p>
<p>Documentation was particularly important for a poor .NET developer like myself - that seems to have been improving over at the <a href="https://docs.microsoft.com/en-us/aspnet/core/blazor/get-started?view=aspnetcore-3.0&amp;tabs=visual-studio">ASP.NET Core Preview docs site</a>.</p>
<p>I see a few of the older channels publishing videos on Blazor, but .NET does not seem to be as happening a place when it comes to community. Or, I may have been spoilt by choice and the over-enthusiastic Javascript community.</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=uW-Kk7Qpv5U">NDC Conference - July</a></li>
<li>Microsoft published videos <a href="https://www.youtube.com/watch?v=PiJtEZYMxOc">Nov 18</a></li>
<li><a href="https://www.youtube.com/watch?v=CaxR4_fP-FA">Blazor tutorial video by Tim Corey</a> [updated]</li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Blazor and what it means for web development</title>
      <link>https://techformist.com/blazor-what-it-means-web-development/</link>
      <pubDate>Sat, 16 Mar 2019 06:30:00 +0000</pubDate>
      
      <guid>https://techformist.com/blazor-what-it-means-web-development/</guid>
      <description>&lt;p&gt;As a web developer I am amazed on web assembly and what Blazor could do with it. And, I am saying that even though I absolutely love what Javascript can do.&lt;/p&gt;
&lt;h3 id=&#34;the-back-story&#34;&gt;The Back Story&lt;/h3&gt;
&lt;p&gt;I had been hearing about this Microsoft experiment with web assembly (WASM) for quite sometime, but got an opportunity to take a further look starting late 2018. This was the time when news of Blazor being released as part of .NET Core started going rounds. At a later time this was expected to be &lt;a href=&#34;https://visualstudiomagazine.com/articles/2018/10/03/blazor-update.aspx&#34;&gt;server side Blazor&lt;/a&gt;. I can&amp;rsquo;t find the patience to go over the messaging confusion with Razor pages, Razor components, server-side and client-side Razor / Blazor. We will get back to that topic at some time.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>As a web developer I am amazed on web assembly and what Blazor could do with it. And, I am saying that even though I absolutely love what Javascript can do.</p>
<h3 id="the-back-story">The Back Story</h3>
<p>I had been hearing about this Microsoft experiment with web assembly (WASM) for quite sometime, but got an opportunity to take a further look starting late 2018. This was the time when news of Blazor being released as part of .NET Core started going rounds. At a later time this was expected to be <a href="https://visualstudiomagazine.com/articles/2018/10/03/blazor-update.aspx">server side Blazor</a>. I can&rsquo;t find the patience to go over the messaging confusion with Razor pages, Razor components, server-side and client-side Razor / Blazor. We will get back to that topic at some time.</p>
<p>NDC demonstrations are always great, and I got blown away by a couple <a href="https://www.youtube.com/watch?v=PiJtEZYMxOc">of</a> <a href="https://www.youtube.com/watch?v=cT2fzFBRZWU">demonstrations</a> that showed what Blazor can do. (<a href="https://www.youtube.com/watch?v=JU-6pAxqAa4">another demo from May &lsquo;19</a>, <a href="https://www.youtube.com/watch?v=y7LAbdoNBJA">another excellent presentation on Microsoft Developer channel</a>).</p>
<ul>
<li>Code in C#</li>
<li>Same code for client and server</li>
<li>Shareable code</li>
</ul>
<p>None of this is path breaking in the Javascript world, but what I was interested was in Web Assembly.</p>
<p>Web assembly has been in development for quite sometime and, today, enjoys good support in major browsers. Web assembly has been an accepted standard across the industry and that is the major difference between the capabilities offered by WASM vs. similar applications of the past like Adobe Air, Silverlight et al.</p>
<p>Web assembly is also exciting because we can literally wipe away the difference between devices and get our web applications the respect they deserve.</p>
<ul>
<li>Run a full-fledged app in browser</li>
<li>Run almost any app</li>
<li>Complete offline capabilities and seamless online/offline switch</li>
<li>True cross-platform with natural native capabilities using native libraries</li>
</ul>
<p>I mean, what more can anyone ask for? Even the man in the Tolstoy book would want to start working in this technology rather than trying to walk full day to acquire land.</p>
<h3 id="where-i-stand-today">Where I stand today?</h3>
<p>As we came closer to .NET release schedules, we learnt that .NET 3 will be late 2019 and may not have full-time, production-ready client-side Blazor.</p>
<p>By this time, those schedules did not matter much to me.</p>
<p>I was going through the previews of .NET 3 and was quite surprised by what Microsoft could achieve. Though the documentation was sparse, we could follow the architecture of a .NET Core application of yore, and have a web application delivered to the client - DLLs and all. The toolsets that came with and promised for later releases are expected to push developer productivity to newer heights.</p>
<p>What I liked about Blazor other than the part that it could deliver a fully client-side app was -</p>
<ul>
<li>More succinct code</li>
<li>Tooling. Visual Studio is much faster and better than what it was</li>
<li>Integration with existing Nuget packages incl. those for integrating with Office apps</li>
</ul>
<p>What I don&rsquo;t like -</p>
<ul>
<li>Boiler plate. Man, I did not quite remember the amount of boiler plate code I was writing at the time</li>
<li>Super picky type-safety. Our beloved Typescript allows us to cheat, C# does not give a damn about what we love</li>
<li>A not-so-nice to work with ORM in Entity Framework Core(Dapper can potentially change that - but I don&rsquo;t have experience there)</li>
</ul>
<p>I am on the fence with SignalR.</p>
<h3 id="what-is-the-future">What is the future?</h3>
<p>As we see more and more of WASM, and the support for WASM in multiple languages (incl. Rust, Javascript etc.), we will probably blur differences between desktop/web applications to a large extent.</p>
<p>What I intend to do with .NET Core 3 is to write applications that depend less on server side infrastructure (so server-side Razor does not interest me much). I intend to create a few simple apps where users have full control over their data, choose their own back-end without limiting the web front-end experience - all without sacrificing easy upgradeability and at super minimal costs.</p>
<p>What time to be alive, eh folks?</p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
