<?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[Kndb's blog]]></title><description><![CDATA[I join lego pieces in the backend. 

This blog acts as a journal to some of my work, so that I can look back on my own progression.]]></description><link>https://blog.debbarma.in</link><image><url>https://cdn.hashnode.com/res/hashnode/image/upload/v1633106560537/2oFBwtsDG.png</url><title>Kndb&apos;s blog</title><link>https://blog.debbarma.in</link></image><generator>RSS for Node</generator><lastBuildDate>Sun, 26 Apr 2026 04:18:21 GMT</lastBuildDate><atom:link href="https://blog.debbarma.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[gRPC with .NET Core]]></title><description><![CDATA[Reading about REST vs RPC few years back I came across this neat RPC framework called gRPC. Since then the framework has gained a lot of traction, companies like Netflix, Lyft use it at its core today.
Most of us, know by now that the g in gRPC does ...]]></description><link>https://blog.debbarma.in/grpc-with-net-core</link><guid isPermaLink="true">https://blog.debbarma.in/grpc-with-net-core</guid><category><![CDATA[asp.net core]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[http2]]></category><dc:creator><![CDATA[kndb]]></dc:creator><pubDate>Mon, 21 Feb 2022 19:23:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1645471709782/zzVs8uDTj.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Reading about <code>REST vs RPC</code> few years back I came across this neat RPC framework called <code>gRPC</code>. Since then the framework has gained a lot of traction, companies like <code>Netflix</code>, <code>Lyft</code> use it at its core today.</p>
<p>Most of us, know by now that the g in <code>gRPC</code> does not stand for <code>Google</code>, it literally stands for nothing. I mean why not give <code>Google</code> the accolades since the project was created and is maintained by them 😃</p>
<p>There are areas where it shines and then of course there are limitations, we will take a look at those at the end of this article. In this article we will take a look at how we can create a simple <code>.NET Core</code> gRPC server, expose a unary rpc method and consume it using <code>BloomRPC</code> client.</p>
<h3 id="heading-create-the-grpc-server">Create the gRPC server</h3>
<h4 id="heading-add-nuget-package">Add nuget package</h4>
<p>Search for <code>Grpc.AspNetCore</code> and add the latest stable version to your project.</p>
<h4 id="heading-create-your-proto-file">Create your <code>.proto</code> file</h4>
<p>We are defining a service called <code>Echo</code>, which would have an <code>rpc</code> method called <code>EchoMessage</code>. Additionally we will also define the data transfer objects <code>EchoRequest</code> and <code>EchoResponse</code>.</p>
<pre><code class="lang-C#">syntax = <span class="hljs-string">"proto3"</span>; <span class="hljs-comment">// protocol buffer version</span>
option csharp_namespace = <span class="hljs-string">"GrpcTrial"</span>;
package echo;
service Echo { <span class="hljs-comment">// the service</span>
  <span class="hljs-function">rpc <span class="hljs-title">EchoMessage</span> (<span class="hljs-params">EchoRequest</span>) <span class="hljs-title">returns</span> (<span class="hljs-params">EchoResponse</span>)</span>; <span class="hljs-comment">// the rpc method</span>
}
message EchoRequest {
  <span class="hljs-keyword">string</span> message = <span class="hljs-number">1</span>; <span class="hljs-comment">// index at which the property is available</span>
}
message EchoResponse {
  <span class="hljs-keyword">string</span> message = <span class="hljs-number">1</span>;
}
</code></pre>
<h4 id="heading-set-the-proto-file-to-build-the-server-stub-classes">Set the proto file to build the server stub classes</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645168337832/jkQHIxtXp.png" alt="image.png" /></p>
<p>As soon as we build our project, few base classes will be autogenerated for us, classes gRPC understands, all we have to do now is override the methods for our logic.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">EchoService</span> : <span class="hljs-title">Echo.EchoBase</span> <span class="hljs-comment">// Inherit from the auto generated base class</span>
{
    <span class="hljs-comment">// override the method and add our own logic</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">override</span> Task&lt;EchoResponse&gt; <span class="hljs-title">EchoMessage</span>(<span class="hljs-params">EchoRequest request, ServerCallContext context</span>)</span>
    {
         <span class="hljs-keyword">return</span> Task.FromResult(<span class="hljs-keyword">new</span> EchoResponse {  Message = <span class="hljs-string">$"Did you just say, <span class="hljs-subst">{request.Message}</span>"</span>});
    }
}
</code></pre>
<h4 id="heading-add-the-grpc-service-to-service-container">Add the gRPC service to service container</h4>
<pre><code><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>{
      services.AddGrpc(); 
}
</code></pre><h4 id="heading-add-the-grpc-middleware">Add the gRPC middleware</h4>
<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">Configure</span>(<span class="hljs-params">IApplicationBuilder app, IWebHostEnvironment env</span>)</span>
{
      app.UseRouting();
      app.UseEndpoints(endpoints =&gt;
      {
             endpoints.MapGrpcService&lt;EchoService&gt;();
      });
}
</code></pre>
<h3 id="heading-call-the-rpc-method-from-a-client">Call the RPC method from a client</h3>
<p>For this article we will use <code>BloomRPC</code>, an open source GUI client for gRPC services.</p>
<p>Simply add the proto file inside BloomRPC app, enter the base uri of server, modify the payload, and send a request</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1645468095186/sg-eTEdTl.gif" alt="final_62026d026b89e200619ed6e2_895774.gif" /></p>
<p>Pretty neat! 👌</p>
<p>Though very promising, this is not a replacement for <code>REST APIs</code> or <code>SignalR</code>. It shines at places and has its own issues.</p>
<p><strong>Pros</strong></p>
<ul>
<li>High performance since it works on top of <code>HTTP/2</code>, additionally it also <code>serializes the data</code> over network reducing data size again</li>
<li>Works for <code>low-bandwidth</code> systems, since the size of data over network is reduced</li>
<li><code>Programming language agnostic</code>, once we have a proto file the same can be used by almost all languages, imagine a <code>microservice architecture</code> where each service is built using a different programming language</li>
<li><code>Bidirectional streaming</code> capabilities, client can stream data to the server, server can stream data to the client, or both can happen at the same time.</li>
</ul>
<p><strong>Cons</strong></p>
<ul>
<li><code>HTTP/2 and greater only</code>, which might be a headache for clients/services on older versions of HTTP. </li>
<li>There is a <code>learning curve</code>, getting used to protocol buffer, bidirectional streaming etc may take sometime. </li>
<li><code>Not enough tooling</code> is available, 🛑 I just couldn't make use of https using BloomRPC, from a console app it works seamlessly.</li>
</ul>
<p>I have used <code>gRPC</code> to <strong>stream</strong> <code>log messages</code> from one component to another. Few of our backend jobs take time(even days) and logs are continuously written to flat files inside a VM, a <code>gRPC</code> connection is established between the VM and a service, logs are then pushed as soon as they arrive, giving the user <code>visibility</code> of what's happening <code>behind the scenes</code> with the process. 🌟 But more about streaming in my next articles.</p>
<p>I hope this post gave you some insights on <code>gRPC</code> and will help you get started. Thank you for reading. Cheers!</p>
<p>Resources</p>
<ul>
<li>gRPC <a target="_blank" href="https://grpc.io/docs">official documentation</a> </li>
<li>BloomRPC <a target="_blank" href="https://github.com/bloomrpc/bloomrpc">GitHub page</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[I participated in a company wide 24hr hackathon and here's how it went]]></title><description><![CDATA[Run through of the idea
I did a last minute registration, couldn't find anyone to join me, with a bit of hesitation ran solo 😑
Most of the themes were focused towards company's product use cases. I ended up picking the General theme, because I was n...]]></description><link>https://blog.debbarma.in/i-participated-in-a-24hr-hackathon</link><guid isPermaLink="true">https://blog.debbarma.in/i-participated-in-a-24hr-hackathon</guid><category><![CDATA[hackathon]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[server]]></category><category><![CDATA[Azure]]></category><category><![CDATA[DigitalOcean]]></category><dc:creator><![CDATA[kndb]]></dc:creator><pubDate>Sat, 08 Jan 2022 13:16:39 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1641646956651/wBt1yzwQb.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-run-through-of-the-idea">Run through of the idea</h2>
<p>I did a last minute registration, couldn't find anyone to join me, with a bit of hesitation ran solo 😑</p>
<p>Most of the themes were focused towards company's product use cases. I ended up picking the General theme, because I was not interested in any of them.</p>
<p>There was an area which bugged me for quite sometime and it was around <code>HTTP polling</code> which we were doing in a lot of places in our cloud app. The first thought that came to my mind was to use <code>SignalR</code> to be able to switch to a more real-time data transfer from server to client. The only problem was <code>SignalR</code> exposes a <code>bidirectional channel</code> and for the issue in hand it seemed unnecessary. The problems I wanted to solve were around status updates, log streaming etc wherein after a client-server handshake is established the client would not be sending any data to the server.</p>
<p>While exploring for other real-time data transfer options and talking to few other colleagues I came across this little known <code>HTTP</code> feature called <code>Server-Sent Events</code>, and it was exactly what I was looking for 👌</p>
<ul>
<li>It created a <code>unidirectional channel</code></li>
<li><code>Lightweight</code> with less bloat</li>
<li><code>Easy</code> to setup</li>
</ul>
<p><strong>From Wikipedia</strong></p>
<blockquote>
<p>Server-Sent Events (SSE) is a server push technology enabling a client to receive automatic updates from a server via an HTTP connection, and describes how servers can initiate data transmission towards clients once an initial client connection has been established. </p>
</blockquote>
<h2 id="heading-overall-design">Overall design</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640088794283/9_8XbaF9c.png" alt="Everything-HackathonDec2021.drawio (1).png" /></p>
<p>I am going to talk about a redacted and miniature version of what I built, but overall the same concepts would apply. By no means these are production ready 😋</p>
<h2 id="heading-building-blocks">Building blocks</h2>
<h3 id="heading-step-1-expose-an-azure-function-to-push-text-as-events">Step 1 - Expose an Azure function to push text as events</h3>
<p>Inside your Azure function app,
Navigate to <code>Development Tools</code> &gt; <code>Advanced Tools</code>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640089395457/2QUbhXcAE.png" alt="image.png" /></p>
<p>That should open up <code>kudu service</code> that runs your function app</p>
<p>Navigate to <code>Debug Console</code> &gt; <code>CMD</code>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640090060624/tIUOjUR4B.png" alt="image.png" /></p>
<p>Find <code>wwwroot</code> sub folder and add a <code>SampleLog.txt</code> there (put whatever content you would want to send as events)</p>
<p>With our log file in place, lets create a function to access it.</p>
<p>Head back to functions tab and create a function 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640090170040/0ZZuvkSnw.png" alt="image.png" />
Select a HTTP trigger template, since we need an API </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640090278771/msa7c6qt5h.png" alt="image.png" /></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Net;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;
<span class="hljs-keyword">using</span> Microsoft.Extensions.Primitives;
<span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-keyword">using</span> System.IO;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Run</span>(<span class="hljs-params">HttpRequest req, ILogger log, ExecutionContext context</span>)</span>
{
    <span class="hljs-keyword">var</span> sampleLogPath = System.IO.Path.Combine(context.FunctionDirectory, <span class="hljs-string">"..\\SampleLog.txt"</span>);
    <span class="hljs-keyword">var</span> allText = <span class="hljs-keyword">await</span> File.ReadAllTextAsync(sampleLogPath);
    req.HttpContext.Response.Headers.Add(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/event-stream"</span>);
    <span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> line <span class="hljs-keyword">in</span> allText.Split(<span class="hljs-string">"\n"</span>))
    {
        <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">2000</span>);
        <span class="hljs-keyword">byte</span>[] bytes = Encoding.ASCII.GetBytes(<span class="hljs-string">$"data:<span class="hljs-subst">{line}</span>\n\n"</span>);
        <span class="hljs-keyword">await</span> req.HttpContext.Response.Body.WriteAsync(bytes);
        <span class="hljs-keyword">await</span> req.HttpContext.Response.Body.FlushAsync();
    }
}
</code></pre>
<blockquote>
<p>The response should start with <code>data:</code> and end with <code>\n\n</code>, as browsers look at this to figure that these are chunked events.</p>
</blockquote>
<h3 id="heading-step-2-expose-an-azure-function-to-send-status-updates-at-random-intervals">Step 2 - Expose an Azure function to send status updates at random intervals</h3>
<p>Create another function, select the HTTP trigger template again</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Net;
<span class="hljs-keyword">using</span> Microsoft.AspNetCore.Mvc;
<span class="hljs-keyword">using</span> Microsoft.Extensions.Primitives;
<span class="hljs-keyword">using</span> System.Text;
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Run</span>(<span class="hljs-params">HttpRequest req, ILogger log</span>)</span>
{
    <span class="hljs-keyword">string</span>[] states =
    {
        <span class="hljs-string">"Lorem"</span>, <span class="hljs-string">"Ipsum"</span>, <span class="hljs-string">"is"</span>, <span class="hljs-string">"simply"</span>, <span class="hljs-string">"dummy"</span>, <span class="hljs-string">"text"</span>, <span class="hljs-string">"of "</span>, <span class="hljs-string">"the"</span>, <span class="hljs-string">"printing"</span>, <span class="hljs-string">"and"</span>, <span class="hljs-string">"typesetting"</span>, <span class="hljs-string">"industry"</span>
    };
    req.HttpContext.Response.Headers.Add(<span class="hljs-string">"Content-Type"</span>, <span class="hljs-string">"text/event-stream"</span>);
    Random random = <span class="hljs-keyword">new</span> Random();           
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">short</span> i = <span class="hljs-number">0</span>; i &lt; states.Length; i++)
    {
        <span class="hljs-keyword">await</span> Task.Delay(random.Next(<span class="hljs-number">5</span>, <span class="hljs-number">15</span>) * <span class="hljs-number">1000</span>);
        <span class="hljs-keyword">byte</span>[] bytes = Encoding.ASCII.GetBytes(<span class="hljs-string">$"data:<span class="hljs-subst">{states[i]}</span>\n\n"</span>);
        <span class="hljs-keyword">await</span> req.HttpContext.Response.Body.WriteAsync(bytes);
        <span class="hljs-keyword">await</span> req.HttpContext.Response.Body.FlushAsync();
    }
}
</code></pre>
<p>Our backend APIs are ready and serving data now.</p>
<h3 id="heading-step-3-create-a-simple-static-page-that-has-logic-to-consume-both-the-events">Step 3 - Create a simple static page that has logic to consume both the events</h3>
<blockquote>
<p>Do make sure to replace the eventsource endpoints, I may delete my function app after a while</p>
</blockquote>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css"</span> <span class="hljs-attr">integrity</span>=<span class="hljs-string">"sha512-Fo3rlrZj/k7ujTnHg4CGR2D7kSs0v4LLanw2qksYuRlEzO+tcaEPQogQ0KaoGN26/zrn20ImR1DfuLWnOo7aBA=="</span> <span class="hljs-attr">crossorigin</span>=<span class="hljs-string">"anonymous"</span> <span class="hljs-attr">referrerpolicy</span>=<span class="hljs-string">"no-referrer"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>  
<span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fas fa-file-alt fa-2x"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"streamlog()"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">i</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"fas fa-tasks fa-2x"</span> <span class="hljs-attr">onclick</span>=<span class="hljs-string">"streamevent()"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">i</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"cards"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card-columns"</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">streamlog</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> cards = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"cards"</span>);
    <span class="hljs-keyword">var</span> cardHtml = <span class="hljs-string">'&lt;div class="card" style="background-color: #343a40!important; width:500px; height:300px; overflow-y: scroll;"&gt;&lt;div class="card-header" style="background: #343a40; color:white"&gt;Log&lt;/div&gt;&lt;div class="card-body" style="background: #343a40; color: yellow"&gt;&lt;p id="log"&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;'</span>
    cards.insertAdjacentHTML(<span class="hljs-string">"beforeend"</span>, cardHtml);
    <span class="hljs-keyword">var</span> logSource = <span class="hljs-keyword">new</span> EventSource(<span class="hljs-string">'https://kd-playground-functionapp.azurewebsites.net/api/StreamLogs?code=MuFPYxFQhc1q7CaxM2X8e8PLoJGoJWpo/8QUWABctC1g7WCObi9cOQ=='</span>);
    logSource.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) 
    </span>{
        <span class="hljs-keyword">var</span> element = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'log'</span>);
        <span class="hljs-keyword">if</span> (element)
        {
            element.textContent += <span class="hljs-string">"&lt;br&gt;"</span> + event.data;
        }
    };
}
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">streamevent</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">var</span> cards = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"cards"</span>);
    <span class="hljs-keyword">var</span> cardHtml = <span class="hljs-string">'&lt;div class="card" style="width:200px; height:300px;border:1px; background-color:#311b92;"&gt;&lt;div class="card-header" style="color:white"&gt;Event Status&lt;/div&gt;&lt;div class="card-body"&gt;&lt;p id="status"&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;'</span>
    cards.insertAdjacentHTML(<span class="hljs-string">"beforeend"</span>, cardHtml);
    <span class="hljs-keyword">var</span> logSource = <span class="hljs-keyword">new</span> EventSource(<span class="hljs-string">'https://kd-playground-functionapp.azurewebsites.net/api/HttpTrigger1?code=5C8YjKcM2D3Oj10iAq8F3BLHwnzkjNHMS24mac4tkG8pwxnP1ZGjzA=='</span>);
    logSource.onmessage = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">event</span>) 
    </span>{
        <span class="hljs-keyword">var</span> element = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">'status'</span>);
        <span class="hljs-keyword">if</span> (element)
        {
            element.textContent += <span class="hljs-string">"&lt;br&gt;"</span> + event.data;
        }
    };
}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<h3 id="heading-step-4-create-a-repository-in-github-and-push-the-html-file">Step 4 - Create a repository in GitHub and push the html file</h3>
<p>This should be pretty straight forward.</p>
<h3 id="heading-step-5-serve-html-pages-via-digitalocean">Step 5 - Serve html pages via DigitalOcean</h3>
<p><strong><em>You can use your preferred platform too</em></strong></p>
<p>You should be able to create a DigitalOcean account using GitHub. They do give a 100$ free credit but in any case I think 3 static pages are free 😎</p>
<ul>
<li><strong>Create a new app, select source as GitHub</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640093704307/Gx8XvzihA.png" alt="image.png" /></li>
<li><strong>Select your repository and branch</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640094063129/WWaJS79R0.png" alt="image.png" /></li>
<li><strong>Name your static site</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640096530173/gRLBE0For.png" alt="image.png" /></li>
<li><strong>Select starter pack and launch</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640094387593/ZlF3t39w_.png" alt="image.png" /></li>
<li><strong>Once the build completes we should have our page deployed at a public URL</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640096730418/vUIHje95X.png" alt="image.png" /></li>
<li><strong>Dont forget to add a CORS entry in your Azure function app for this URL</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1640096906302/PocJoM-7o.png" alt="image.png" /></li>
</ul>
<h2 id="heading-final-outcome">Final outcome</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1644327070343/MZaiGLcV_.gif" alt="final_62026d026b89e200619ed6e2_632053.gif" /></p>
<ul>
<li>By default, if the connection between the client and server closes, the <code>connection is restarted</code>, until it is explicitly closed by the client.</li>
<li><code>Multiple events</code> can be transferred over the same channel.</li>
<li><code>Different events</code> can be transferred over the same channel.</li>
</ul>
<h2 id="heading-break-down-of-24hrs">Break down of 24hrs</h2>
<ul>
<li>~10% spent on wrapping my head around what I wanted to build, feasibility in my mind</li>
<li>~20% spent on creating and testing azure functions</li>
<li>~40% spent on front end code :( i hate css</li>
<li>~20% spent on bringing it all together and e2e testing</li>
<li>~10% on prep for demo</li>
<li>Also I did some basic research even before hackathon day 🤓</li>
</ul>
<h2 id="heading-few-takeaways">Few takeaways</h2>
<ul>
<li>Make sure to ensure feasibility, you don't want to bang your head and end up pivoting, no harm in doing some <code>research</code>.</li>
<li>Keep accounts created beforehand with <code>max max max access</code>. </li>
<li><code>Jump straight into demo</code>, do not build fancy presentations, there is no point if you cant showcase what you were able to build.</li>
<li>Keep some <code>buffer for questions</code>, more questions mean people actually are interested and find value, <strong>OR</strong> they just didn't get it, in any case you get to explain them again. </li>
</ul>
<h2 id="heading-resources">Resources</h2>
<ol>
<li>Mozilla documentation on <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events">Server sent events</a></li>
<li>Checkout <a target="_blank" href="https://try.digitalocean.com/freetrialoffer/">DigitalOcean</a></li>
<li>Checkout <a target="_blank" href="https://azure.microsoft.com/en-us/services/functions/">Azure functions</a></li>
</ol>
]]></content:encoded></item><item><title><![CDATA[Cancellation token multifold]]></title><description><![CDATA[This post is a continuation of my previous one Cancellation token and APIs😇  
You should check that out for an intro to cancellation tokens and how we can use them in APIs.
In this post we will take a step further and take a look at 

How to cancel ...]]></description><link>https://blog.debbarma.in/cancellation-token-multifold</link><guid isPermaLink="true">https://blog.debbarma.in/cancellation-token-multifold</guid><category><![CDATA[dotnet]]></category><category><![CDATA[dotnetcore]]></category><category><![CDATA[C#]]></category><category><![CDATA[backend]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[kndb]]></dc:creator><pubDate>Sat, 27 Nov 2021 16:04:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638026780552/2CPt-nVl2.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This post is a continuation of my previous one <a target="_blank" href="https://blog.kndb.in/cancellation-token-and-apis">Cancellation token and APIs</a>😇  </p>
<p>You should check that out for an intro to cancellation tokens and how we can use them in APIs.</p>
<p>In this post we will take a step further and take a look at </p>
<ul>
<li>How to cancel multiple tasks using the same cancellation token</li>
<li>Link multiple token sources<ol>
<li>Track multiple cancellation tokens simultaneously so that we can cancel a task if either token requests cancellation</li>
<li>Parent token, child token scenarios</li>
</ol>
</li>
</ul>
<h3 id="heading-cancel-multiple-tasks-using-the-same-cancellation-token">Cancel multiple tasks using the same cancellation token</h3>
<p>This one is pretty straight forward, we pass on the <code>same token</code> to <code>multiple tasks</code>, if cancellation is requested, all tasks are cancelled.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"~/longoperation"</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">LongRunningOperation</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
    _logger.LogInformation(<span class="hljs-string">"Calling long running operations"</span>);

    Task one = LongRunningOperationOneAsync(token);
    Task two = LongRunningOperationTwoAsync(token);
    <span class="hljs-keyword">await</span> Task.WhenAll(one, two);

    _logger.LogInformation(<span class="hljs-string">"Done with long running operations"</span>);
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">LongRunningOperationOneAsync</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
    <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">1000</span>);
    <span class="hljs-keyword">if</span> (token.IsCancellationRequested)
    {
        _logger.LogError(<span class="hljs-string">"LongRunningOperationOneAsync was cancelled"</span>);
    }
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">LongRunningOperationTwoAsync</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
    <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">1000</span>);
    <span class="hljs-keyword">if</span> (token.IsCancellationRequested)
    {
        _logger.LogError(<span class="hljs-string">"LongRunningOperationTwoAsync was cancelled"</span>);
    }
}
</code></pre>
<p>After I initiated the request using <code>Postman</code>, I immediately hit <code>cancel</code> and this is how the application behaves.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638023297523/DvQD8JlzR.png" alt="image.png" /></p>
<p>When a cancellation request was encountered, both tasks processed it.</p>
<h3 id="heading-link-multiple-token-sources">Link multiple token sources</h3>
<p>⚡ <strong>Track multiple cancellation tokens simultaneously</strong>  </p>
<p>Leverage <code>CreateLinkedTokenSource</code> to combine multiple tokens and build a <code>CancellationTokenSource</code>. This tokensource would start monitoring cancellation in any of the encapsulating tokens.</p>
<p>In our case, we created a new CancellationTokenSource and set it up to auto <code>cancel</code> after <code>500ms</code>, and then we also have the token that is <code>injected</code> via the <code>API request</code>. We make use of CreateLinkedTokenSource method to generate a new CancellationTokenSource from the 2 tokens, which is then used further in our long running operation.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"~/longoperation"</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">LongRunningOperation</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
    CancellationTokenSource otherTokenSource = <span class="hljs-keyword">new</span> CancellationTokenSource();
    otherTokenSource.CancelAfter(<span class="hljs-number">500</span>); 

    <span class="hljs-comment">// create a new tokensource out of available 2 cancellation tokens</span>
    CancellationTokenSource tokenSourceToUse = CancellationTokenSource.CreateLinkedTokenSource(token, otherTokenSource.Token);

    _logger.LogInformation(<span class="hljs-string">"Calling long running operation"</span>);
    <span class="hljs-keyword">await</span> LongRunningOperationOneAsync(tokenSourceToUse.Token);
    _logger.LogInformation(<span class="hljs-string">"Done with long running operation"</span>);
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">LongRunningOperationOneAsync</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
    <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">1000</span>);
    <span class="hljs-keyword">if</span> (token.IsCancellationRequested)
    {
        _logger.LogError(<span class="hljs-string">"LongRunningOperationOneAsync was cancelled"</span>);
    }
}
</code></pre>
<p>After I initiated the request using <code>Postman</code>, I waited for sometime and this is how the application behaves.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638023553887/l3k9EoNKj.png" alt="image.png" /></p>
<p>Since our token triggers cancellation after <code>500ms</code> automatically, our long running operation gets cancelled.</p>
<p>⚡ <strong>Parent token, child token scenarios</strong>  </p>
<p>There are times when you would want to <code>cancel child tasks</code> but <code>continue your parent tasks</code>. For cases like these, we again leverage an overload of the <code>CreateLinkedTokenSource</code> method.</p>
<pre><code class="lang-csharp">[<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"~/longoperation"</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">LongRunningOperation</span>(<span class="hljs-params">CancellationToken parentToken</span>)</span>
{
    <span class="hljs-comment">// create a tokensource out of parentToken</span>
    CancellationTokenSource childTokenSource = CancellationTokenSource.CreateLinkedTokenSource(parentToken);
    childTokenSource.CancelAfter(<span class="hljs-number">500</span>);

    _logger.LogInformation(<span class="hljs-string">"Calling long running operation"</span>);
    <span class="hljs-keyword">await</span> LongRunningOperationOneAsync(childTokenSource.Token);
    <span class="hljs-keyword">if</span> (!parentToken.IsCancellationRequested)
    {
        _logger.LogInformation(<span class="hljs-string">"Parent cancellation was never requested, continue processing 100 other operations"</span>);
    }
    _logger.LogInformation(<span class="hljs-string">"Done with long running operation"</span>);
}

<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">LongRunningOperationOneAsync</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
    <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">1000</span>);
    <span class="hljs-keyword">if</span> (token.IsCancellationRequested)
    {
        _logger.LogError(<span class="hljs-string">"Child cancellation was requested"</span>);
    }
}
</code></pre>
<p>After I initiated the request using <code>Postman</code>, I waited for sometime and this is how the application behaves.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638024731530/wFZUwf2Em.png" alt="image.png" /></p>
<p>Since our child token triggers cancellation after <code>500ms</code> automatically, our child task gets cancelled, but our parent token still continues to be available.</p>
<p>💡 Note</p>
<blockquote>
<p>If parent token is cancelled, all child tokens will be cancelled automatically.</p>
</blockquote>
<p>The <code>Task Parallel Library</code> provides us with a wide range of easy to use extensions around cancellation tokens, we can setup cancellation behavior for various mix and matches. </p>
<p><img src="https://media.giphy.com/media/l2JJHgjz1uaEncXew/giphy.gif" alt="image" /></p>
<p>I hope this post gave you some insights on how we can leverage CancellationTokens. Thank you for reading. Cheers!</p>
]]></content:encoded></item><item><title><![CDATA[Cancellation token and APIs]]></title><description><![CDATA[Ever encountered a situation where you got frustrated with an unresponsive website/app and you hit the refresh button.

Of course you have. Its 2021 and everyone wants instant gratification.
On the Web, the end user always has the cancel/refresh butt...]]></description><link>https://blog.debbarma.in/cancellation-token-and-apis</link><guid isPermaLink="true">https://blog.debbarma.in/cancellation-token-and-apis</guid><category><![CDATA[dotnet]]></category><category><![CDATA[dotnetcore]]></category><category><![CDATA[C#]]></category><category><![CDATA[backend]]></category><category><![CDATA[APIs]]></category><dc:creator><![CDATA[kndb]]></dc:creator><pubDate>Sat, 20 Nov 2021 14:10:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638026903640/2cwhI8gfT.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Ever encountered a situation where you got frustrated with an <code>unresponsive</code> website/app and you hit the <code>refresh button</code>.
<img src="https://media.giphy.com/media/G7iGNzr3VBING/giphy.gif" alt="abort" />
Of course you have. Its 2021 and everyone wants instant gratification.</p>
<p>On the Web, the end user always has the cancel/refresh button at their disposal, and they wont hesitate to use it. But what about the process that was initiated on the server side? How do we as <code>backend devs</code> take care of that, we don't want to keep on processing a <code>cancelled operation</code> and <code>exhaust</code> our resources, do we?</p>
<p>In this post we will take a look at cancellation tokens in .NET and how we can leverage them for situations just like these.</p>
<h2 id="heading-cancellation-tokens">Cancellation tokens</h2>
<p>Cancellation tokens or the cancellation model in general belong to the <code>Task Parallel Library</code>. The library provides us a Type called <code>CancellationTokenSource</code> which encapsulates a <code>CancellationToken</code> object within it. CancellationTokenSource also provides us with other extensions to manage a cancelled operation.</p>
<p>On a high level, to make use of the cancellation model we need to do the following</p>
<ul>
<li>Run our logic inside a Task, this would accept a cancellation token</li>
<li>We keep on monitoring for cancellation requests by taking a look at the cancellation token and handle them gracefully</li>
<li>From outside our logic, some other operation informs our task that a cancellation is requested</li>
</ul>
<p>Now since we are dealing with APIs in this post, there is no need for us to manage CancellationTokenSource as it is <code>inherently injected</code> by the framework as part of each request. All we have to do is manage the cancellation token.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1637405253841/6aeXJlaIL.png" alt="image.png" /></p>
<p>Lets take a look at some snippets where we will pass CancellationToken as a parameter to our API endpoint. There is no need to build or manage the CancellationTokenSource.</p>
<p>⚡<strong>Make use of framework methods which accept cancellation tokens</strong></p>
<pre><code class="lang-csharp">[<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"~/longoperation"</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;ActionResult&gt; <span class="hljs-title">AnnoyingLongRunningOperation</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
     <span class="hljs-keyword">try</span>
     {
            _logger.LogInformation(<span class="hljs-string">"Calling long running operation"</span>);
            <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">1000000000</span>, token); <span class="hljs-comment">// our annoying long running task</span>
            _logger.LogInformation(<span class="hljs-string">"Done with long running operation"</span>);
     }
     <span class="hljs-keyword">catch</span> (OperationCanceledException ex)
     {
          <span class="hljs-comment">// handle ex</span>
          _logger.LogError(<span class="hljs-string">"Long running operation was cancelled"</span>);
     }
     <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> OkObjectResult(<span class="hljs-string">"Done!"</span>);
}
</code></pre>
<p>After I initiated the request using <code>Postman</code>, I immediately hit <code>cancel</code> and this is how the application behaves.
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1637403981002/YrInTtwfd.png" alt="image.png" />
As you can see, <code>Task.Delay()</code> throws an <code>OperationCanceledException</code> as soon as it encounters a cancellation request (it has its own logic to dispose objects etc), and we can handle that exception gracefully in our logic.</p>
<blockquote>
<p>Likewise, we can leverage alot of framework methods which already accept cancellation tokens.</p>
</blockquote>
<p>⚡<strong>Write your own method which accepts a cancellation token</strong></p>
<pre><code class="lang-csharp">[<span class="hljs-meta">HttpPost(<span class="hljs-meta-string">"~/longoperation"</span>)</span>]
<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task&lt;ActionResult&gt; <span class="hljs-title">AnnoyingLongRunningOperation</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
    <span class="hljs-keyword">try</span>
    {
        _logger.LogInformation(<span class="hljs-string">"Calling long running operation"</span>);
        <span class="hljs-keyword">await</span> ActualAnnoyingLongRunningOperationAsync(token);
        _logger.LogInformation(<span class="hljs-string">"Done with long running operation"</span>);
    }
    <span class="hljs-keyword">catch</span> (OperationCanceledException ex)
    {
        <span class="hljs-comment">// handle ex</span>
        _logger.LogError(<span class="hljs-string">"Long running operation was cancelled"</span>);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> OkObjectResult(<span class="hljs-string">"Done!"</span>);
}
<span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">ActualAnnoyingLongRunningOperationAsync</span>(<span class="hljs-params">CancellationToken token</span>)</span>
{
    <span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i&lt;<span class="hljs-number">100</span>;i+=<span class="hljs-number">2</span>)
    {
        _logger.LogInformation(<span class="hljs-string">$"Loop counter : <span class="hljs-subst">{i}</span>"</span>);
        <span class="hljs-keyword">await</span> Task.Delay(<span class="hljs-number">100</span>); <span class="hljs-comment">// 100 important operations</span>
    }
    token.ThrowIfCancellationRequested();
    <span class="hljs-comment">// 100 other important operations</span>
}
</code></pre>
<p>Again, after I initiated the request using <code>Postman</code>, I immediately hit <code>cancel</code> and this is how the application behaves now.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1637412232025/-mHDH1p8B.png" alt="image.png" />
This time you can see that we have managed cancellation on our own terms, we have made sure the loop runs completely(could represent some necessary backend job etc) before cancellation is processed.</p>
<p>In both the cases, the task that was consuming needless server resources, was <code>disposed</code> from the pool. </p>
<p>Cancellation model is an easy and neat feature we should always look out for implementing in our projects and I hope this post gave you some insights. </p>
<p>Thank you for reading. Cheers!</p>
<p>Take a look at my other post <a target="_blank" href="https://blog.kndb.in/cancellation-token-multifold">Cancellation token multifold</a> 😇 which talks about different mix and matches of cancellation token usage.</p>
]]></content:encoded></item><item><title><![CDATA[Code reviews - Used to hate them, not anymore]]></title><description><![CDATA[Developers = Crazy individuals with mild OCD. 
Individuals who are particular about their operating system, the editor they use, the way they use language constructs. 
In this post, I am going to talk about how this craziness make code reviews even c...]]></description><link>https://blog.debbarma.in/code-reviews-used-to-hate-them-not-anymore</link><guid isPermaLink="true">https://blog.debbarma.in/code-reviews-used-to-hate-them-not-anymore</guid><category><![CDATA[code review]]></category><category><![CDATA[C#]]></category><category><![CDATA[Text Editors]]></category><category><![CDATA[asp.net core]]></category><category><![CDATA[clean code]]></category><dc:creator><![CDATA[kndb]]></dc:creator><pubDate>Sat, 02 Oct 2021 17:11:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633194337303/-G6dvhZIa.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Developers = Crazy individuals with mild OCD. </p>
<p>Individuals who are particular about their operating system, the editor they use, the way they use language constructs. </p>
<p>In this post, I am going to talk about how this craziness make code reviews even crazier. A real pain in the 🍑</p>
<h2 id="heading-hello-madness">Hello madness</h2>
<p>Imagine 10 such individuals working on a project, everybody having their own set of preferences. </p>
<ul>
<li>Some prefer curly braces inline, some on next line.</li>
<li>Some prefer a space before their if parenthesis and some don't.</li>
<li>Some prefer space before and after their logical operations, some want them to be as compact as possible.</li>
<li>You get the point..</li>
</ul>
<p>As a reviewer, this is what you might end up seeing during code reviews.  Where the hell is the actual code change?
Also in my head -&gt; BC 🤬 ???</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633182291327/l-ad28TL2.png" alt="image.png" /></p>
<p>While I have never played Waldo, I have seen memes on the internet, and it was the first thing that came to my mind when I got my first "crazy" pull request to review</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633181459839/L1nJ5Qrha.png" alt="image.png" /></p>
<p>Having consistent coding styles within a team is critical, every developer in the team should agree to use the language features the same way and that would make a reviewers life so much easy. But how do you enforce this? We'll take a look at that in our next section.</p>
<p>If you are still trying to figure what the code change was, here it is</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633185919630/Um9k4He95.png" alt="image.png" />
<strong><em>Which again, does not make any sense, <code>++i</code> and <code>i++</code> within the context of a <code>for</code> loop is the same.</em></strong></p>
<h2 id="heading-how-do-we-enforce-code-consistency">How do we enforce code consistency?</h2>
<p>⭐EditorConfig⭐</p>
<p>This sleek little configuration file helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. </p>
<p>😋 <strong>The best parts</strong>  </p>
<ul>
<li><code>Multiple editor</code> support.</li>
<li>Works with a <code>wide range of file types</code>.</li>
<li>These settings <code>take precedence over your editor settings</code>, which means that you can enforce consistent coding styles for your code base, settings that are specific to a repository. </li>
</ul>
<p>🧱 <strong>To create one </strong>  <em>(I am going to use Visual Studio since that's my preferred IDE, your favorite IDE should have similar steps)</em></p>
<ul>
<li><p>All you have to do is right click on your project solution and add a new editorconfig
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1633186699297/F03kGGh_F.png" alt="image.png" />
This will pick all the editor settings you have in your Visual Studio instance and put it into a .editorconfig file inside your codebase. You can now push this to your remote repository. You should also get in touch with your fellow developers and make sure all are in agreement with the settings in place. As soon as they pull this file to their local, their preferences will be overridden.</p>
</li>
<li><p>You could also go to Github, search for .editorconfig and take a look at how others have them created in their repositories. </p>
</li>
</ul>
<p>😩 <strong>Caveat in Visual Studio</strong><br />Editorconfig settings are <code>not used automatically</code> in Visual Studio, you will have to execute code cleanup each time. You could install <code>extensions</code> which would run <code>code cleanup</code> on <code>save operation</code> to overcome this. In my opinion Microsoft should make this a default behavior.</p>
<p>Editorconfig has made code reviews much more simpler for me and my team, makes it much more bearable now 😜, highly recommended.</p>
<p>Thank you for going through this post. I hope you found it useful. Cheers!</p>
<p>Extra Resources</p>
<ul>
<li><a target="_blank" href="https://softwareengineering.stackexchange.com/questions/2715/should-curly-braces-appear-on-their-own-line">People arguing over curly braces inline vs newline</a>🧐</li>
<li><a target="_blank" href="https://editorconfig.org/">EditorConfig website</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Your services will fail, but you can do something about it]]></title><description><![CDATA[You read it right, go ahead and search for faulted errors, socket exceptions in your favorite instrumentation tool (azure application insights, new relic etc), there is a very high chance you are going to find few of these logged.
Here is a snippet f...]]></description><link>https://blog.debbarma.in/your-services-will-fail-but-you-can-do-something-about-it</link><guid isPermaLink="true">https://blog.debbarma.in/your-services-will-fail-but-you-can-do-something-about-it</guid><category><![CDATA[asp.net core]]></category><category><![CDATA[Microservices]]></category><category><![CDATA[backend]]></category><category><![CDATA[C#]]></category><category><![CDATA[error handling]]></category><dc:creator><![CDATA[kndb]]></dc:creator><pubDate>Wed, 29 Sep 2021 21:35:41 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1633022326019/y2wYu0FIf.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You read it right, go ahead and search for <code>faulted errors</code>, <code>socket exceptions</code> in your favorite instrumentation tool (azure application insights, new relic etc), there is a very high chance you are going to find few of these logged.</p>
<p>Here is a snippet from one of our sandbox application insights
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632593722332/9oNXetwjW.png" alt="image.png" /></p>
<h2 id="heading-the-criminal">The criminal</h2>
<p><strong>Transient failures</strong> </p>
<p><img src="https://media.giphy.com/media/JsE9qckiYyVClQ5bY2/giphy.gif?cid=ecf05e47gwt6fxfij0ewnytv3mcgmcuqom8hrggy0hwhbu29&amp;rid=giphy.gif&amp;ct=g" alt="asd" /></p>
<p>These failures can occur anytime, <code>irrespective of the platform</code>, the <code>operating system</code>, the <code>programming language</code> you are using to build your application. On a bad day, your application would simply not respond to key actions giving an impression to the end user that the system in place is highly unreliable.</p>
<p>There could be various reasons for such kind of failures, <code>network issues</code>, <code>temporary unavailable services</code>, server not able to respond in time(<code>timeouts</code>), some idiot spilled coffee on the server where your service is hosted etc.</p>
<p>With a paradigm shift towards <code>cloud</code>, these kind of errors have become more and more prominent. You are not going to get rid of them, but you could make your system more resilient and fault tolerant to such kind of failures.</p>
<p>💡 Note</p>
<blockquote>
<p>They are often self-correcting, if the action is repeated again it is likely to succeed. </p>
</blockquote>
<p>On your SSR enabled react app, you could notify the user to wait for sometime and try again, but microservices/components behind the scenes communicate with each other all the time, strategies have to be in-place beforehand, manual intervention just wont work in this case.</p>
<h2 id="heading-polly">Polly</h2>
<p>Enter <a target="_blank" href="https://github.com/App-vNext/Polly">Polly</a> - A library that enables resilience and transient-fault-handling in your <code>.NET application</code>.</p>
<p>I am going to talk about 3 types of policies that I have used in my projects.</p>
<ol>
<li>Fixed amount of retries but retry after an interval</li>
<li>Fixed amount of retries but retry with exponential backoff</li>
<li>Circuit breaker policy</li>
</ol>
<h3 id="heading-base-setup">Base setup</h3>
<p>I exposed a throttled api which accepts only <code>2 requests in 10sec from a particular IP address</code>. The API would respond with a 429 response code and a message. We will call this API continuously and see behaviour as a result of polly policies.</p>
<p><strong>Behavior without any policy in place</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632946467540/BumS8X4Fn.gif" alt="final_6154aee2ad89470077c10ddf_27415.gif" /></p>
<p>💡 Note</p>
<blockquote>
<p>In production environments, the behavior would be one failure and we are done, no further execution.</p>
</blockquote>
<h3 id="heading-fixed-amount-of-retries-but-retry-after-an-interval">Fixed amount of retries but retry after an interval</h3>
<p>⚙️ <strong>Setup in place</strong><br />If response code is 429(too many requests) -&gt; <code>retry 3 times</code>, wait for <code>2 sec before each retry</code>.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> asyncRetryPolicy = Policy.HandleResult&lt;HttpResponseMessage&gt;(r =&gt; r.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
                   .WaitAndRetryAsync(
                    <span class="hljs-number">3</span>,  
                    (retryNumber) =&gt; TimeSpan.FromSeconds(<span class="hljs-number">2</span>),    
                    (exception, attemptTimespan) =&gt;
                    {
                            Console.WriteLine(<span class="hljs-string">$"[Polly] - Encountered an error: \"<span class="hljs-subst">{ response.Result.Content.ReadAsStringAsync().Result}</span>\" - Retrying after <span class="hljs-subst">{attemptTimespan.TotalSeconds}</span> sec."</span>);
                    });
<span class="hljs-comment">// run in loop</span>
<span class="hljs-keyword">await</span> asyncRetryPolicy.ExecuteAsync(<span class="hljs-keyword">async</span> () =&gt; <span class="hljs-keyword">await</span> httpClient.GetAsync(<span class="hljs-string">"endpoint"</span>));
</code></pre>
<p><strong>Behavior with policy in place</strong> 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632947692250/PkSwged4Q.gif" alt="final_6154aee2ad89470077c10ddf_910190.gif" /></p>
<h3 id="heading-fixed-amount-of-retries-but-retry-with-exponential-backoff">Fixed amount of retries but retry with exponential backoff</h3>
<p>⚙️ <strong>Setup in place</strong><br />If response code is 429(too many requests) -&gt; <code>retry 3 times</code>, 1st retry after <code>2 sec</code>, second retry after <code>4 sec</code>, third retry after <code>8 sec</code>.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> asyncRetryPolicy = Policy.HandleResult&lt;HttpResponseMessage&gt;(r =&gt; r.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
                   .WaitAndRetryAsync(
                    <span class="hljs-number">3</span>,    
                    (retryNumber) =&gt; TimeSpan.FromSeconds(Math.Pow(<span class="hljs-number">2</span>, retryNumber)), 
                    (exception, attemptTimespan) =&gt;  
                    {
                            Console.WriteLine(<span class="hljs-string">$"[Polly] - Encountered an error: \"<span class="hljs-subst">{ response.Result.Content.ReadAsStringAsync().Result}</span>\" - Retrying after <span class="hljs-subst">{attemptTimespan.TotalSeconds}</span> sec."</span>);
                    });
<span class="hljs-comment">// run in loop</span>
<span class="hljs-keyword">await</span> asyncRetryPolicy.ExecuteAsync(<span class="hljs-keyword">async</span> () =&gt; <span class="hljs-keyword">await</span> httpClient.GetAsync(<span class="hljs-string">"endpoint"</span>));
</code></pre>
<p><strong>Behavior with policy in place</strong>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632944441107/IuEUSGp78.gif" alt="final_6154aee2ad89470077c10ddf_371182.gif" /></p>
<h3 id="heading-circuit-breaker-policy">Circuit breaker policy</h3>
<p>⚙️ <strong>Setup in place</strong><br />If response code is 429(too many requests) -&gt;  And it happens for <code>3 times consecutively</code>, <code>open the circuit for 10 sec</code> so that no further API calls can go through.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> circuitBreakerPolicy = Policy.HandleResult&lt;HttpResponseMessage&gt;(r =&gt; r.StatusCode == System.Net.HttpStatusCode.TooManyRequests)
           .CircuitBreakerAsync(<span class="hljs-number">3</span>, TimeSpan.FromSeconds(<span class="hljs-number">10</span>),
            (response, attemptTimespan) =&gt; 
            {
                       Console.WriteLine(<span class="hljs-string">"[Polly] - Circuit is open for 10 sec."</span>);
             },
             () =&gt;
             {
                       Console.WriteLine(<span class="hljs-string">"[Polly] - Circuit closed, requests flow normally."</span>);
             });
<span class="hljs-comment">// run in loop</span>
<span class="hljs-keyword">await</span> circuitBreakerPolicy .ExecuteAsync(<span class="hljs-keyword">async</span> () =&gt; <span class="hljs-keyword">await</span> httpClient.GetAsync(<span class="hljs-string">"endpoint"</span>));
</code></pre>
<p><strong>Behavior with policy in place</strong> 
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1632944527778/LpNzZln1e.gif" alt="final_6154aee2ad89470077c10ddf_213348.gif" /></p>
<p>In this post, I created a policy around the 429 http response code but you can write your policies around any kind of transient fault, or any kind of http response code(even treat 200 response as a failure 🙃 and do something about it) its all configurable. Polly provides a lot of resiliency options. Do check out their GitHub page <a target="_blank" href="https://github.com/App-vNext/Polly">here</a>.</p>
<p>Thank you for going through this post. I hope you had some takeaways from it. Cheers!</p>
]]></content:encoded></item><item><title><![CDATA[A guide on how to setup Blazor WebAssembly with Auth0]]></title><description><![CDATA[I have had some experience working on OpenID Connect.
Exploring Auth0 has made me realize one thing, it cant get simpler than this. Setting up identity with Auth0 was a delight, most of the time I didn't even need to look at the documentation (am I b...]]></description><link>https://blog.debbarma.in/a-guide-on-how-to-setup-blazor-webassembly-with-auth0</link><guid isPermaLink="true">https://blog.debbarma.in/a-guide-on-how-to-setup-blazor-webassembly-with-auth0</guid><category><![CDATA[C#]]></category><category><![CDATA[Blazor ]]></category><category><![CDATA[Auth0]]></category><category><![CDATA[Auth0Hackathon]]></category><category><![CDATA[authorization]]></category><dc:creator><![CDATA[kndb]]></dc:creator><pubDate>Sat, 21 Aug 2021 16:38:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629563428900/pRfFL6v7b.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I have had some experience working on OpenID Connect.</p>
<p>Exploring Auth0 has made me realize one thing, it cant get simpler than this. Setting up identity with Auth0 was a delight, most of the time I didn't even need to look at the documentation (am I bragging or was the interface so user friendly?)</p>
<p>We will take a look at <strong>Stonks</strong>, a simple crypto listing app using Blazor WebAssembly and Auth0. The Blazor WebAssembly framework provides us with a frontend and a fake backend project, we will integrate Auth0 on both. From the backend logic we are going to make a call to coinapi.io to fetch a list of crypto currencies, narrow it down to a few thousand cryptos(<strong>why are there 12k+ cryptos?</strong>) and display them in our Blazor UI.</p>
<p><strong>Apps and tools</strong></p>
<ul>
<li><p>An IDE for .NET projects -&gt; VS or VSCode or Rider</p>
</li>
<li><p>Latest version of VS would automatically install <a target="_blank" href="https://dotnet.microsoft.com/download/dotnet/5.0">.NET 5</a> for us</p>
</li>
<li><p><a target="_blank" href="https://auth0.com">Auth0</a> -&gt; auth + identity</p>
</li>
<li><p><a target="_blank" href="https://www.coinapi.io">Coinapi.io</a> -&gt; fetch list of cryptos</p>
</li>
<li><p>https://jwt.io -&gt; decrypt and analyze jwt tokens</p>
</li>
</ul>
<h2 id="heading-tldr">TL;DR</h2>
<p>I have attached some demo videos on the different connection types in Auth0, their setup and behaviour. Head over to the end of the post and take a peek.</p>
<h2 id="heading-step1-bootstrap-a-blazor-project">Step1 - Bootstrap a blazor project</h2>
<p>We will create the base Blazor project first.</p>
<ol>
<li><p>Open command line</p>
</li>
<li><p>Go to the directory where you would want to create your projects, for me its<br /> <code>cd StonksApplication</code></p>
</li>
<li><p>Bootstrap the projects using <code>dotnet new blazorwasm --hosted</code>, this command will create a Client, a Server, and a Shared project for us. The final structure should look like</p>
</li>
</ol>
<pre><code class="lang-plaintext">.
├── Client           # Client project
│   ├── Pages   
│   ├── Shared
│   └── ...
├── Server           # Backend project
│   ├── Controllers                          
│   └── ...    
├── Shared           # Shared Library
│   └── ...
└── ...
</code></pre>
<ol start="4">
<li><p>Open the solution inside VisualStudio, inside cmdline <code>start StonksApplication.sln</code></p>
</li>
<li><p>One VisualStudio is up, we will go ahead and run the application</p>
</li>
</ol>
<p>For me the application loads at <strong>https://localhost:44304</strong></p>
<h2 id="heading-step2-auth0-setup">Step2 - Auth0 setup</h2>
<p>Once we have created and verified our Auth0 account, we will go ahead and setup the following</p>
<ol>
<li><p>Application</p>
</li>
<li><p>Callbacks and CORS</p>
</li>
<li><p>API resources</p>
</li>
<li><p>Users</p>
</li>
</ol>
<p><strong>Setup Application</strong><br />Since ours is a SPA we will select that type while creating.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628620901437/MyIY532TA.png" alt="image.png" /></p>
<p><strong>Setup Callbacks and CORS</strong><br />In the application settings page set the following values (the description against the setting tells us exactly they are meant for)</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629010138186/Kk-nlq5ZF.png" alt="Untitled.png" /></p>
<p>We use the same base url where our app is running<br />Allowed Callback URLs -&gt; <strong>https://localhost:44304</strong>/authentication/login-callback (this is the default blazor middleware callback path)<br />Allowed Logout URLs -&gt; <strong>https://localhost:44304</strong><br />Allowed Origins (CORS) -&gt; <strong>https://localhost:44304</strong></p>
<p><strong>Setup API resources</strong><br />For our backend API, we will go ahead and create an API resource</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628621697053/s7pRCzKoo.png" alt="image.png" /></p>
<p>Identifier -&gt; <strong>https://localhost:44304/</strong></p>
<blockquote>
<p>The identifier(a.k.a audience) is critical, and in simple words mean "this API resource can be accessed by whosoever has this identifier".</p>
</blockquote>
<p><strong>Users</strong><br />We will also go ahead and create one user under the User Management tab. We will use this user to login in our application.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629532184380/WYjk6Js4_.png" alt="image.png" /></p>
<p>Basic Auth0 configuration is now in place.</p>
<h2 id="heading-step3-configure-blazor-projects-for-auth0">Step3 - Configure Blazor projects for Auth0</h2>
<p>We will configure Auth0 for our projects</p>
<ol>
<li><p>StonksApplication.Client</p>
</li>
<li><p>StonksApplication.Server</p>
</li>
</ol>
<h3 id="heading-configure-auth0-in-client-project">Configure Auth0 in Client project</h3>
<p><em>For brevity we are going to take a look at the major code blocks/components only.</em></p>
<ul>
<li><p>Under <code>wwwroot</code> folder create a <code>appsettings.json</code> file.<br />  Add a json object which holds the following configurations from Auth0.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628934381667/cYMaY4obN.png" alt="image.png" /></p>
</li>
<li><p>Configure oidc authentication inside <code>Program.cs</code>.</p>
</li>
</ul>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>)</span>
    {
        ...
        builder.Services.AddOidcAuthentication(options =&gt;
        {
            builder.Configuration.Bind(<span class="hljs-string">"Auth0"</span>, options.ProviderOptions); 
            options.ProviderOptions.ResponseType = <span class="hljs-string">"code"</span>;
        });

        <span class="hljs-keyword">await</span> builder.Build().RunAsync();
    }
}
</code></pre>
<p>Fetch and bind configuration from <code>appsettings.json</code> using <code>builder.Configuration.Bind("Auth0", options.ProviderOptions);</code></p>
<p>Set the client to follow <code>authorization_code</code> flow using <code>options.ProviderOptions.ResponseType = "code";</code>. More on flows <a target="_blank" href="https://darutk.medium.com/diagrams-of-all-the-openid-connect-flows-6968e3990660">here</a>.</p>
<p><strong>Weird BLAZOR issue</strong></p>
<blockquote>
<p>As part of oidc configuration I should be also allowed to setup the audience property for my client, if missing, that would result into auth issues. More about it in later sections of the post, for now we move on.</p>
</blockquote>
<ul>
<li>Under <code>Pages</code> folder create <code>Authentication.razor</code> which deals with login, logout authentication actions</li>
</ul>
<pre><code class="lang-csharp">@page <span class="hljs-string">"/authentication/{action}"</span>
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@using Microsoft.Extensions.Configuration

@inject NavigationManager Navigation
@inject IConfiguration Configuration

&lt;RemoteAuthenticatorView Action=<span class="hljs-string">"@Action"</span>&gt;
    &lt;LogOut&gt;
        @{
            <span class="hljs-keyword">var</span> authority = (<span class="hljs-keyword">string</span>)Configuration[<span class="hljs-string">"Auth0:Authority"</span>];
            <span class="hljs-keyword">var</span> clientId = (<span class="hljs-keyword">string</span>)Configuration[<span class="hljs-string">"Auth0:ClientId"</span>];
            Navigation.NavigateTo(<span class="hljs-string">$"<span class="hljs-subst">{authority}</span>/v2/logout?client_id=<span class="hljs-subst">{clientId}</span>&amp;returnTo=<span class="hljs-subst">{Navigation.BaseUri}</span>"</span>);
        }
    &lt;/LogOut&gt;
&lt;/RemoteAuthenticatorView&gt;
@code{
    [<span class="hljs-meta">Parameter</span>] <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Action { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<ul>
<li>Under <code>Shared</code> folder, create <code>AccessControl.razor</code> which will have a label for username, login and logout buttons.</li>
</ul>
<pre><code class="lang-csharp">@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
@inject SignOutSessionStateManager SignOutManager

&lt;AuthorizeView&gt;
    &lt;Authorized&gt;
        Hello, @context.User.Identity.Name &amp;nbsp;
        &lt;button @onclick=<span class="hljs-string">"BeginSignOut"</span>&gt;Log <span class="hljs-keyword">out</span>&lt;/button&gt;
    &lt;/Authorized&gt;
    &lt;NotAuthorized&gt;
        &lt;button @onclick=<span class="hljs-string">"BeginSignIn"</span>&gt;Log <span class="hljs-keyword">in</span>&lt;/button&gt;
    &lt;/NotAuthorized&gt;
&lt;/AuthorizeView&gt;

@code{
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">BeginSignOut</span>(<span class="hljs-params">MouseEventArgs args</span>)</span>
    {
        <span class="hljs-keyword">await</span> SignOutManager.SetSignOutState();
        Navigation.NavigateTo(<span class="hljs-string">"authentication/logout"</span>);
    }
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">BeginSignIn</span>(<span class="hljs-params">MouseEventArgs args</span>)</span>
    {
        Navigation.NavigateTo(<span class="hljs-string">"authentication/login"</span>);
    }
}
</code></pre>
<ul>
<li>Create a new <code>Stonks.razor</code> under <code>Pages</code> folder, this is the component where we will display the list of cryptos.<br />  Mark the page with <code>Authorize</code> attribute, this will force the user to login to view this page.</li>
</ul>
<pre><code class="lang-csharp">@page <span class="hljs-string">"/stonks"</span>
@using StonksApplication.Shared
@attribute [Authorize]
</code></pre>
<h3 id="heading-configure-auth0-in-server-project">Configure Auth0 in Server project</h3>
<p><em>For brevity we are going to take a look at the major code blocks/components only</em></p>
<ul>
<li>Inside appsettings.json file add a json object which holds the following configurations from Auth0.</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628934524269/zV_Tas97p.png" alt="image.png" /></p>
<ul>
<li>Inside Startup.cs file of the project, setup authentication service</li>
</ul>
<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>
        {
            ...
            services.AddAuthentication(options =&gt;
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =&gt;
            {
                options.Authority = _configuration.GetValue&lt;<span class="hljs-keyword">string</span>&gt;(<span class="hljs-string">"Auth0:Authority"</span>);
                options.Audience = _configuration.GetValue&lt;<span class="hljs-keyword">string</span>&gt;(<span class="hljs-string">"Auth0:Audience"</span>);
            });
        }
</code></pre>
<p>Set <code>DefaultAuthenticateScheme</code> and <code>DefaultChallengeScheme</code> to <code>Bearer</code>. We want to use jwt tokens for auth inside our Server by default. Set the <code>Authority</code> and <code>Audience</code> values from appsettings.json as well.</p>
<blockquote>
<p>This setup makes sure jwt(bearer token) validations are in place.</p>
</blockquote>
<ul>
<li>Create a controller, mark the controller with the <code>Authorize</code> attribute. Only authorized requests will be allowed to go through from here on.</li>
</ul>
<pre><code class="lang-csharp">[<span class="hljs-meta">ApiController</span>]
[<span class="hljs-meta">Route(<span class="hljs-meta-string">"v1/stonks"</span>)</span>]
[<span class="hljs-meta">Authorize</span>]
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">StonksController</span> : <span class="hljs-title">ControllerBase</span>
{
       <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">StonksController</span>(<span class="hljs-params"></span>)</span>
        {
               ...
        }
}
</code></pre>
<p>With all of this in place, along with a few additional stuff like</p>
<ol>
<li><p>Attaching access tokens to API calls from Client To Server</p>
</li>
<li><p>Coinapi setup inside Server, making API calls to coinapi to fetch list of cryptos</p>
</li>
<li><p><strong>Weird Blazor issue resolution</strong></p>
</li>
<li><p>Code cleanup</p>
</li>
</ol>
<p>Here is the final result (the user was created while setting up Auth0)</p>
<iframe width="640" height="360" src="https://www.loom.com/embed/795544afd4fe478da0c0f52c6059682f"></iframe>

<p>I did spend more time exploring other connection types and super excited to share them too.<br /><strong>Had alot of wow moments along the way.</strong></p>
<ul>
<li>Enterprise OIDC(extra setup was done on remote-identity-provider to allow calls from auth0 and a different user)</li>
</ul>
<iframe width="640" height="361" src="https://www.loom.com/embed/af2be6b41b9a4553b4a8c4e99d61b6f1"></iframe>

<ul>
<li>Passwordless</li>
</ul>
<iframe width="640" height="360" src="https://www.loom.com/embed/bf2e317ff7a04751a5d901147db60d83"></iframe>

<ul>
<li>Social</li>
</ul>
<p>Placeholder for video.</p>
<p>I had a lot of fun exploring Auth0, hope you had some takeaways from it.<br />In future I do plan to write about OIDC, OAuth and experiences in my blog. Thanks!</p>
<p><strong>Additional resources</strong></p>
<ol>
<li><p>Github repo https://github.com/kndb-star/StonksApplication</p>
</li>
<li><p>Open issue in Blazor https://github.com/dotnet/aspnetcore/issues/20813</p>
</li>
</ol>
<hr />
<h2 id="heading-blazor-issue">😡 Blazor issue</h2>
<p>Calls to StonksApplication.Server kept on failing with a 401 httpstatus code.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628879831922/538lKSzvg.png" alt="image.png" /></p>
<p>After successful login, as a result of our oidc setup in StonksApplication.Client, we get a id_token and access_token from Auth0. We can clearly see something is wrong with the access token (they are usually bigger in length)  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629563103225/T7UfG3mDs.png" alt="0rwuVQ1Wl.png" /></p>
<p>As part of our login flow we couldn't pass the audience in the login request. And that was the root of all my hair pulling.<br />Copy the access token, head to https://jwt.io, and decode the same</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628882651041/jDJw_mzS1z.png" alt="image.png" /></p>
<p>We can confirm the token is invalid.<br />From Auth0 docs, one way to solve this would be to set the audience value for all applications inside our Auth0 tenant. Basically, instead of the client requesting, we force set this.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628882878130/q1mk8gQqO.png" alt="image.png" /></p>
<p>We logout and login in our StonksApplication, and this time we see a different access token.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629563348105/-1KMZfwUg.png" alt="aaaaa.png" /></p>
<p>Copy the access token, head to https://jwt.io, and decode the same again</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628931120445/hwGQe0p2Z.jpeg" alt="audience.JPG" /></p>
<p>Our API calls are going through now.</p>
<p><img src="https://media.giphy.com/media/gLFVVFawHtn9icDmZE/giphy.gif" alt="phew" /></p>
]]></content:encoded></item><item><title><![CDATA[Middlewares in .NET Core]]></title><description><![CDATA[Modern web applications, among many other things, demand

a modular approach to building components

loose-coupling between its components.


Pre .NET Core, all types of web applications in the .NET ecosystem (MVC, WebAPI, etc) were heavily dependent...]]></description><link>https://blog.debbarma.in/middlewares-in-net-core</link><guid isPermaLink="true">https://blog.debbarma.in/middlewares-in-net-core</guid><category><![CDATA[C#]]></category><category><![CDATA[dotnetcore]]></category><category><![CDATA[Beginner Developers]]></category><category><![CDATA[Middleware]]></category><dc:creator><![CDATA[kndb]]></dc:creator><pubDate>Fri, 06 Aug 2021 21:00:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1628277697980/7MDGKXvI7w.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Modern web applications, among many other things, demand</p>
<ol>
<li><p>a modular approach to building components</p>
</li>
<li><p>loose-coupling between its components.</p>
</li>
</ol>
<p>Pre .NET Core, all types of web applications in the .NET ecosystem (MVC, WebAPI, etc) were heavily dependent on the System.Web library which in turn was tightly coupled to IIS. The library tried to do too many things, did a great deal of heavy lifting behind the scenes, most of which would end up being redundant, unwanted, or unchangeable.</p>
<p>Enter "Open Web Interface for .NET" a.k.a. OWIN</p>
<h2 id="heading-owin">OWIN</h2>
<p>From their website</p>
<blockquote>
<p>OWIN defines a standard interface between .NET web servers and web applications. The goal of the OWIN interface is to decouple server and application, encourage the development of simple modules for .NET web development, and, by being an open standard, stimulate the open source ecosystem of .NET web development tools.</p>
</blockquote>
<p>OWIN specification helps create a decoupled layer that allows two frameworks with different object models to work together. Decoupling components would mean iterations would be independent, a plug-n-play option would enable small, lightweight, high-performance hosting of applications.</p>
<p>.NET Core fully supports OWIN specification, this allows .NET Core to be hosted on top of a OWIN compatible server/host or for other OWIN compatible components to run on top of .NET Core.</p>
<p>The specification also introduces something called middlewares. We will take a look at middlewares in .NET Core, the middleware pipeline, and leverage that to create a middleware of our own.</p>
<h2 id="heading-what-is-a-middleware">What is a middleware?</h2>
<p>From OWIN specification</p>
<blockquote>
<p>Middleware — Pass through components that form a pipeline between a server and application to inspect, route, or modify request and response messages for a specific purpose.</p>
</blockquote>
<p>Middleware is a code-block/logic/component that is assembled into an application pipeline to handle requests and responses. Each component</p>
<ol>
<li><p>Chooses whether to pass the request to the next component in the pipeline.</p>
</li>
<li><p>Can perform work before and after the next component in the pipeline.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628014296876/gi5wljlQW.png" alt="image.png" /></p>
<h2 id="heading-middlewares-in-net-core">Middlewares in .NET Core</h2>
<p>There are different ways to setup Middlewares in .NET Core</p>
<ol>
<li><p>Inline request delegates(which are middlewares) using <strong>Use, Run, Map</strong></p>
</li>
<li><p>Custom middleware class</p>
</li>
</ol>
<p><strong>Use</strong><br />Helps chain multiple request delegates. The next parameter represents the next delegate in the pipeline.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Startup</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Configure</span>(<span class="hljs-params">IApplicationBuilder app</span>)</span>
    {
        app.Use(<span class="hljs-keyword">async</span> (context, next) =&gt;
        {
            <span class="hljs-comment">// Do some work before calling the next middleware</span>
            <span class="hljs-keyword">await</span> next.Invoke();
            <span class="hljs-comment">// Do some work after the next middleware execution completes</span>
        });
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =&gt;
        {
            endpoints.MapRazorPages();
        });
    }
}
</code></pre>
<p><strong>Run</strong><br />Helps short-circuit the pipeline. Nothing gets executed beyond this.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Startup</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Configure</span>(<span class="hljs-params">IApplicationBuilder app</span>)</span>
    {
        app.Run(<span class="hljs-keyword">async</span> context =&gt;
        {
            <span class="hljs-keyword">await</span> context.Response.WriteAsync(<span class="hljs-string">"Allo!"</span>);
        });
        <span class="hljs-comment">// nothing beyond this gets executed</span>
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =&gt;
        {
            endpoints.MapRazorPages();
        });
    }
}
</code></pre>
<p><strong>Map</strong><br />Helps with conditional branching in the pipeline. Runs middlewares when conditions are met.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Startup</span>
{
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">HandleMyRoute</span>(<span class="hljs-params">IApplicationBuilder app</span>)</span>
    {
        app.Run(<span class="hljs-keyword">async</span> context =&gt;
        {
            <span class="hljs-keyword">await</span> context.Response.WriteAsync(<span class="hljs-string">"I was forced here."</span>);
        });
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Configure</span>(<span class="hljs-params">IApplicationBuilder app</span>)</span>
    {
        <span class="hljs-comment">// a request with path "/myroute" will branch out</span>
        app.Map(<span class="hljs-string">"/myroute"</span>, HandleMyRoute);
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =&gt;
        {
            endpoints.MapRazorPages();
        });
    }
}
</code></pre>
<p><strong>Custom middleware class</strong><br />A cleaner approach, we write our middleware logic in a separate class and then use it in our pipeline using the UseMiddleware extension. The invoke method(which takes in the HtttpContext) is important here and this is where we have our middleware logic.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MyCustomMiddleware</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> RequestDelegate _next;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyCustomMiddleware</span>(<span class="hljs-params">RequestDelegate next</span>)</span>
    {
        _next = next;
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Invoke</span>(<span class="hljs-params">HttpContext httpContext</span>)</span>
    {
        <span class="hljs-comment">// Do some work before calling the next middleware  </span>
        <span class="hljs-keyword">await</span> next(httpContext);
        <span class="hljs-comment">// Do some work after the next middleware execution completes</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Startup</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Configure</span>(<span class="hljs-params">IApplicationBuilder app</span>)</span>
    {
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        <span class="hljs-comment">// after authorization run MyCustomMiddleware</span>
        app.UseMiddleware&lt;MyCustomMiddleware&gt;();
        app.UseEndpoints(endpoints =&gt;
        {
            endpoints.MapRazorPages();
        });
    }
}
</code></pre>
<h2 id="heading-our-very-own-custom-middleware">Our very own custom middleware</h2>
<p>Let's create a custom middleware class of our own, use it in our middleware pipeline and see it in action.</p>
<p><strong>Middleware class</strong><br />Our middleware logic will catch unhandled exceptions, wrap them into a problem details object before sending back the response to the client.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">CustomExceptionMiddleware</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> RequestDelegate _next;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">bool</span> _seeStackTrace;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">CustomExceptionMiddleware</span>(<span class="hljs-params">RequestDelegate next, <span class="hljs-keyword">bool</span> seeStackTrace = <span class="hljs-literal">false</span></span>)</span>
    {
        _next = next;
        _seeStackTrace = seeStackTrace;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">Invoke</span>(<span class="hljs-params">HttpContext httpContext</span>)</span>
    {
        <span class="hljs-keyword">try</span>
        {
            <span class="hljs-keyword">await</span> next(httpContext);
        }
        <span class="hljs-keyword">catch</span>(Exception ex)
        {
            <span class="hljs-keyword">await</span> HandleException(httpContext, ex);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">async</span> Task <span class="hljs-title">HandleException</span>(<span class="hljs-params">HttpContext httpContext, Exception ex</span>)</span>
    {
        <span class="hljs-keyword">string</span> details;
        <span class="hljs-keyword">if</span>(_seeStackTrace)
        {
            details = ex.ToString();
        }
        <span class="hljs-keyword">else</span>
        {
            details = <span class="hljs-string">"Exception was caught inside custom exception middleware."</span>;
        }
        <span class="hljs-keyword">var</span> responseProblemDetails = <span class="hljs-keyword">new</span> ProblemDetails
        {
            Title = ex.Message,
            Detail = details,
            Type = <span class="hljs-string">"https://httpstatuses.com/"</span> + (<span class="hljs-keyword">int</span>)HttpStatusCode.InternalServerError
        };
        httpContext.Response.ContentType = <span class="hljs-string">"application/json"</span>;
        httpContext.Response.StatusCode = (<span class="hljs-keyword">int</span>)HttpStatusCode.InternalServerError;
        <span class="hljs-keyword">await</span> httpContext.Response.WriteAsync(JsonSerializer.Serialize(responseProblemDetails));
    }
}
</code></pre>
<p><strong>Startup class</strong><br />We will place the middleware at the start of the middleware pipeline so that it acts as an umbrella for all uncaught exceptions. <strong>EVERYTHING GETS CAUGHT</strong></p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Startup</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Configure</span>(<span class="hljs-params">IApplicationBuilder app</span>)</span>
    {
        <span class="hljs-comment">// we place our middleware at the start </span>
        app.UseMiddleware&lt;CustomExceptionMiddleware&gt;();
        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =&gt;
        {
            endpoints.MapRazorPages();
        });
    }
}
</code></pre>
<p><strong>Controller</strong><br />We expose a GET endpoint and explicitly throw an exception.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">HashnodeController</span> : <span class="hljs-title">ControllerBase</span>
{
        [<span class="hljs-meta">HttpGet(<span class="hljs-meta-string">"~/hashnode"</span>)</span>]
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">GetHashnodePostCount</span>(<span class="hljs-params"></span>)</span>
        {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ApplicationException(<span class="hljs-string">"You shall not pass!"</span>);
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">int</span>.MaxValue;
        }
}
</code></pre>
<p>Done with our setup, now it's time to see it in action.<br />As soon as we hit our <strong><em>/hashnode</em></strong> GET endpoint, in the error response we should start seeing our custom message wrapped as a problemdetails object.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1628280770433/p0CSQlNyy.png" alt="image.png" /></p>
<p>A pretty neat way to make sure all uncaught exceptions are handled appropriately. Also helps declutter code from too many try-catch blocks.</p>
<p>Thank you for going through this post. I hope you found it useful. Cheers!</p>
<p>Additional resources</p>
<ol>
<li><p>Read about <a target="_blank" href="http://owin.org/html/spec/owin-1.0.html">OWIN specification</a>.</p>
</li>
<li><p>Also take a look at project <a target="_blank" href="https://github.com/aspnet/AspNetKatana/wiki">Katana</a>, which contains a set of OWIN components built by Microsoft.</p>
</li>
<li><p>Read about <a target="_blank" href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.problemdetails?view=aspnetcore-3.1">problem details</a>.</p>
</li>
</ol>
]]></content:encoded></item></channel></rss>