<?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" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Cloud Coders]]></title><description><![CDATA[Cloud, ASP.NET, NextJS, ReactJS]]></description><link>https://cloudcoders.xyz/</link><image><url>https://cloudcoders.xyz/favicon.png</url><title>Cloud Coders</title><link>https://cloudcoders.xyz/</link></image><generator>Ghost 5.26</generator><lastBuildDate>Thu, 23 Apr 2026 12:06:07 GMT</lastBuildDate><atom:link href="https://cloudcoders.xyz/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Serilog and AWS CloudWatch Logging for .NET 6: A Step-by-Step Tutorial]]></title><description><![CDATA[Learn how to use Serilog and AWS CloudWatch Logging for your .NET 6 web application in this step-by-step tutorial. Improve your app performance and reliability with structured logging and cloud-based service.]]></description><link>https://cloudcoders.xyz/blog/serilog-and-aws-cloudwatch-logging-for-net-6-a-step-by-step-tutorial/</link><guid isPermaLink="false">6432e8889a92842a8dff9855</guid><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Sun, 14 Jan 2024 20:59:30 GMT</pubDate><media:content url="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/AWS-CloudWatch-Logging-with-serilog.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/AWS-CloudWatch-Logging-with-serilog.jpg" alt="Serilog and AWS CloudWatch Logging for .NET 6: A Step-by-Step Tutorial"><p>Logging is an essential part of any web application development. It helps you to track errors, debug issues, monitor performance, and improve user experience. However, logging can also be challenging, especially when you have to deal with large volumes of data, multiple sources, and different formats.</p><p>That&apos;s why in this blog post, I will show you how to use Serilog and AWS CloudWatch Logging for .NET 6 web applications. Serilog is a popular and powerful library supporting structured logging and various sinks. AWS CloudWatch Logging is a cloud-based service that allows you to collect, store, analyze, and visualize your logs in a centralized place.</p><p>By following this step-by-step tutorial, you will learn how to:</p><ul><li>Set up Serilog and AWS CloudWatch Logging for your .NET 6 web application</li><li>Configure Serilog to send logs to AWS CloudWatch Logging using AWS.Logger.Serilog sink</li><li>Use Serilog enrichers to add contextual information to your logs</li><li>Query and filter your logs using AWS CloudWatch Insights</li><li>Create dashboards and alarms using AWS CloudWatch Metrics and Alarms</li></ul><p>Ready to get started? Let&apos;s dive in!</p><h2 id="overview-of-serilog-and-aws-cloudwatch">Overview of Serilog and AWS CloudWatch</h2><p>Before we dive into the tutorial, let&apos;s briefly review what Serilog and AWS CloudWatch are and why they are useful for logging.</p><h3 id="serilog">Serilog</h3><p><a href="https://github.com/serilog/serilog-aspnetcore">Serilog</a> is a user-friendly logging library that provides structured logging and powerful support for structured diagnostic data. Serilog can be used to log information about application events, errors, and performance metrics. It is designed for .NET frameworks. Some of the features of Serilog are:</p><ul><li>Built-in support for structured logging, enabling logs to be treated as datasets rather than text.</li><li>Seamless compatibility with asynchronous applications and systems.</li><li>Flexible logging targets, including files, console, email, and other customizable outputs.</li><li>Convenient message templates that simplify object serialization using the &quot;@&quot; operator.</li></ul><p>Serilog uses message templates, a simple DSL that extends .NET format strings with named as well as positional parameters. Instead of formatting events immediately into text, Serilog captures the values associated with each named parameter.</p><p>Serilog&#x2019;s support for structured event data opens up a huge range of diagnostic possibilities not available when using traditional loggers. You can query and filter your logs based on the properties, create dashboards and metrics from them, and leverage the power and flexibility of the cloud for your logging needs.</p><h3 id="aws-cloudwatch">AWS CloudWatch</h3><p><a href="https://aws.amazon.com/cloudwatch/">AWS CloudWatch</a> is a comprehensive logging and monitoring service by Amazon Web Services. It provides a wide range of features for monitoring and troubleshooting resources within an AWS environment, including logging capabilities. It allows you to collect, store, analyze, and visualize your logs in a centralized place. Some of the features of AWS CloudWatch are:</p><p><strong>Log Groups:</strong> Log groups are collections of log streams that have the same retention settings, access control, and monitoring parameters. Log groups organize and manage logs by providing a logical grouping for logs created by various AWS services or applications.</p><p><strong>Log Streams:</strong> Log streams are sequences of log events that have the same source. Each log stream represents a distinct source of logs, such as an EC2 instance, a Lambda function, or an application running in an ECS container.</p><p><strong>Retention Policies:</strong> Logs are stored in Cloudwatch forever by default. You may further customize this to your needs by changing the retention duration from 1 day to up to 10 years. Properly configuring the retention period also helps you save money on your monthly AWS bill, particularly for Production applications.</p><p><strong>Log Data Collection:</strong> CloudWatch offers several methods for collecting log data. It collects logs directly from Amazon resources such as EC2 instances, Lambda functions, and CloudTrail. It also provides APIs and SDKs for sending custom logs from EC2 instances or on-premises systems.</p><p><strong>Log Search and Analysis:</strong> CloudWatch has robust log search and analysis features. CloudWatch Logs Insights is a built-in query language that allows you to search and analyze log data using extensive filtering and aggregation tools. It also supports real-time monitoring of logs, making it easier to troubleshoot issues and gain insights into the behavior of your resources.</p><p><strong>Monitoring and Alerting:</strong> CloudWatch allows you to configure metric filters and alerts on logs, which helps in monitoring and alerting certain log events or patterns. For example, you may configure an alert to warn you when the number of failures in your application logs surpasses a specific level. This provides proactive monitoring and alerting based on log data, assisting you in swiftly identifying and resolving issues.</p><p>Cloudwatch can also respond to events. For instance, you can create an alarm &#x1F514;for a particular event which will then notify your team.</p><p>AWS CloudWatch Logging integrates well with Serilog using <strong>AWS.Logger.Serilog</strong> sink. This sink allows you to send your Serilog events to AWS CloudWatch Logging with minimal configuration. You can then use AWS CloudWatch Logging to view, search, filter, query, and visualize your Serilog events in the cloud.</p><p>By combining Serilog and AWS CloudWatch Logging, you can create a powerful and flexible logging solution for your .NET web application.</p><h2 id="setting-up-serilog-with-net-6">Setting Up Serilog with .NET 6</h2><p>Serilog is a popular open-source logging framework for .NET applications that lets you capture, store, and query log events in a flexible and extensible manner. It enables you to set logging configuration in code, making it extremely versatile and adaptable to various logging needs.</p><p>Let&apos;s install and configure Serilog in our .NET 6 web API project. Open up the package manager console and run the following command.</p><pre><code>dotnet add package Serilog.AspNetCore</code></pre><p>Now, let&apos;s open the Program.cs file and configure Serilog in the web host.</p><pre><code class="language-CSharp">using Serilog;

Log.Logger = new LoggerConfiguration()
    .WriteTo.Console()
    .CreateBootstrapLogger();

try
{
    Log.Information(&quot;Starting web application&quot;);

    var builder = WebApplication.CreateBuilder(args);

    builder.Host.UseSerilog((ctx, services, config) =&gt; config
    .ReadFrom.Configuration(ctx.Configuration));

    builder.Services.AddControllers();
    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    
    var app = builder.Build();
    app.UseSerilogRequestLogging();
    
    app.UseHttpsRedirection();
    app.UseAuthorization();
    app.MapControllers();
    app.Run();
}
catch (Exception ex)
{
    Log.Fatal(ex, &quot;Application terminated unexpectedly&quot;);
}
finally
{
    Log.CloseAndFlush();
}
</code></pre><p>There are two ways to configure Serilog. The first is via the code in the startup method (in the Program.cs file) and the second is via app settings. We will use the app settings way. Before configuring the <code>appsettings.json</code> file, first let&apos;s understand the above code snippets.</p><p>Line #3-5: set up a static Log.Logger instance with <a href="https://github.com/serilog/serilog-aspnetcore/tree/dev#two-stage-initialization">two-stage initialization</a> and write output to the console. An initial &quot;bootstrap&quot; logger is configured immediately when the program starts, and this is replaced by the fully configured logger once the host has loaded.</p><p>Line #13-14: We are instructing the Serilog Middleware to read the configurations from the appsettings.</p><p>Line #21: The built-in request logging is noisy with multiple events emitted per request. To enable this middleware, first, we need to override the default log level for <code>Microsoft.AspNetCore</code> to <code>Warning</code> in our <code>appsettings.json</code> file.</p><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/noisy-request-logging.png" class="kg-image" alt="Serilog and AWS CloudWatch Logging for .NET 6: A Step-by-Step Tutorial" loading="lazy" width="1216" height="591"></figure><p>They are condensed by the provided middleware into a single event that has more manageable information. When we run the API now, we can clearly see the difference in the events emitted.</p><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ASP.NET-6-request-logging-middleware.png" class="kg-image" alt="Serilog and AWS CloudWatch Logging for .NET 6: A Step-by-Step Tutorial" loading="lazy" width="1108" height="201"></figure><p>We have also added a <code>try</code> / <code>catch</code> block that will ensure any configuration-related issues are properly logged.</p><p>Next, let&apos;s add the Serilog configuration in the appsettings.json.</p><pre><code class="language-json">{
  &quot;Serilog&quot;: {
    &quot;Using&quot;: [ &quot;Serilog.Sinks.Console&quot;],
    &quot;MinimumLevel&quot;: {
      &quot;Default&quot;: &quot;Information&quot;,
      &quot;Override&quot;: {
        &quot;Microsoft&quot;: &quot;Warning&quot;,
        &quot;Microsoft.AspNetCore&quot;: &quot;Warning&quot;,
        &quot;Microsoft.Hosting.Lifetime&quot;: &quot;Warning&quot;
      }
    },
    &quot;WriteTo&quot;: [
      {
        &quot;Name&quot;: &quot;Console&quot;,
        &quot;Args&quot;: {
          &quot;outputTemplate&quot;: &quot;[{Timestamp:G} [{Level:u3}] {Message}{NewLine}{Exception}&quot;
        }
      }
    ],
    &quot;Enrich&quot;: [ &quot;FromLogContext&quot;, &quot;WithMachineName&quot;, &quot;WithThreadId&quot; ]
  },
  &quot;AllowedHosts&quot;: &quot;*&quot;
}
</code></pre><p>That&apos;s it, we now have Serilog configured in our web API project.</p><div class="kg-card kg-callout-card kg-callout-card-yellow"><div class="kg-callout-emoji">&#x2139;&#xFE0F;</div><div class="kg-callout-text">It&apos;s crucial to be practical and just record the information we actually need because logging may be quite expensive for many software-related aspects.</div></div><h2 id="setting-up-aws-cloudwatch-logging-with-serilog">Setting Up AWS CloudWatch Logging with Serilog</h2><p>AWS CloudWatch is a centralized and highly scalable logging service that collects, stores, and analyzes logs from multiple AWS services and custom applications.</p><p>There are different ways to integrate AWS CloudWatch logging for your .NET 6 application.</p><p>You can use the <a href="https://www.nuget.org/packages/AWSSDK.CloudWatchLogs">AWSSDK.CloudWatchLogs</a> NuGet package that provides <em>AmazonCloudWatchLogsClient</em> to interact with CloudWatch logs. This approach requires you to write a little bit more code. Why repeat yourself if it&apos;s already done for you &#x1F914;.</p><p>You may also use the Amazon logging provider for .NET. The GitHub project <a href="https://github.com/aws/aws-logging-dotnet#aspnet-core-logging">AWS Logging Dotnet</a> provides a plugin for it that also utilizes <em>AmazonCloudWatchLogsClient</em>, which abstracts all of the complexities and mechanics of communicating with CloudWatch.</p><p>Serilog offers flexible configuration options for sinks, allowing you to receive log messages via a configuration file or programmatically through code. We will go through each method but first, let&apos;s install the following required NuGet package.</p><pre><code>dotnet add package AWS.Logger.SeriLog</code></pre><h3 id="configuring-serilog-sinks-with-aws-cloudwatch-via-a-configuration-file">Configuring Serilog Sinks with AWS CloudWatch via a Configuration File</h3><p>Up to this point, we have already configured Serilog in our application via the configuration file. Now let&apos;s open the <em>appsettings.json </em>file and modify it to write logs to CloudWatch.</p><pre><code class="language-json">{
  &quot;Serilog&quot;: {
    &quot;Using&quot;: [ &quot;Serilog.Sinks.Console&quot;, &quot;AWS.Logger.SeriLog&quot; ],
    &quot;LogGroup&quot;: &quot;JokeFetcher&quot;,
    &quot;Region&quot;: &quot;eu-west-1&quot;,
    &quot;MinimumLevel&quot;: {
      &quot;Default&quot;: &quot;Information&quot;,
      &quot;Override&quot;: {
        &quot;Microsoft&quot;: &quot;Warning&quot;,
        &quot;Microsoft.AspNetCore&quot;: &quot;Warning&quot;,
        &quot;Microsoft.Hosting.Lifetime&quot;: &quot;Warning&quot;
      }
    },
    &quot;WriteTo&quot;: [
      {
        &quot;Name&quot;: &quot;Console&quot;,
        &quot;Args&quot;: {
          &quot;outputTemplate&quot;: &quot;[{Timestamp:G} [{Level:u3}] {Message}{NewLine}{Exception}&quot;
        }
      },
      {
        &quot;Name&quot;: &quot;AWSSeriLog&quot;,
        &quot;Args&quot;: {
          &quot;textFormatter&quot;: &quot;Serilog.Formatting.Json.JsonFormatter, Serilog&quot;
        }
      }
    ],
    &quot;Enrich&quot;: [ &quot;FromLogContext&quot;, &quot;WithMachineName&quot;, &quot;WithThreadId&quot; ]
  },
  &quot;AllowedHosts&quot;: &quot;*&quot;
}</code></pre><p> Let&apos;s go through the changes that we have made to this file.</p><p>Line #3: We added <code>AWS.Logger.Serilog</code> in the using array.</p><p>Line #4: Added log group name that will be used to segregate the logs. We want to separate the log group for each application. In this case, we have supplied <em>JokeFetcher </em>which is the name I came up with for this demo project.</p><p>Line #5: &#xA0;This is the AWS region where you want to store the logs. This is optional if you have configured an AWS profile on your machine because it is going to fetch it from there.</p><p>Line #22: We added AWSSerilog sink to the WriteTo Section. WriteTo Section accepts a list of sinks where you would want it to write logs. In our case, we have two sinks, the first one is the console and the second one is AWS CloudWatch.</p><p>Line #23-24: We have added a text formatter that will prettify the logs into clean JSON messages which is useful for structured logging. We will see its benefits in the filtering section.</p><p>Serilog automatically searches for AWS credentials using the standard .NET credentials search path, which includes checking for a profile named &quot;default&quot;, environment variables, or an instance profile on an EC2 instance. To use a different profile other than &quot;default&quot;, simply add a &quot;Profile&quot; under the &quot;Serilog&quot; node in your configuration. This allows you to easily customize the AWS credentials used by Serilog for authenticating with AWS services, ensuring secure and seamless logging in your .NET 6 application.</p><pre><code class="language-json">{
  &quot;Serilog&quot;: {
    &quot;Profile&quot;: {
      &quot;Region&quot;: &quot;your-aws-region&quot;,
      &quot;AccessKey&quot;: &quot;your-access-key&quot;,
      &quot;SecretKey&quot;: &quot;your-secret-key&quot;
    }
  }
}</code></pre><h3 id="programmatic-configuration-of-serilog-sinks-with-aws-cloudwatch">Programmatic Configuration of Serilog Sinks with AWS CloudWatch</h3><p>Next, let&apos;s configure the AWS sink for Serilog using code. Simply use the &quot;WriteTo&quot; method to add the AWS sink to the logger. This provides you with the flexibility to programmatically configure the AWS logging sink for Serilog in your .NET 6 application, allowing you to easily customize your logging setup according to your requirements.</p><pre><code class="language-csharp">    AWSLoggerConfig configuration = new(&quot;JokeFetcher&quot;)
    {
        Region = &quot;eu-west-1&quot;
    };

    builder.Host.UseSerilog((ctx, services, config) =&gt; config
    .ReadFrom.Configuration(ctx.Configuration)
      .WriteTo.AWSSeriLog(configuration, textFormatter: new RenderedCompactJsonFormatter())
    );</code></pre><h3 id="writing-log-events-with-serilog-and-aws-cloudwatch">Writing Log Events with Serilog and AWS CloudWatch</h3><p>Once you&apos;ve completed these steps, your application will be ready to write logs to AWS CloudWatch. Next, let&apos;s add a controller to test it.</p><pre><code class="language-csharp">using JokeFetcherAPI.Models;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;

namespace JokeFetcherAPI.Controllers
{
    [Route(&quot;api/[controller]&quot;)]
    [ApiController]
    public class JokesController : ControllerBase
    {
        private readonly ILogger&lt;JokesController&gt; _logger;
        private readonly IHttpClientFactory _httpClientFactory;

        public JokesController(IHttpClientFactory httpClientFactory, ILogger&lt;JokesController&gt; logger)
        {
            _httpClientFactory = httpClientFactory;
            _logger = logger;
        }

        [HttpGet]
        public async Task&lt;IActionResult&gt; GetJoke()
        {
            JokeApiResponse jokeApiResponse;
            try
            {
                var httpClient = _httpClientFactory.CreateClient(&quot;Jokes&quot;);

                _logger.LogInformation(&quot;Getting programming jokes.&quot;);

                var httpResponseMessage = await httpClient.GetAsync(&quot;Programming&quot;);

                if (!httpResponseMessage.IsSuccessStatusCode)
                {
                    _logger.LogError(&quot;Failed to retrieve joke from external API with status code:{code}&quot;, StatusCode((int)httpResponseMessage.StatusCode));
                    return StatusCode((int)httpResponseMessage.StatusCode);
                }

                var joke = await httpResponseMessage.Content.ReadAsStringAsync();
                jokeApiResponse = JsonSerializer.Deserialize&lt;JokeApiResponse&gt;(joke)!;

                _logger.LogInformation(&quot;Got programming joke with ID:{jokeId} and category:{jokeCategory}&quot;, jokeApiResponse!.Id, jokeApiResponse.Category);

            }
            catch (Exception ex)
            {
                _logger.LogError(ex, &quot;An error occurred while retrieving joke&quot;);
                return StatusCode(StatusCodes.Status500InternalServerError, &quot;An error occurred while retrieving joke.&quot;);
            }
            return Ok(jokeApiResponse);
        }
    }
}</code></pre><p>Here, we have injected the Logger instance in the constructor via DI. Next, we have added a GET endpoint that will fetch a joke from an external API and would log some messages.</p><p>Now, let&apos;s test the endpoint from the postman.</p><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/testing-from-postman.png" class="kg-image" alt="Serilog and AWS CloudWatch Logging for .NET 6: A Step-by-Step Tutorial" loading="lazy" width="1310" height="618"></figure><p>Now that we have a 200 success status code from our API endpoint, we should have:</p><ul><li>A log group named <em><strong>JokeFetcher</strong></em> was created on AWS CloudWatch.</li><li>Logs would have been logged to this log group.</li></ul><p>Let&apos;s go to CloudWatch in the AWS Management Console to verify this.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/log-group-created-in-cloudwatch.png" class="kg-image" alt="Serilog and AWS CloudWatch Logging for .NET 6: A Step-by-Step Tutorial" loading="lazy" width="1684" height="566"></figure><p>You can see that the new log group has been successfully created. By clicking on the log group name, you can view the logs it contains, organized into log streams based on timestamps.</p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/aws-cloudwatch-log-streams.png" class="kg-image" alt="Serilog and AWS CloudWatch Logging for .NET 6: A Step-by-Step Tutorial" loading="lazy" width="1735" height="373"></figure><p>We have one log stream created inside the JokeFetcher log group. Click on the log stream to view the application logs. </p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/aws-cloudwatch-log-events.png" class="kg-image" alt="Serilog and AWS CloudWatch Logging for .NET 6: A Step-by-Step Tutorial" loading="lazy" width="1737" height="723"></figure>]]></content:encoded></item><item><title><![CDATA[Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES]]></title><description><![CDATA[<p>Email communication is a vital aspect of any web application allowing businesses to deliver important notifications and connect and engage with customers effectively. However, ensuring that your emails reach your users&apos; inboxes reliably and avoid the dreaded spam folder can be a challenging task.</p><p>That&apos;s where <a href="https://aws.amazon.com/ses/">Amazon</a></p>]]></description><link>https://cloudcoders.xyz/blog/step-by-step-guide-sending-emails-from-asp-net-core-with-amazon-ses/</link><guid isPermaLink="false">64c8f0589a92842a8dff9bf9</guid><category><![CDATA[aws]]></category><category><![CDATA[.net 6]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Thu, 03 Aug 2023 14:46:09 GMT</pubDate><media:content url="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/Sending-Emails-from-ASP.NET-Core-with-Amazon-SES.png" medium="image"/><content:encoded><![CDATA[<img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/Sending-Emails-from-ASP.NET-Core-with-Amazon-SES.png" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES"><p>Email communication is a vital aspect of any web application allowing businesses to deliver important notifications and connect and engage with customers effectively. However, ensuring that your emails reach your users&apos; inboxes reliably and avoid the dreaded spam folder can be a challenging task.</p><p>That&apos;s where <a href="https://aws.amazon.com/ses/">Amazon SES (Simple Email Service)</a> comes to the rescue! Amazon SES is a highly scalable and cost-effective email service offered by AWS, which is designed to handle all aspects of email delivery and management. By using Amazon SES in your <a href="https://learn.microsoft.com/en-us/aspnet/core/introduction-to-aspnet-core?view=aspnetcore-6.0">ASP.NET Core</a> applications, you can get excellent delivery rates, improved email engagement, and, most importantly, maintain a positive sender reputation.</p><p>This guide will take you through the process of setting up your Amazon SES account and integrating it with your ASP.NET Core application, enabling you to send professional and personalized emails hassle-free.</p><p>By the end of this tutorial, you&apos;ll have the skills and knowledge to create a robust email delivery system that ensures your messages reach their intended recipients effectively and reliably.</p><p>So, let&apos;s dive in and unlock the full potential of sending emails from your ASP.NET Core application with Amazon SES.</p><h2 id="understanding-amazon-ses">Understanding Amazon SES</h2><p>Amazon SES (Simple Email Service) is a powerful and cloud-based email service provided by Amazon Web Services (AWS). It offers developers a robust solution for sending and receiving emails efficiently and at scale. Understanding Amazon SES is crucial to harnessing its full potential for enhancing email communication within your ASP.NET Core applications.</p><h3 id="what-is-amazon-ses">What is Amazon SES?</h3><p>Amazon SES is a cloud-based email service designed to make it easy for developers to send both marketing and transactional emails without the need to manage complex email infrastructures. It provides a simple API (Application Programming Interface) that developers can integrate directly into their applications. With Amazon SES, you can send notifications, updates, newsletters, and other critical communications to your users reliably.</p><h3 id="key-features-of-amazon-ses">Key Features of Amazon SES</h3><ul><li><strong>High Scalability:</strong> Applications that require frequent email communication or have a big user base can benefit from Amazon SES&apos;s ability to handle large-scale email operations.</li><li><strong>Cost-Effectiveness:</strong> You only pay for the emails you send thanks to Amazon SES&apos;s pay-as-you-go pricing model, which has no minimum purchase requirements or up-front charges.</li><li><strong>Robust Deliverability:</strong> Amazon SES a variety of strategies to improve deliverability rates and ensure that your emails land in the inboxes of your intended recipients rather than the spam folder.</li><li><strong>Bounce and Complaint Handling:</strong> It automatically handles bounced and complaint emails, which helps maintain a positive sender reputation.</li><li><strong>SMTP Interface and API Integration:</strong> Amazon SES supports both SMTP and API interfaces, allowing you to choose the integration method that best suits your application&apos;s needs.</li></ul><h3 id="use-cases-for-amazon-ses">Use Cases for Amazon SES</h3><p>Amazon SES is suitable for a wide range of applications and industries. Some common use cases include:</p><ul><li><strong>Transactional Emails:</strong> Send emails for user account creation, password resets, order confirmations, and shipping notifications.</li><li><strong>Marketing Campaigns:</strong> Run personalized email marketing campaigns to engage and retain customers.</li><li><strong>Application Notifications:</strong> Notify users about activity updates, product releases, or important announcements.</li><li><strong>Automated Workflows:</strong> Integrate Amazon SES with AWS Lambda or other AWS services to trigger emails as part of automated workflows.</li></ul><h2 id="pricing">Pricing</h2><p><a href="https://aws.amazon.com/ses/pricing/">Amazon SES</a> has a pay-as-you-go pricing model. However, the Free Tier is quite generous for you to try out. You can send nearly 200 emails every 24 hours for free (assuming you use an EC2 instance). In most circumstances, you will be charged next to nothing. Aside from that, you&apos;ll have to pay $0.10 for every 1,000 emails you send or receive, which is a pretty good offer. Each additional GB of data sent as an attachment will incur an additional charge of about $0.12.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/aws-ses-free-tier-pricing.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="277" height="497"></figure><h2 id="setting-up-an-amazon-ses-in-aws-management-console">Setting Up an Amazon SES in AWS Management Console</h2><p>Let&apos;s go to our AWS Management Console and open up Amazon SES. This is how it would appear if you were to launch this service for the first time.</p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/aws-ses-management-console.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="1916" height="895"></figure><p>To start sending emails, we will have to create and validate a sender identity first, which is a domain or email address you use to send emails via Amazon SES.</p><p>Click on <strong>Create Identity</strong>.</p><p>For this demo, I will use an email address to create an identity. Make sure you have access to the mailbox as a verification email will be sent to this address.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/aws-simple-email-service-create-identity.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="848" height="841"></figure><p>After creating the identity, a verification email will be sent to the email address that you have put above which will look like this.</p><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/amazon-web-services-email-address-verification-request-email.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="1603" height="517"></figure><p>Click on the verification link to verify the email address.</p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/amazon-simple-email-service-ses-verification-successful.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="661" height="109"></figure><p>Now you can check the status of the identity in the AWS Management Console. It should have now a verified status.</p><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/aws-simple-email-service-verified-identities.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="1522" height="183"></figure><h2 id="sending-test-email-from-aws-management-console">Sending Test Email from AWS Management Console</h2><p>Now that we have verified the identity, let&apos;s <a href="https://docs.aws.amazon.com/ses/latest/dg/send-an-email-from-console.html">send a test email from the management console</a>. The Amazon SES mailbox simulator lets you test how your application handles different email-sending scenarios. Emails that you send to the mailbox simulator do not count toward your sending quota or your bounce and complaint rates.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/aws-simple-email-service-send-test-email.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="723" height="842"></figure><ul><li>Select the Email Format as <strong>Formatted</strong>.</li><li>Select the scenario as <strong>Custom. </strong>This will allow us to input a custom recipient for testing purposes.</li><li>Enter the <strong>Subject</strong> and <strong>Body</strong> of the email and hit the <strong>Send Test Email</strong> button.</li></ul><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">&#x2139;&#xFE0F;</div><div class="kg-callout-text">You can also send emails via <a href="https://awscli.amazonaws.com/v2/documentation/api/latest/reference/ses/send-email.html">AWS CLI</a>.</div></div><h3 id="requesting-production-access-in-aws-ses">Requesting production access in AWS SES</h3><p>Your Amazon SES account is in the sandbox when you create it. To request full access to be able to send to any (unverified) email address, you can <a href="https://docs.aws.amazon.com/ses/latest/dg/request-production-access.html">request production access</a> from the SES dashboard.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/AWS-Simple-Email-Service-Account-dashboard-request-production-access.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="1559" height="142"></figure><h2 id="configuring-amazon-ses-in-aspnet-core">Configuring Amazon SES in ASP.NET Core</h2><p>We will be using the ASP.NET Core Web API project using .NET 6 to send emails. </p><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/configure-dotnet-6-web-api.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="998" height="753"></figure><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/create-dotnet-6-web-api.png.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="997" height="752"></figure><p>We can send email programmatically via two approaches: one is through the SMTP interface and the other is using the AWS SDK for .NET.</p><h2 id="sending-mail-using-amazon-ses-via-smtp-interface-in-net">Sending Mail using Amazon SES via SMTP Interface in .NET</h2><p>Our.NET Core API will need SMTP credentials (username and password) to log in with AWS SES in order to send emails.</p><ul><li>Navigate to the <strong>SMTP Settings</strong> from the left pane menu.</li><li>Proceed to create your SMTP credentials by clicking on the <strong>Create My SMTP Credentials</strong> button. This action will redirect you to the AWS Identity and Access Management (IAM) section, allowing you to generate a new user with email-sending access.</li><li>Click <strong>Create</strong> to create your SMTP credentials. You can modify the IAM Username or keep the default one provided by AWS.</li><li>Click the <strong>Show User SMTP Security Credentials</strong> and then copy or download the username and password for use in the subsequent step.</li></ul><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/AWS-Simple-Email-Service-SMTP-settings.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="1571" height="444"></figure><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/create-user-for-smtp.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="1480" height="847"></figure><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/retrieve-smtp-credentials.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="1482" height="361"></figure><p>Let&apos;s return to our Visual Studio and first install the necessary packages for your project.</p><pre><code class="language-bash">Install-Package MailKit
Install-Package MimeKit</code></pre><p>Create a new class named <strong>MailRequest</strong>.</p><pre><code class="language-csharp">public class MailRequest
{
    public string? ToEmail { get; set; }
    public string? Subject { get; set; }
    public string? Body { get; set; }
}</code></pre><p>Next, create another class named MailSettings that will be responsible for loading configurations from the appsettings.json file.</p><pre><code class="language-csharp">public class MailSettings
{
    public string? Host { get; set; }
    public int Port { get; set; }
    public string? DisplayName { get; set; }
    public string? Mail { get; set; }
    public string? Username { get; set; }
    public string? Password { get; set; }
}</code></pre><p>Now, let&apos;s configure the appsettings.json file with the following data. Replace the placeholder with your own data.</p><pre><code class="language-json">&quot;MailSettings&quot;: {
  &quot;Host&quot;: &quot;&lt;smtp server&gt;&quot;,
  &quot;Port&quot;: 587,
  &quot;DisplayName&quot;: &quot;&lt;your name&gt;&quot;,
  &quot;Mail&quot;: &quot;&lt;ses identity registered mail id&gt;&quot;,
  &quot;Username&quot;: &quot;&lt;smtp username&gt;&quot;,
  &quot;Password&quot;: &quot;&lt;smtp password&gt;&quot;
}</code></pre><ul><li><strong>Host</strong> &#x2013; SMTP endpoint from Amazon SES SMTP Settings</li><li><strong>Port</strong> &#x2013; 587</li><li><strong>Display Name</strong> &#x2013; This will be what your recipient will be able to see.</li><li><strong>Mail</strong> &#x2013; the mail id that we registered earlier in SES.</li><li><strong>Username &amp; Password</strong> &#x2013; the credentials that we generated via Amazon SES (IAM User).</li></ul><p>Now let&apos;s add a service for sending emails using the Mailkit package. Create a new folder called <strong>Services </strong>and add the following code.</p><figure class="kg-card kg-code-card"><pre><code class="language-csharp">public interface IMailService
{
    Task SendEmailAsync(MailRequest mailRequest);
}</code></pre><figcaption>IMailService.cs</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-csharp">public class MailService : IMailService
{
    private readonly MailSettings _mailSettings;
    public MailService(IOptions&lt;MailSettings&gt; mailSettings)
    {
        _mailSettings = mailSettings.Value;
    }
    public async Task SendEmailAsync(MailRequest mailRequest)
    {
        var email = new MimeMessage();

        email.From.Add(new MailboxAddress(_mailSettings.DisplayName, _mailSettings.Mail));
        email.To.Add(MailboxAddress.Parse(mailRequest.ToEmail));
        email.Subject = mailRequest.Subject;

        var builder = new BodyBuilder
        {
            HtmlBody = mailRequest.Body
        };
        email.Body = builder.ToMessageBody();

        using var smtp = new SmtpClient();

        smtp.Connect(_mailSettings.Host, _mailSettings.Port, SecureSocketOptions.StartTls);
        smtp.Authenticate(_mailSettings.Username, _mailSettings.Password);
        await smtp.SendAsync(email);
        smtp.Disconnect(true);
    }
}</code></pre><figcaption>MailService.cs</figcaption></figure><p>Let&apos;s understand the code.</p><p><strong>Lines 4-7:</strong> We are using the <a href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/options?view=aspnetcore-7.0">IOptions pattern</a> to inject the configuration from the appsettings into the constructor.</p><p><strong>Line 12:</strong> Adding From metadata into the email variable.</p><p><strong>Line 22:</strong> Create a new SMTP client to connect to the host, port, and authentication details from appsettings.</p><p><strong>Line 26:</strong> Sending email.</p><p>Open up the Program.cs class and register the dependencies into the DI Conationer of the ASP.NET Core application.</p><pre><code class="language-csharp">builder.Services.Configure&lt;MailSettings&gt;(builder.Configuration.GetSection(&quot;MailSettings&quot;));
builder.Services.AddTransient&lt;IMailService, MailService&gt;();</code></pre><p>Next, let&apos;s create a controller named MailsController and wire it up with the service.</p><p>We&apos;re going to create a new endpoint (/api/mails) that will call the IMailService&apos;s SendEmailAsync function. It&apos;s important to note that the endpoint accepts MailRequest as a request and passes it on to the service call, which sends the email via the SMTP client.</p><pre><code class="language-csharp">[Route(&quot;api/[controller]&quot;)]
    [ApiController]
    public class MailsController : ControllerBase
    {
        private readonly IMailService _mailService;
        public MailsController(IMailService mailService)
        {
            this._mailService = mailService;
        }
        [HttpPost]
        public async Task&lt;IActionResult&gt; SendMail(MailRequest request)
        {
            await _mailService.SendEmailAsync(request);
            return Ok();
        }
    }</code></pre><p>Now run the application and test it using Swagger.</p><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/test-application.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="1905" height="961"></figure><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/test-email-received-from-AWS-SES.png" class="kg-image" alt="Step-by-Step Guide: Sending Emails from ASP.NET Core with Amazon SES" loading="lazy" width="651" height="216"></figure><h2 id="sending-mail-using-amazon-ses-via-aws-sdk-for-net">Sending Mail using Amazon SES via AWS SDK for .NET</h2><p>Now that we have implemented how to send email using Amazon SES via the SMTP interface, let&apos;s implement it via the AWS SDK package for .NET.</p><p>First, install the following packages in the same project.</p><pre><code>install-package AWSSDK.Extensions.NETCore.Setup
install-package AWSSDK.SimpleEmail</code></pre><p>Next, add the following in the appsettings.json. Make sure you change the value that is applicable to you.</p><pre><code class="language-json">&quot;AWS&quot;: {
  &quot;Profile&quot;: &quot;default&quot;,
  &quot;Region&quot;: &quot;eu-west-1&quot;
}</code></pre><p>Now, let&apos;s add a new service that uses AWS SDK packages. Create a new class name under the services folder and paste the following code.</p><pre><code class="language-csharp">public class SESService : IMailService
{
    private readonly MailSettings _mailSettings;
    private readonly IAmazonSimpleEmailService _mailService;
    public SESService(IOptions&lt;MailSettings&gt; mailSettings,
        IAmazonSimpleEmailService mailService)
    {
        _mailSettings = mailSettings.Value;
        _mailService = mailService;
    }
    public async Task SendEmailAsync(MailRequest mailRequest)
    {
        var mailBody = new Body(new Content(mailRequest.Body));
        var message = new Message(new Content(mailRequest.Subject), mailBody);
        var destination = new Destination(new List&lt;string&gt; { mailRequest.ToEmail! });
        var request = new SendEmailRequest(_mailSettings.Mail, destination, message);
        await _mailService.SendEmailAsync(request);
    }
}</code></pre><p>This code defines a class named <code>SESService</code>, which is responsible for sending emails using Amazon Simple Email Service (Amazon SES) within an ASP.NET Core application. Let&apos;s break down the code step by step:</p><p><strong>Lines 3-10:</strong> The class has two private fields, <code>_mailSettings</code> and <code>_mailService</code>. The <code>_mailSettings</code> field is of type <code>MailSettings</code>, and the <code>_mailService</code> field is of type <code>IAmazonSimpleEmailService</code>. we are injecting the dependencies of IAmazonSimpleEmailService and the email configuration into the constructor of this service using dependency injection.</p><p><strong>Lines 13-15:</strong> we create the components needed for the email message using the information provided in the <code>MailRequest</code> parameter. We construct the email&apos;s body and subject and then specify the recipient&apos;s email address.</p><p><strong>Line 16:</strong> We create a <code>SendEmailRequest</code> object, which is a part of the Amazon SES SDK. This object is used to send the email and requires the sender&apos;s email address, the recipient&apos;s email address, and the message content.</p><p><strong>Line 17:</strong> Finally, we call the <code>SendEmailAsync</code> method of the <code>_mailService</code> field, passing the <code>SendEmailRequest</code> object we created. This asynchronous method is responsible for sending the email using Amazon SES.</p><p>Open up the Program.cs class and register the dependencies into the DI Conationer of the ASP.NET Core application.</p><pre><code class="language-csharp">builder.Services.Configure&lt;MailSettings&gt;(builder.Configuration.GetSection(&quot;MailSettings&quot;));
//builder.Services.AddTransient&lt;IMailService, MailService&gt;();

builder.Services.AddDefaultAWSOptions(builder.Configuration.GetAWSOptions());
builder.Services.AddAWSService&lt;IAmazonSimpleEmailService&gt;();
builder.Services.AddTransient&lt;IMailService, SESService&gt;();</code></pre><p>Now let&apos;s run the application and test it using Swagger as we did above. This time the email will be sent using the SES Service (the AWS SDK package for Simple Email Service).</p><h2 id="conclusion">Conclusion</h2><p>To conclude, this article provided a comprehensive guide to sending emails with ASP.NET Core using Amazon SES, also known as the Simple Email Service. We covered all aspects of the implementation, and you can access the complete <a href="https://github.com/nandkishor-yadav/AmazonSES.Demo">source code here</a>.</p><p>If you found this article helpful, don&apos;t hesitate to share it with your colleagues. Your support will not only benefit them but also help increase the visibility of my blog. Thank you for reading, and I hope this guide empowers you to leverage Amazon SES for efficient email communication in your ASP.NET Core projects.</p>]]></content:encoded></item><item><title><![CDATA[Working with SignalR and NCache Backplane]]></title><description><![CDATA[<p>Real-time communication is a key requirement for modern web applications. Users expect fast and responsive applications that can provide real-time updates without the need to refresh the page. SignalR is a powerful technology that enables real-time communication between a client and a server, making it a popular choice for building</p>]]></description><link>https://cloudcoders.xyz/blog/working-with-signalr-and-ncache-backplane/</link><guid isPermaLink="false">6283fea259cb9c0a473409d1</guid><category><![CDATA[signalR]]></category><category><![CDATA[NCache]]></category><category><![CDATA[.net 6]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Sat, 25 Mar 2023 22:18:44 GMT</pubDate><media:content url="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/Working-with-SignalR-and-NCache-Backplane.png" medium="image"/><content:encoded><![CDATA[<img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/Working-with-SignalR-and-NCache-Backplane.png" alt="Working with SignalR and NCache Backplane"><p>Real-time communication is a key requirement for modern web applications. Users expect fast and responsive applications that can provide real-time updates without the need to refresh the page. SignalR is a powerful technology that enables real-time communication between a client and a server, making it a popular choice for building real-time web applications.</p><p>However, as the user base grows, SignalR applications can become challenging to scale, especially when the number of clients and the amount of data being transmitted increases. This is where <a href="https://www.alachisoft.com/">NCache</a> comes in. NCache is a distributed in-memory caching solution that can be used to improve application performance and scalability.</p><p>In this article, we&apos;ll explore how to use SignalR and NCache together to build scalable and high-performance web applications. We&apos;ll start by introducing SignalR and NCache and their roles in web development. Then we&apos;ll show you how to use SignalR with NCache to improve web application performance. Finally, we&apos;ll discuss how to scale SignalR applications using NCache backplane.</p><p>Whether you&apos;re building a real-time chat application, a stock market ticker, or an online multiplayer game, the combination of SignalR and NCache can help you build high-performance, scalable, and real-time web applications. So, let&apos;s get started!</p><h2 id="what-is-signalr">What is SignalR?</h2><p><a href="https://learn.microsoft.com/en-us/aspnet/signalr/overview/getting-started/introduction-to-signalr">SignalR</a> is an open-source library for ASP.NET that enables real-time communication between a client and a server. It allows developers to build real-time web applications that can push updates to clients as soon as the data changes on the server.</p><p>SignalR uses WebSockets to establish a persistent connection between the client and the server, enabling real-time communication. If WebSockets are not available, SignalR can automatically fall back to other transport mechanisms, such as Server-Sent Events (SSE), Long Polling, or Forever Frame.</p><p>SignalR provides a simple and easy-to-use API for building real-time web applications. It allows developers to send messages from the server to clients, from clients to the server, or even from client to client. This makes SignalR ideal for building applications that require real-time updates, such as online gaming, chat applications, or financial trading platforms.</p><p>SignalR also provides a robust error-handling mechanism that can handle connection failures, server timeouts, and other network issues. It also provides built-in support for scaling out, allowing you to scale SignalR applications across multiple servers.</p><h2 id="limitations-of-signalr-in-a-webfarm">Limitations of SignalR in a WebFarm</h2><p>While SignalR is a powerful technology for building real-time applications, it can encounter certain limitations when implemented in a WebFarm environment. One of the main challenges of SignalR in a WebFarm is managing multiple servers and ensuring that messages are delivered correctly to all clients.</p><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/webfarm.jpg" class="kg-image" alt="Working with SignalR and NCache Backplane" loading="lazy" width="795" height="601"></figure><p>One major limitation is that SignalR relies on a single message bus for all servers in the WebFarm, known as the SignalR backplane. This can create a bottleneck when handling a large number of messages or clients and can result in delays or dropped messages. Additionally, SignalR&apos;s default load balancing algorithm is round-robin, which can lead to uneven distribution of messages among servers.</p><p>Another limitation of SignalR in a WebFarm is the inability to share in-memory data between servers. This means that if a client is connected to one server and then switches to another, it may not be able to retrieve the same data. This can lead to inconsistencies and incorrect data for the client.</p><p>To overcome these limitations, developers may need to implement workarounds or use third-party solutions such as <a href="https://www.alachisoft.com/ncache/asp-net-core-signalr.html">NCache as a SignalR backplane</a>. These solutions can help to distribute messages more evenly among servers and provide a shared cache for in-memory data. It&apos;s important to carefully consider the limitations of SignalR in a WebFarm and choose the appropriate solutions to ensure optimal performance and scalability for real-time applications.</p><h2 id="bottlenecks-with-signalr-backplane">Bottlenecks with SignalR Backplane</h2><p>1. Real-time applications need less latency and more Throughput</p><ul><li>SignalR Backplane needs low latency and high Throughput.</li><li>Database as SignalR Backplane is slow, Database can not scale out with increasing application load.</li></ul><p>2. SignalR apps need guaranteed delivery of messages</p><ul><li>SignalR Backplane must be reliable.</li><li>The database can choke down under extreme load and is a single-point failure.</li></ul><p>3. SignalR Backplane must have high availability built into it</p><ul><li>SignalR backplane needs to be highly available.</li><li>Backplane maintenance or unplanned outage can cause service delivery issues.</li></ul><h2 id="what-is-ncache">What is NCache?</h2><p>NCache is an open-source distributed in-memory cache developed natively in .NET and .NET Core. NCache is a distributed cache that stores application data and prevents expensive database trips. It is extremely quick and linearly scalable. NCache can be used to reduce performance bottlenecks caused by data storage and databases, as well as to extend the capabilities of your .NET Core applications to handle high-volume transaction processing (XTP). It works both locally and configured as a distributed cache cluster for an ASP.NET Core app running in Azure or other hosting platforms.</p><p>NCache also provides built-in support for scaling out, allowing you to scale your application across multiple servers. It supports multiple cache topologies, including replicated, partitioned, and client-cache, enabling you to configure the cache to suit your application&apos;s needs.</p><h2 id="using-signalr-with-ncache">Using SignalR with NCache</h2><p>NCache stands out as an excellent option when considering third-party SignalR backplane providers due to several compelling reasons.</p><p>By combining SignalR with NCache, you can improve the performance and scalability of your real-time web applications. NCache can be used as a backplane for SignalR, enabling real-time updates to be shared across multiple servers.</p><p>When using NCache with SignalR, the client connections are distributed across multiple servers, and each server maintains its own connection to the NCache cluster. When a message is sent through SignalR, it is sent to the NCache cluster, which then distributes the message to all connected clients.</p><p>Using NCache as a backplane for SignalR offers several benefits. </p><ol><li>It improves the performance of real-time web applications by reducing the load on the database server. </li><li>It enables high availability by distributing client connections across multiple servers, ensuring that clients can still receive updates even if one server fails. </li><li>It enables scaling out by allowing you to add additional servers to the NCache cluster as your application grows.</li></ol><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/singlar-backplane.png" class="kg-image" alt="Working with SignalR and NCache Backplane" loading="lazy" width="650" height="489"></figure><p>The main problem that NCache solves as a backplane is a scalability. NCache&apos;s distributed linear scalability enables each application to send messages to the backplane, and the backplane then sends the message back to the client&apos;s application. By eliminating the need to manage the complexity of parallel connectors, developers can focus on building robust applications without worrying about performance bottlenecks caused by backplane scalability limitations.</p><h2 id="scaling-signalr-apps-with-ncache-backplane">Scaling SignalR Apps with NCache Backplane</h2><p>One of the key benefits of using NCache as a backplane for SignalR is the ability to scale out your application as your user base grows. NCache provides built-in support for scaling out, which allows you to add additional servers to the NCache cluster as your application grows.</p><p>When using NCache as a backplane for SignalR, client connections are distributed across multiple servers, ensuring that clients can still receive updates even if one server fails. This makes it possible to scale out your application by simply adding more servers to the NCache cluster. As new servers are added, the load is automatically distributed across all servers in the cluster, ensuring that each server can handle its fair share of the client connections.</p><p>Refer to the article <a href="https://cloudcoders.xyz/blog/caching-with-ncache-in-asp-net-core/">Caching with NCache in ASP.NET Core</a> for instructions on installing NCache and managing the cache using the <a href="https://cloudcoders.xyz/blog/caching-with-ncache-in-asp-net-core/#simulating-stress-and-monitoring-statistics">NCache web monitoring application</a>.</p><p>To begin the demo, we will use the existing ASP.NET Core SignalR application. The source code can be downloaded from <a href="https://github.com/nandkishor-yadav/SignalRChat">GitHub</a>. </p><p>The next step is to add a JSON object to the appsettings.json file.</p><pre><code class="language-json">&quot;NCacheConfiguration&quot;: {
  &quot;CacheName&quot;: &quot;mylocalcache&quot;,
  &quot;ApplicationID&quot;: &quot;chatApplication&quot;
},</code></pre><p><strong>CacheName: </strong>It is<strong> </strong>the name of the newly created cache</p><p><strong>ApplicationID:</strong> should be a unique string relevant to the application.</p><p>To use NCache with SignalR, download and install the <code>AspNetCore.SignalR.NCache</code> package from NuGet Package Manager. Then, add the below code to the <code>Startup.cs</code> file. This code configures NCache options, including the cache name and application ID, using the values from the appsettings.json file.</p><pre><code class="language-csharp">services.AddSignalR().AddNCache(ncacheOptions =&gt; {
    ncacheOptions.CacheName = Configuration[&quot;NCacheConfiguration:CacheName&quot;];
    ncacheOptions.ApplicationID = Configuration[&quot;NCacheConfiguration:ApplicationID&quot;];
});</code></pre><p>Start the application, then try to chat using two different user accounts. As soon as NCache starts, the NCache web monitor application will display the client count, as seen in the following figure:</p><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/signalR_in_action.png" class="kg-image" alt="Working with SignalR and NCache Backplane" loading="lazy" width="1915" height="407"></figure><p>The client connection is now established, and our SignalR application is using the NCache as a backplane:</p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/NCache_monitoring.png" class="kg-image" alt="Working with SignalR and NCache Backplane" loading="lazy" width="612" height="422"></figure><h2 id="conclusion">Conclusion</h2><p>In conclusion, NCache with SignalR is a powerful combination for building real-time applications that are scalable, reliable, high-performing, and deliver real-time updates to clients. By leveraging the benefits of NCache and SignalR together, developers can build applications that provide a seamless user experience and can handle a high volume of data and traffic.</p><p>NCache provides several benefits, including scalability, high availability, performance, reliability, and reduced database load. Using SignalR with NCache enables real-time updates to clients, ensuring that they are always viewing the latest data. This makes NCache with SignalR a perfect fit for use cases such as financial applications, gaming applications, social media applications, and other real-time applications.</p>]]></content:encoded></item><item><title><![CDATA[React Hooks - explained]]></title><description><![CDATA[Learn how to use React Hooks (useState, useEffect, useContext, useRef, useReducer, useCallback, useMemo) and how to create your own custom Hooks.]]></description><link>https://cloudcoders.xyz/blog/react-hooks-explained/</link><guid isPermaLink="false">630754d2637a245bacf2c4fa</guid><category><![CDATA[ReactJs]]></category><category><![CDATA[NextJs]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Tue, 06 Sep 2022 08:53:30 GMT</pubDate><media:content url="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/react-hooks.png" medium="image"/><content:encoded><![CDATA[<img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/react-hooks.png" alt="React Hooks - explained"><p><a href="https://reactjs.org/docs/hooks-intro.html">React Hooks</a> were introduced in React 16.8 which allows functional components to have access to state and other features like performing an after effect when a particular condition is met or specific changes occur in the state(s) without having to write class components.</p><p>In this article, I will explain how to use React Hooks (<em>useState, </em><a href="https://cloudcoders.xyz/blog/react-useeffect-hook/"><em>useEffect</em></a><em>, useContext, useRef, useReducer, useCallback, useMemo</em>) and how to create your custom Hooks. Just bear in mind that you can use hooks solely for the functional component.</p><h2 id="what-is-a-hook-in-react">What is a Hook in React?</h2><p><strong>A hook is a special function that enables the use of state and several other features in functional components available in class-based components.</strong></p><h2 id="the-rules-of-a-hook">The rules of a Hook</h2><p>Let&apos;s talk about the general <a href="https://reactjs.org/docs/hooks-rules.html">rules of Hooks</a>. It is important to know where in your code you can use hooks. You need to follow the rules to use Hooks.</p><ol><li>Hooks can only be called inside React function components.</li><li>Hooks can only be called at the top level of a component.</li><li>Hooks cannot be conditional.</li></ol><h2 id="react-usestate-hook">React <code>useState</code> Hook</h2><p>Your application&apos;s status will undoubtedly change at some point. This might be any form of data present in your components, such as the value of a variable or object.</p><p>The React <code>useState</code> hooks allow us to track and reflect these changes in the DOM.</p><p>Let&apos;s see how can we use <code>useState</code> hook in a function component.</p><p>To use this hook, we first need to import it into our component.</p><pre><code class="language-javascript">import {useState} from &apos;react&apos;</code></pre><p>Next, we need to initialize our state by calling <code>useState</code>. It accepts an initial state and returns two values.</p><ul><li>The current state</li><li>A function that updates the state</li></ul><pre><code class="language-javascript">const [name, setName] = useState(&apos;John Doe&apos;);</code></pre><p>We are destructuring the returned values from <code>useState</code>. The first value is a <code>name</code> which is our current state and the second value <code>setName</code> is the function that is used to update our state. Lastly, we set the initial state to <code>John Doe</code>.</p><p>Our state is initialized and ready to be used anywhere in our component. For example, we can read the state by using the state variable in the rendered component.</p><pre><code class="language-javascript">import { useState } from &apos;react&apos;;
function MyComponent() {
  const [name, setName] = useState(&apos;John Doe&apos;);
   return (
    &lt;&gt;
      &lt;div&gt;
        &lt;p&gt;My name is {name}&lt;/p&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}
export default MyComponent;</code></pre><p>Similarly, we can update our state by using the state updater function.</p><pre><code class="language-javascript">import { useState } from &apos;react&apos;;
function MyComponent() {
  const [name, setName] = useState(&apos;John Doe&apos;);
  const changeName = () =&gt; {
    setName(&apos;Foo&apos;);
  };
  return (
    &lt;&gt;
      &lt;div&gt;
        &lt;p&gt;My name is {name}&lt;/p&gt;
        &lt;button onClick={changeName}&gt; Click me &lt;/button&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}
export default MyComponent;</code></pre><p>In the code above, we update the state with a button click.</p><p>At this point you might be thinking, what can the state hold?&#x1F914;</p><p>The <code>useState</code> hook can keep track of objects, arrays, strings, numbers, booleans, and any combination of these.</p><h2 id="react-useeffect-hook">React <code>useEffect</code> Hook</h2><p>I have written a separate post on <a href="https://cloudcoders.xyz/blog/react-useeffect-hook/">React useEffect Hook</a> </p><h2 id="react-usecontext-hook">React <code>useContext</code> Hook</h2><p>React <code>useContext</code> hook is a way to manage states globally no matter how deep they are in the components tree.</p><p>In React, there are three basic steps to using the context: </p><ol><li>creating the context</li><li>providing the context</li><li>consuming the context.</li></ol><p>But, before diving into details on the above steps, let&apos;s talk about what problem does useContext hook solves.</p><p>The short answer is <em>props drilling</em>.</p><p>The parent component in the stack that requires access to the state should hold the state.</p><p>For example, let&apos;s say we have many nested components and access to the state is required by the components at the top and bottom of the stack.</p><p>We will need to pass the state as &quot;props&quot; through each nested component to accomplish this without Context. This is called &quot;prop drilling&quot;. Let&apos;s see an example.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/react-useContext-prop-drilling.png" class="kg-image" alt="React Hooks - explained" loading="lazy" width="1086" height="1812"><figcaption>Passing &quot;props&quot; through nested components:</figcaption></figure><p>As you can see, components 2 and 3 did not need the state, even though they had to pass the state along so that it could reach component 4.</p><p>So, the solution to this problem is to use the <code>useContext</code> hook.</p><p>The main goal of using the context is to provide your components access to some global data and enable them to re-render if that global data is changed. When it comes to passing along props from parents to children, context is the key to solving the props drilling problem.</p><p>However, you should be careful before deciding to use context in your app as it adds complexity to the application and makes it hard to unit test.</p><p>A quick reminder, there are three basic steps to using the context, creating the context, providing the context, and consuming the context. Let&apos;s dive into more details about this and solve the props drilling problem.</p><p><strong>Creating the context</strong></p><p>To create context, you must import the built-in function <code>createContext</code> and initialize it.</p><pre><code class="language-javascript">import { createContext } from &apos;react&apos;;
const Context = createContext();</code></pre><p> <strong>Providing the context</strong></p><p><code>Context.Provider</code> is used to provide the context to its child components, no matter how deep they are. You can use the &#xA0;<code>value</code> prop to set the value of context.</p><pre><code class="language-javascript">function Component1() {
  const [user, setUser] = useState(&quot;John Doe&quot;);

  return (
    &lt;UserContext.Provider value={user}&gt;
      &lt;h1&gt;{`Hey ${user}!`}&lt;/h1&gt;
      &lt;Component2 user={user} /&gt;
    &lt;/UserContext.Provider&gt;
  );
}</code></pre><p>Now, the user Context will be accessible to every component in this tree.</p><p><strong>Consuming the context</strong></p><p>To use the Context in a child component, we need to access it using the useContext Hook.</p><pre><code class="language-javascript">import { useContext } from &quot;react&quot;;

function Component4() {
  const user = useContext(UserContext);

  return (
    &lt;&gt;
      &lt;h1&gt;Component 4&lt;/h1&gt;
      &lt;h2&gt;{`Hey ${user} again!`}&lt;/h2&gt;
    &lt;/&gt;
  );
}</code></pre><p>The full example is below.</p><pre><code class="language-javascript">import { useState, createContext, useContext } from &apos;react&apos;;

const UserContext = createContext();

function Component1() {
  const [user, setUser] = useState(&apos;John Doe&apos;);

  return (
    &lt;UserContext.Provider value={user}&gt;
      &lt;h1&gt;{`Hey ${user}!`}&lt;/h1&gt;
      &lt;Component2 /&gt;
    &lt;/UserContext.Provider&gt;
  );
}

function Component2() {
  return (
    &lt;&gt;
      &lt;h1&gt;Component 2&lt;/h1&gt;
      &lt;Component3 /&gt;
    &lt;/&gt;
  );
}

function Component3() {
  return (
    &lt;&gt;
      &lt;h1&gt;Component 3&lt;/h1&gt;
      &lt;Component4 /&gt;
    &lt;/&gt;
  );
}

function Component4() {
  const user = useContext(UserContext);
  return (
    &lt;&gt;
      &lt;h1&gt;Component 4&lt;/h1&gt;
      &lt;h2&gt;{`Hey ${user} again!`}&lt;/h2&gt;
    &lt;/&gt;
  );
}</code></pre><h2 id="react-useref-hook">React <code>useRef</code> Hook</h2><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">&#x1F449;</div><div class="kg-callout-text">The <code>useRef</code> Hook allows you to persist values between renders.</div></div><p>This hook also makes it possible to access DOM nodes directly within the functional components.</p><p>UseState and useReducer in a React component can cause your component re-render every time the update methods are called.</p><p>Let&apos;s take a look at how to use the <code>useRef()</code> hook to keep track of variables without causing re-renders, and how to enforce the re-rendering of React Components.</p><p><strong><code>useRef</code> does not cause re-renders</strong></p><p>The <code>useState</code> The hook itself causes a re-render, therefore if we were to count how many times our application renders using this Hook, we would be caught in an infinite loop. The <code>useRef</code> hook can be used to avoid this.</p><p><code>useRef(initialValue)</code> accepts one argument as the initial value and returns a <em>reference</em>. A reference is an object having a special property <code>current</code>.</p><pre><code class="language-javascript">import { useRef } from &apos;react&apos;;

export default function LogButtonClicks() {
  const countRef = useRef(0);

  const handle = () =&gt; {
    countRef.current++;
    console.log(`Clicked ${countRef.current} times`);
  };
  console.log(&apos;I rendered!&apos;);
  return &lt;button onClick={handle}&gt;Click me&lt;/button&gt;;
}</code></pre><p><code>const countRef = useRef(0)</code> creates a references <code>countRef</code> initialized with <code>0</code>.</p><p><code>CountRef.current++</code> is increased when the button is clicked, and the handle function is also invoked. The reference value is logged to the console.</p><p>Updating the reference value <code>countRef.current++</code> does not cause component re-rendering.</p><p>As you can see, updating the reference value <code>countRef.current++</code> does not cause component re-rendering, because you can see in the console that &apos;I rendered!&apos; is logged just once at initial rendering and does not re-render when the reference is updated.</p><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/useref-hook.gif" class="kg-image" alt="React Hooks - explained" loading="lazy" width="1280" height="720"></figure><p>Now, let&apos;s see the difference between reference and state by re-using &#xA0;<code>LogButtonClicks</code> from the previous example. We will use the <code>useState</code> hook to count the number of button clicks.</p><pre><code class="language-javascript">import { useState } from &apos;react&apos;;

export default function LogButtonClicks() {
  const [count, setCount] = useState(0);
  
  const handle = () =&gt; {
    const updatedCount = count + 1;
    console.log(`Clicked ${updatedCount} times`);
    setCount(updatedCount);
  };
  console.log(&apos;I rendered!&apos;);
  return &lt;button onClick={handle}&gt;Click me&lt;/button&gt;;
}</code></pre><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/usestate-and-useref-difference.gif" class="kg-image" alt="React Hooks - explained" loading="lazy" width="1280" height="720"></figure><p>As you can see every time the button is clicked, the message &apos;I rendered!&apos; gets logged in the console causing the component to re-render.</p><p><strong>Accessing DOM elements</strong></p><p>Most of the time, we should let React handle all the DOM manipulation, but there might be some use cases where we want to take control of DOM manipulation. In such scenarios, we can use <code>useRef</code> hook to do this without causing any issues. &#xA0;</p><p>For instance, let&apos;s say we want to focus on the input field when the component mounts. To make it work you&#x2019;ll need to create a reference to the input, and assign the reference to the ref attribute of the input, once the component mounts call the <em><em>element.focus()</em></em> method on the element.</p><pre><code class="language-javascript">import { useRef, useEffect } from &apos;react&apos;;

function TextInputWithFocus() {
  const inputRef = useRef();
  useEffect(() =&gt; {
    inputRef.current.focus();
  }, []);
  return (
    &lt;input ref={inputRef} type=&quot;text&quot;/&gt;
  );
}</code></pre><p>The functional component&apos;s function scope should either calculate the output or invoke hooks. Because of this, updating a reference and changing the state of a component shouldn&apos;t be performed inside the immediate scope of the component&apos;s function.</p><p>Either a <a href="https://cloudcoders.xyz/blog/react-useeffect-hook/">useEffect()</a> callback or handlers (event handlers, timer handlers, etc) must be used to change the reference.</p><pre><code class="language-javascript">import { useRef, useEffect } from &apos;react&apos;;

function MyComponent({ prop }) {
  const myRef = useRef(0);
    
  useEffect(() =&gt; {
    myRef.current++; // Good!&#x1F44D;
    setTimeout(() =&gt; {
      myRef.current++; // Good!&#x1F44D;
    }, 1000);
  }, []);
    
  const handler = () =&gt; {
    myRef.current++; // Good!&#x1F44D;
  };
    
  myRef.current++; // Bad!&#x1F44E;
    
  if (prop) {
    myRef.current++; // Bad!&#x1F44E;
  }
  return &lt;button onClick={handler}&gt;My button&lt;/button&gt;;
}</code></pre><p>As we can persist useRef values between renders, we can use this hook to keep track of previous state values.</p><pre><code class="language-javascript">import { useState, useEffect, useRef } from &quot;react&quot;;

function MyComponent() {
  const [inputValue, setInputValue] = useState(&quot;&quot;);
  const previousInputValue = useRef(&quot;&quot;);

  useEffect(() =&gt; {
    previousInputValue.current = inputValue;
  }, [inputValue]);

  return (
    &lt;&gt;
      &lt;input type=&quot;text&quot; value={inputValue}
          onChange={(e) =&gt; setInputValue(e.target.value)}
      /&gt;
      &lt;h2&gt;Current Value: {inputValue}&lt;/h2&gt;
      &lt;h2&gt;Previous Value: {previousInputValue.current}&lt;/h2&gt;
    &lt;/&gt;
  );
}</code></pre><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/previous-state-values-useref-hook.gif" class="kg-image" alt="React Hooks - explained" loading="lazy" width="1280" height="720"></figure><h2 id="react-usereducer-hook">React <code>useReducer</code> Hook</h2><p>The useReducer Hook is similar to the useState Hook which also allows you to manage state and re-render a component whenever that state changes. The idea behind <code>useReducer</code> is it gives you a more concrete way to handle complex states. It gives you a set of actions that you can perform in your state and it&apos;s going to convert your current state to a new version of the state based on the action that you send it. If you&apos;re familiar with redux, the useReducer hook has a very similar pattern to redux.</p><pre><code class="language-javascript">useReducer(&lt;reducer&gt;, &lt;initialState&gt;)</code></pre><p>The useReducer Hook accepts two arguments: <em><strong>reducer </strong></em>and <strong><em>initialState.</em></strong></p><p>The hook then returns an array of 2 items: the <em>current state</em> and the <em>dispatch</em> function.</p><pre><code class="language-javascript">import { useReducer } from &apos;react&apos;;
function MyComponent() {
  const [state, dispatch] = useReducer(reducer, initialState);
    
  const action = {
    type: &apos;ActionType&apos;
  };
  return (
    &lt;button onClick={() =&gt; dispatch(action)}&gt;
      Click me
    &lt;/button&gt;
  );
}</code></pre><p>Now, let&apos;s first understand what the terms <em>initial state, action object, dispatch, and reducer</em> mean.</p><p><strong>Initial state: T</strong>his can be a simple value the state is initialized with, but generally contain an object. For instance, in the case of user state, the initial value could be:</p><pre><code class="language-javascript">// initial state
const initialState = { 
  users: []
};</code></pre><p><strong>Action Object: </strong>It describes how to update the state. The property type of an action object is often a string defining the kind of state update that the reducer needs to do. For example</p><pre><code class="language-javascript">const action = {
  type: &apos;ADD_USER&apos;
};</code></pre><p>You can add more attributes to the action object if the reducer requires it to contain a payload.</p><pre><code class="language-javascript">const action = {
  type: &apos;ADD_USER&apos;,
  user: { 
    name: &apos;John Doe&apos;,
    email: &apos;jdoe@mail.com&apos;
  }
};</code></pre><p><strong>Dispatch function:</strong> It is a special function that dispatches an action object. It is created by the useReducer hook.</p><pre><code class="language-javascript">const [state, dispatch] = useReducer(reducer, initialState);</code></pre><p>You can simply call the dispatch function with the appropriate action object: <code>dispatch(actionObject)</code> to update the state.</p><p><strong>Reducer function:</strong> It is a pure function that contains your custom logic. It accepts 2 parameters: the current state and an action object. The reducer function must update the state in an immutable way, depending on the action object, and return the new state.</p><p>The following reducer function adds the user to the state.</p><pre><code class="language-javascript">const initialState = {
  users: [],
}

const userReducer = (state = initialState, action) =&gt; {
  switch (action.type) {
    case &apos;ADD_USER&apos;:
      return {
        ...state,
        users: [...state.users, action.payload],
      }
    default:
      return state
  }
}</code></pre><p><strong>Wiring everything</strong></p><pre><code class="language-javascript">import React, { useReducer } from &apos;react&apos;

const initialState = {
  users: [],
}

const userReducer = (state = initialState, action) =&gt; {
  switch (action.type) {
    case &apos;ADD_USER&apos;:
      return {
        ...state,
        users: [...state.users, action.payload],
      }
    default:
      return state
  }
}

function Reducer() {
  const [users, dispatch] = useReducer(userReducer, initialState)
  console.log(JSON.stringify(users, null, 2))

  const payload = {
    name: &apos;John Smith&apos;,
    email: &apos;jsmith@mail.com&apos;,
  }

  const addUser = () =&gt; {
    dispatch({ type: &apos;ADD_USER&apos;, payload })
  }

  return (
    &lt;div&gt;
      &lt;button onClick={addUser}&gt;Add User&lt;/button&gt;
    &lt;/div&gt;
  )
}

export default Reducer
</code></pre><p>From the above code snippet, when you click the <code>Add User</code> button, the function dispatches an action object of the type <code>ADD_USER</code> which adds the user to the state and logs the new state in the console. You can add more complex logic like updating, and deleting a user inside the single reducer function by adding more actions.</p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/useReducer-hook.png" class="kg-image" alt="React Hooks - explained" loading="lazy" width="801" height="562"></figure><h2 id="react-usecallback-hook">React <code>useCallback</code> Hook</h2><p>Let&apos;s first discuss performance optimization before moving on. The render time must be taken into account whenever we create a React app. We can enhance our application performance if we can reduce the time taken to render the DOM. One way to achieve this will be by preventing unnecessary renders of our components. This might not have great performance improvement for a small application, but if we have a large application with many components, we can have a serious performance boost &#x1F680;.</p><p><strong>The React useCallback returns a memoized version of the callback function that changes only when one of the dependencies has changed.</strong></p><p>You can think of memoization as caching, so it returns a cached version of the result (callback function) which can boost the performance.</p><p>It is useful when passing callbacks to optimized child components that rely on reference equality to prevent unnecessary renders.</p><h3 id="why-we-need-a-usecallback-function">Why We Need a useCallback Function</h3><p>One reason to use the useCallback function is to prevent unnecessary re-rendering of the components. The component should not re-render unless its props have been changed.</p><p>Let&apos;s see an example.</p><pre><code class="language-javascript">import React, { useState } from &apos;react&apos;;
import User from &apos;./User&apos;;

function CallbackHookDemo() {
  const [users, setUsers] = useState([]);
  const [darkMode, setDarkMode] = useState(false);

  const addUser = () =&gt; {
    setUsers((u) =&gt; [...u, &apos;New User added !!&apos;]);
  };

  const handleCheckboxChange = () =&gt; setDarkMode((prev) =&gt; !prev);

  return (
    &lt;&gt;
      &lt;User users={users} addUser={addUser} /&gt;
      &lt;hr /&gt;

      &lt;div className={darkMode ? &apos;dark-mode&apos; : &apos;&apos;}&gt;
        &lt;label htmlFor=&quot;darkMode&quot;&gt;dark mode&lt;/label&gt;
        &lt;input
          name=&quot;darkMode&quot;
          type=&quot;checkbox&quot;
          checked={darkMode}
          onChange={handleCheckboxChange}
        /&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}

export default CallbackHookDemo;</code></pre><figure class="kg-card kg-code-card"><pre><code class="language-javascript">import React, { memo } from &apos;react&apos;;

function User({ users, addUser }) {
  console.log(&apos;User component rendered&apos;);
  return (
    &lt;&gt;
      &lt;h2&gt;Users:&lt;/h2&gt;
      {users.map((user, i) =&gt; {
        return &lt;p key={i}&gt;{user}&lt;/p&gt;;
      })}
      &lt;button onClick={addUser}&gt;Add User&lt;/button&gt;
    &lt;/&gt;
  );
}

export default memo(User);</code></pre><figcaption>User.js</figcaption></figure><p>When you run this code and check the dark mode checkbox, you will notice that the <code>User</code> component re-renders even when the <code>users</code> do not change.</p><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/useCallback-hook.gif" class="kg-image" alt="React Hooks - explained" loading="lazy" width="1280" height="720"></figure><p>Why is this happening?&#x1F914; The <code>User</code> component should not re-render since neither the <code>users</code> state nor the <code>addUser</code> function are changing when the checkbox is checked.</p><p>This is due to <em>referential equality</em>. Functions get recreated when a component re-renders. That&apos;s why the <code>addUser</code> function has changed.</p><p>To fix this, we can use the useCallback hook to prevent unnecessary re-render of the component unless necessary. We can now wrap the <code>addUser</code> function inside the useCallback hook like the below code.</p><pre><code class="language-javascript">  const addUser = useCallback(() =&gt; {
    setUsers((u) =&gt; [...u, &apos;New User added !!&apos;]);
  }, [users]);</code></pre><p>Now, the <code>User</code> component will only re-render when the <code>users</code> prop changes.</p><h2 id="react-usememo-hook">React <code>useMemo</code> Hook</h2><p>The react useMemo hook returns a memoized value that only runs when one of its dependencies changes.</p><div class="kg-card kg-callout-card kg-callout-card-yellow"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text"><code>UseMemo</code> and <code>useCallback</code> hooks have some similarities. The main difference is that UseMemo returns a memoized value whereas useCallback returns a memoized function.</div></div><p>You might have some expensive and resource-intensive functions in your React application. If those functions are run on every re-render of the component, the application will have a massive performance issue which can be costly in either memory, time, or processing and it will also lead to poor user experience.</p><p>You can try to optimize the performance of the application by utilizing the <a href="https://en.wikipedia.org/wiki/Memoization">memoization </a>technique.</p><p>useMemo hook tries to address the following two problems.</p><ul><li>referential equality</li><li>computationally expensive operations</li></ul><p><code>useMemo()</code> is a built-in React hook that accepts 2 arguments &#x2014; a function <code>compute</code> that computes a result and the <code>depedencies</code> array:</p><pre><code class="language-javascript">const memoizedResult = useMemo(compute, dependencies);</code></pre><p>On the first render, <code>useMemo(compute, dependencies)</code> invokes <code>compute</code>, remembers the calculated output and returns it to the component.</p><p>In the subsequent renders, the <code>compute</code> functions would not need to run again as long as the dependencies do not change. It will simply return the memoized output.</p><p>Now let&apos;s see how <code>useMemo()</code> works in an example.</p><pre><code class="language-javascript">import React, { useState } from &apos;react&apos;

const expensiveCalculation = (num) =&gt; {
  console.log(&apos;Calculating...&apos;)
  for (let i = 0; i &lt; 1000000000; i++) {
    num += 1
  }
  return num
}

function UseMemoHookExample() {
  const [users, setUsers] = useState([])
  const [count, setCount] = useState(0)
  const calculation = expensiveCalculation(count)

  const addUser = () =&gt; {
    setUsers((u) =&gt; [...u, &apos;New User added !!&apos;])
  }

  const increment = () =&gt; {
    setCount((c) =&gt; c + 1)
  }

  return (
    &lt;&gt;
      &lt;h2&gt;Users:&lt;/h2&gt;
      {users.map((user, i) =&gt; {
        return &lt;p key={i}&gt;{user}&lt;/p&gt;
      })}
      &lt;button onClick={addUser}&gt;Add User&lt;/button&gt;
      &lt;hr /&gt;
      &lt;div&gt;
        Count: {count}
        &lt;button onClick={increment}&gt;+&lt;/button&gt;
        &lt;h2&gt;Expensive Calculation&lt;/h2&gt;
        {calculation}
      &lt;/div&gt;
    &lt;/&gt;
  )
}

export default UseMemoHookExample
</code></pre><p>In this example, you will notice that when you increase the count or add a user, there is a delay in execution.</p><p>Even if you only add a user, the component re-renders, and the expensive calculation function gets invoked resulting in a delayed execution.</p><p>Let&apos;s improve the performance of this component by using <code>useMemo</code> hook which will memoize the result of the expensive function.</p><pre><code class="language-javascript">import React, { useMemo, useState } from &apos;react&apos;

const expensiveCalculation = (num) =&gt; {
  console.log(&apos;Calculating...&apos;)
  for (let i = 0; i &lt; 1000000000; i++) {
    num += 1
  }
  return num
}

function UseMemoHookExample() {
  const [users, setUsers] = useState([])
  const [count, setCount] = useState(0)
  const calculation = useMemo(() =&gt; expensiveCalculation(count), [count])

  const addUser = () =&gt; {
    setUsers((u) =&gt; [...u, &apos;New User added !!&apos;])
  }

  const increment = () =&gt; {
    setCount((c) =&gt; c + 1)
  }

  return (
    &lt;&gt;
      &lt;h2&gt;Users:&lt;/h2&gt;
      {users.map((user, i) =&gt; {
        return &lt;p key={i}&gt;{user}&lt;/p&gt;
      })}
      &lt;button onClick={addUser}&gt;Add User&lt;/button&gt;
      &lt;hr /&gt;
      &lt;div&gt;
        Count: {count}
        &lt;button onClick={increment}&gt;+&lt;/button&gt;
        &lt;h2&gt;Expensive Calculation&lt;/h2&gt;
        {calculation}
      &lt;/div&gt;
    &lt;/&gt;
  )
}

export default UseMemoHookExample
</code></pre><p>Now, when the component renders for the first time, an expensive calculation function will be invoked and the result will be memoized so that when we click on add user, the function will not be invoked again as there is no change in dependency and the execution will be super fast.</p><h2 id="react-custom-hook">React custom Hook</h2><p>You can create your custom hook by using the react built-in hooks and extract your custom logic into a reusable function.</p><p>There are two rules for creating a custom hook:</p><ul><li>Custom hooks are prefixed with &quot;use&quot;. For example, it could be named as <code>useFetch</code></li><li>Custom hooks consist of built-in or other custom hooks. A custom Hook is not a custom Hook and should not begin with the prefix &quot;use&quot; if it does not internally utilize any hooks.</li></ul><p>Let&apos;s create a custom hook that will fetch a random joke from the API. </p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">import { useState, useEffect } from &apos;react&apos;

function useFetch(url) {
  const [data, setData] = useState(null)

  useEffect(() =&gt; {
    fetch(url)
      .then((res) =&gt; res.json())
      .then((data) =&gt; setData(data))
  }, [url])

  return [data]
}

export default useFetch
</code></pre><figcaption>useFetch.js</figcaption></figure><p>We created a new file and named it useFetch.js which contains our custom logic to fetch data from the API endpoint.</p><p>In <code>App.js</code>, we are importing our <code>useFetch</code> Hook and utilize it like any other Hook. This is where we pass in the URL to fetch data.</p><p>Now we can reuse this custom Hook in any component to fetch data from any URL.</p><figure class="kg-card kg-code-card"><pre><code class="language-javascript">import useFetch from &apos;./components/useGetRandomJoke&apos;
function App() {
  const [data] = useFetch(&apos;http://api.icndb.com/jokes/random&apos;)

  return &lt;div className=&quot;App&quot;&gt;{data &amp;&amp; &lt;p&gt;{data.value.joke}&lt;/p&gt;}&lt;/div&gt;
}

export default App</code></pre><figcaption>App.js</figcaption></figure><h2 id="conclusion">Conclusion</h2><p>This article explored built-in react hooks and their appropriate use in the React application. If you like the article then please share it and feel free to ask any questions you may have in the comment section below. &#xA0;</p>]]></content:encoded></item><item><title><![CDATA[React useEffect Hook - Ultimate Guide]]></title><description><![CDATA[Hooks are special functions that enable the use of state and several other features in functional components available in class-based components.]]></description><link>https://cloudcoders.xyz/blog/react-useeffect-hook/</link><guid isPermaLink="false">628f4ec2fd7c98dacae9e621</guid><category><![CDATA[ReactJs]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Tue, 23 Aug 2022 11:41:48 GMT</pubDate><media:content url="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/react-useEffect-hook.png" medium="image"/><content:encoded><![CDATA[<img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/react-useEffect-hook.png" alt="React useEffect Hook - Ultimate Guide"><p>If you&apos;re working with functional components in React, the useEffect hook is an essential tool for managing side effects. Whether you need to perform operations when a component is rendered, updated, or unmounted, the useEffect hook can help you do so with ease.</p><p>In functional components, the useEffect hook can be used to perform operations (or side effects) in the following situations:</p><ul><li>when a component is rendered (<code>componentDidMount</code> function in class-based components)</li><li>when a component changes (<code>componentDidUpdate</code> function in class-based components)</li><li>before a component is unmounted/removed (<code>componentWillUnmount</code> function in class-based components)</li></ul><h2 id="why-is-it-called-useeffect">Why is it called useEffect?</h2><p>The core <a href="https://cloudcoders.xyz/blog/react-hooks-explained/">React Hooks</a> (useState, useEffect, and so on) were added to the library in 2018. The name of this hook, &quot;useEffect,&quot; confused many developers.</p><p>What exactly is an &quot;effect&quot;?</p><p>In functional programming, the word &quot;effect&quot; refers to a concept known as a &quot;<strong>side effect.&quot; </strong></p><p>But in order to fully understand what a side effect is, we must first understand what a pure function is. Perhaps to your surprise, the majority of React components are designed to be pure functions.</p><p> React components may be seen as functions, despite the fact that this may appear strange. It is instructive to note that a standard React function component is declared similarly to a JavaScript function:</p><pre><code class="language-javascript">function MyReactComponent() {}</code></pre><p>The majority of React components are pure functions, which means they take an input and output a predictable output of JSX.</p><p>Input to a javascript function is arguments. However, what is a React component&apos;s input? Props!</p><p>Here, the prop <code>name</code> has been specified on a <code>User</code> component. The prop value is shown in a header element within the <code>User</code> component.</p><pre><code class="language-javascript">export default function App() {
  return &lt;User name=&quot;John Doe&quot; /&gt;   
}
  
function User(props) {
  return &lt;h1&gt;{props.name}&lt;/h1&gt;;
}</code></pre><p>This is a pure function because it produces the same output when given the same input.</p><p>Our output will always be John Doe if we provide the <code>User</code> a <code>name</code> prop with the value &quot;John Doe&quot;.</p><p>The fact that pure functions are dependable, predictable, and easy to test is a huge advantage. This is in contrast to situations where we must implement a side effect in our component.</p><h2 id="what-are-side-effects-in-react">What are side effects in React?</h2><p>Side effects are not predictable as actions that are performed with the outside world.</p><p>When we need to reach outside of our React components to do something, we perform a side effect. However, performing a side effect will not have a predictable result.</p><p>Consider requesting data (such as blog posts) from a server that has failed and returns a 500 status code response instead of our post data.</p><p>Common side effects include:</p><ul><li>Fetching data from an API</li><li>Reading from local storage</li><li>Interacting with browser APIs (that is, to use <code>document</code> or <code>window</code> directly)</li><li>Using unpredictable timing functions like <code>setTimeout</code> or <code>setInterval</code></li></ul><p>This is why useEffect exists: to provide a way to handle performing these side effects in what is otherwise pure React components.</p><p>For instance, if we wanted to change the title meta tag to display the user&apos;s name in their browser tab, we could do it within the component itself, but we shouldn&apos;t.</p><pre><code class="language-javascript">function User({ name }) {
  document.title = name; 
  // This is a side effect. Don&apos;t do this in the component body!
    
  return &lt;h1&gt;{name}&lt;/h1&gt;;   
}</code></pre><p>The rendering of our React component is affected if a side effect is carried out right in its body.</p><p>It is best to keep side effects apart from the rendering process. If we need to do a side effect, it should strictly be done after<em><em> </em></em>our component renders.</p><p>In a nutshell, <strong>useEffect is a tool that allows us to interact with the outside world while preserving the component&apos;s rendering and performance<strong>.</strong></strong></p><h2 id="how-do-i-use-useeffect">How do I use useEffect?</h2><p>UseEffect&apos;s basic syntax looks like this:</p><pre><code class="language-javascript">import { useEffect } from &apos;react&apos;;

function MyComponent() {
  // 2. call it above the returned JSX  
  // 3. pass two arguments to it: a function and an array
  useEffect(() =&gt; {}, []);
  
  // return ...
}</code></pre><p>The correct way to perform the side effect in our <code>User</code> component is as follows:</p><ol><li>We import <code>useEffect</code> from &quot;react&quot;</li><li>We call it above the returned JSX in our component</li><li>We pass it two arguments: a function and an array</li></ol><pre><code class="language-javascript">import { useEffect } from &apos;react&apos;;

function User({ name }) {
  useEffect(() =&gt; {
    document.title = name;
  }, [name]);
    
  return &lt;h1&gt;{name}&lt;/h1&gt;;   
}</code></pre><p>useEffect receives a callback function as its parameter. After the component renders, this will be invoked.</p><p>We can perform one or more side effects in this function if we want.</p><p>The dependencies array is the second parameter, which is an array. All the values on which our side effect depends should be included in this array.</p><p>We need to include <code>name</code> in the dependents array in the example above because we are changing the title depending on a value in the outer scope.</p><p>This array will check to see whether a value (in this case, <code>name</code>) has changed between renderings. If so, our useEffect function will be executed again.</p><p>This makes sense since, in case the name changes, we want to display the updated name and rerun our side effect.</p><h3 id="what-is-the-cleanup-function-in-useeffect">What is the cleanup function in useEffect?</h3><p>The effect cleanup function is the last step in carrying out side effects correctly in React.</p><p>Our side effects occasionally need to be turned off. For instance, if you use the <code>setInterval</code> method to start a countdown timer, that interval won&apos;t end until we use the <code>clearInterval</code> function. We use the cleanup function for this.</p><p>If we use setInterval to set the state and that side effect is not cleaned up when our component unmounts and we no longer use it, the state is destroyed along with the component - but the setInterval method continues to run.</p><pre><code class="language-javascript">function Timer() {
  const [time, setTime] = useState(0);
    
  useEffect(() =&gt; {
    setInterval(() =&gt; setTime(1), 1000);
  }, []);
}</code></pre><p>The problem with the above code is that when the component is destroyed, <code>setInterval</code> will try to update a variable of the state <code>time</code> that no longer exists. This is an error called a memory leak.</p><p>We need to stop using <strong>setInterval </strong>when the component unmounts.</p><pre><code class="language-javascript">function Timer() {
  const [time, setTime] = useState(0);

  useEffect(() =&gt; {
    let interval = setInterval(() =&gt; setTime(1), 1000);

    return () =&gt; {
      clearInterval(interval);
    };
  }, []);
}
</code></pre><p>We can perform our cleanup within this function by calling <code>clearInterval</code>.</p><p>The cleanup function will be called when the component is unmounted.</p><p>Going to a new page or route in your application where the component is no longer displayed is a common example of a component being unmounted.</p><p>When we unmount a component, our cleanup code runs, our interval is cleared, and we no longer get an error about trying to update a state variable that doesn&apos;t exist.</p><p>Last but not least, cleaning up after side effects is not always necessary. It is only necessary for very few circumstances, such as when you want to stop a recurring side effect after your component unmounts.</p><h2 id="the-importance-of-the-dependency-array">The importance of the dependency array</h2><p>Let&apos;s take a look at the below example with two states. Why do we have the problem of unnecessary effects?</p><pre><code class="language-javascript">export default function TwoStatesEffects() {
  const [title, setTitle] = useState(&apos;default title&apos;);
  const titleRef = useRef();
  const [darkMode, setDarkMode] = useState(false);

  useEffect(() =&gt; {
    console.log(&apos;useEffect&apos;);
    document.title = title;
  });
  console.log(&apos;render&apos;);
  const handleClick = () =&gt; setTitle(titleRef.current.value);
  const handleCheckboxChange = () =&gt; setDarkMode((prev) =&gt; !prev);

  return (
    &lt;div className={darkMode ? &apos;dark-mode&apos; : &apos;&apos;}&gt;
      &lt;label htmlFor=&quot;darkMode&quot;&gt;dark mode&lt;/label&gt;
      &lt;input
        name=&quot;darkMode&quot;
        type=&quot;checkbox&quot;
        checked={darkMode}
        onChange={handleCheckboxChange}
      /&gt;
      &lt;input ref={titleRef} /&gt;
      &lt;button onClick={handleClick}&gt;change title&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/useEffect.gif" class="kg-image" alt="React useEffect Hook - Ultimate Guide" loading="lazy" width="1280" height="680"><figcaption>Two states causing unnecessary effects</figcaption></figure><p>If you do not provide a dependency array, each <code>useEffect</code> is executed after every render cycle. In our case, whenever one of the two-state variable change, the useEffect is executed.</p><p>Dependencies that you supply as array items are used to handle this behavior. React will only execute the useEffect statement if at least one of the supplied dependencies has changed since the last run. To put it another way, you can condition the execution using the dependency array.</p><p>We want to skip unnecessary effects after an intended re-render, right?</p><p>All we need to do is add an array with the title as a dependency. As a result, the effect is only executed when values between render cycles vary.</p><pre><code class="language-javascript"> useEffect(() =&gt; {
    console.log(&apos;useEffect&apos;);
    document.title = title;
  }, [title]);</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/skip-unnecessary-effect.gif" class="kg-image" alt="React useEffect Hook - Ultimate Guide" loading="lazy" width="1280" height="680"><figcaption>skip unnecessary effect</figcaption></figure><p>We can also add an empty dependency array which will execute the effect only once.</p><h2 id="how-to-fix-common-mistakes-with-useeffect">How to fix common mistakes with useEffect</h2><p>With useEffect, a few important things to be aware of in order to avoid mistakes.</p><pre><code class="language-javascript">useEffect(() =&gt; {
  //the code here runs every time the screen is rendered
});</code></pre><p>If you do not provide any dependency array to the useEffect, it will run after every render.</p><p>If you set a local state variable when the state is changed and useEffect runs without the dependencies array after each render, the loop will continue indefinitely.</p><pre><code class="language-javascript">function MyCustomer() {
  const [customer, setCustomer] = useState([]);

  useEffect(() =&gt; {
    fetchCustomer().then((myCust) =&gt; setCustomer(myCust));
    // Error! useEffect runs after every render without the dependencies array, causing infinite loop
  });
}
</code></pre><p>After the first render, useEffect is executed, the state is changed, which causes a re-render, which triggers useEffect to execute once again, and so on indefinitely.</p><p>To fix the infinite loop, we should pass an empty dependencies array. This will cause the effect function to only run once after the component has been rendered the first time.</p><pre><code class="language-javascript">function MyCustomer() {
  const [customer, setCustomer] = useState([]);

  useEffect(() =&gt; {
    fetchCustomer().then((myCust) =&gt; setCustomer(myCust));
  }, []);
}
</code></pre><h2 id="the-rules-of-hooks">The rules of Hooks</h2><p>Let&apos;s talk about the general rules of Hooks. Although they are not restricted to the useEffect Hook, it&apos;s important to know where you can define effects in your code. You need to follow the <a href="https://reactjs.org/docs/hooks-rules.html">rules to use Hooks</a>.</p><ol><li>Only the top-level function of your functional React component can call hooks.</li><li>Don&apos;t call hooks inside loops, conditions, or nested functions.</li></ol><h2 id="conclusion">Conclusion</h2><p>I believe that one of the most important skills to master if you want to become a next-level React developer is understanding the underlying design concepts and best practices of the useEffect Hook.</p>]]></content:encoded></item><item><title><![CDATA[Caching with NCache in ASP.NET Core]]></title><description><![CDATA[NCache is a cross-platform, open-source distributed caching system by Alachisoft that is exceptionally fast and linearly scalable.]]></description><link>https://cloudcoders.xyz/blog/caching-with-ncache-in-asp-net-core/</link><guid isPermaLink="false">6227680069dbfb43c51a38e4</guid><category><![CDATA[NCache]]></category><category><![CDATA[aspnetcore]]></category><category><![CDATA[caching]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Wed, 01 Jun 2022 07:50:22 GMT</pubDate><media:content url="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/caching-with-ncache-asp-net-core.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: html--><!-- Ezoic - under_feature_image - under_page_title -->
<div id="ezoic-pub-ad-placeholder-137"> </div>
<!-- End Ezoic - under_feature_image - under_page_title --><!--kg-card-end: html--><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/caching-with-ncache-asp-net-core.png" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core"><p>In this article, we will talk about Distributed Caching, NCache, and its features such as Object Caching, Session Caching, and Response Caching along with practical implementation in ASP.NET Core.</p><!--kg-card-begin: html--><!-- Ezoic - under_first_paragraph - under_first_paragraph -->
<div id="ezoic-pub-ad-placeholder-138"> </div>
<!-- End Ezoic - under_first_paragraph - under_first_paragraph --><!--kg-card-end: html--><h2 id="what-is-distributed-caching">What is distributed caching</h2><p><strong>A distributed cache is a cache that is shared by multiple app servers and is often managed as an external service to the app servers that access it. </strong></p><p>While most caches are traditionally housed in a single physical server or hardware component, a distributed cache can expand beyond the memory limits of a single computer by connecting multiple computers&#x2014;referred to as a distributed architecture or a distributed cluster&#x2014;for increased capacity and processing power.</p><p>A distributed cache can increase the efficiency and scalability of an ASP.NET Core project, particularly if the app is hosted by a cloud service or a server farm. Distributed caches are extremely useful in high-data-volume and high-load applications. Because of the distributed design, incremental expansion and scaling are possible by adding more computers to the cluster, allowing the cache to grow in tandem with the data growth.</p><p>When cached data is distributed, the data:</p><ul><li>Is coherent (consistent) across requests to multiple servers.</li><li>Survives server restarts and app deployment.</li><li>Doesn&apos;t use local memory.</li></ul><!--kg-card-begin: html--><!-- Ezoic - under_second_paragraph - under_second_paragraph -->
<div id="ezoic-pub-ad-placeholder-139"> </div>
<!-- End Ezoic - under_second_paragraph - under_second_paragraph --><!--kg-card-end: html--><h2 id="what-is-ncache">What is NCache</h2><p><strong>NCache is an open-source distributed in-memory cache developed natively in .NET and .NET Core</strong>. NCache is a distributed cache that stores application data and prevents expensive database trips. It is extremely quick and linearly scalable. NCache can be used to reduce performance bottlenecks caused by data storage and databases, as well as to extend the capabilities of your .NET Core applications to handle high-volume transaction processing (XTP). It works both locally and configured as a distributed cache cluster for an ASP.NET Core app running in Azure or other hosting platforms.</p><h2 id="some-major-features-of-ncache">Some major features of NCache</h2><p>Some major features of NCache are:</p><ol><li>Recovery from Split-Brain</li><li>ASP.NET Core Object, Session, and Response caching</li><li>WAN Replication</li><li>Search Cache (SQL-Like)</li><li>Security and Encryption</li><li>Data Grouping</li><li>Runtime Data Sharing</li><li>Cache Topologies</li><li>Cache Size Management</li><li>Cache Elasticity (High Availability)</li></ol><!--kg-card-begin: html--><!-- Ezoic - incontent_5 - incontent_5 -->
<div id="ezoic-pub-ad-placeholder-143"> </div>
<!-- End Ezoic - incontent_5 - incontent_5 --><!--kg-card-end: html--><h2 id="how-to-use-ncache-with-aspnet-core-a-tutorial">How to use NCache with ASP.NET Core (a tutorial)</h2><p>Let&#x2019;s dive into a step-by-step practical implementation of NCache with .NET 6.</p><h3 id="setting-up-an-environment">Setting up an environment</h3><p>Let&apos;s have a look at how to set up an NCache server on a Windows machine. For this, we need a &#xA0;windows <a href="https://www.alachisoft.com/download-ncache.html">installer</a>. Let&#x2019;s install NCache Enterprise edition, version 5.3.</p><div class="kg-card kg-callout-card kg-callout-card-accent"><div class="kg-callout-emoji">&#x1F4A1;</div><div class="kg-callout-text">Installation requires either of the following versions, based on your environment:<br>- NET Framework 4.8<br>- NET 6.0</div></div><p>Follow these steps to install NCache using an interactive Windows installer:</p><ul><li>Open command prompt as administrator. This is because NCache must be installed by an administrator user.</li><li>Run <em>msiexec.exe</em> utility from Command Prompt to install NCache in an interactive mode. Please note that the .msi file may have a different name for the .NET Framework installation.</li></ul><pre><code class="language-powershell">msiexec /i &quot;&lt;Setup Path&gt;\ncache.ent.net.x64.msi&quot;</code></pre><!--kg-card-begin: html--><!-- Ezoic - incontent_6 - incontent_6 -->
<div id="ezoic-pub-ad-placeholder-144"> </div>
<!-- End Ezoic - incontent_6 - incontent_6 --><!--kg-card-end: html--><p>The NCache Setup Wizard welcome screen appears:</p><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/1-welcome.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="497" height="384"></figure><p>After launching the installer, we must choose between three installation types: cache server, remote client, and developer/QA. Let&#x2019;s select Cache Server.</p><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/2-InstallationType.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="498" height="384"></figure><p>After that, we must input a license key. Make sure you have a license key for the same version as the one you&apos;re installing. We&apos;ll receive an &quot;invalid license key&quot; error otherwise. The license key is sent to the email address you provided during registration.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_7 - incontent_7 -->
<div id="ezoic-pub-ad-placeholder-145"> </div>
<!-- End Ezoic - incontent_7 - incontent_7 --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/3-License.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="489" height="379"></figure><p>After that, we need to enter our full name, email address, and the organization that we used to apply for the trial license.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/4-data.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="492" height="383"></figure><p>Next, select the installation folder where NCache should be installed. Keep the default location or change it if required.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_8 - incontent_8 -->
<div id="ezoic-pub-ad-placeholder-146"> </div>
<!-- End Ezoic - incontent_8 - incontent_8 --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/5-install-location.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="494" height="384"></figure><p>Then, we need to select an IP address to bind our NCache server to. Let&#x2019;s stick to the defaults.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/6-ip.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="492" height="382"></figure><p>Next, we need to choose an account to run NCache. Let&#x2019;s use the Local System Account.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_9 - incontent_9 -->
<div id="ezoic-pub-ad-placeholder-147"> </div>
<!-- End Ezoic - incontent_9 - incontent_9 --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/7-user.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="492" height="384"></figure><p>NCache service creates and starts a demo cache named demoCache of topology Partitioned-Replica by default at the end of setup installation. Uncheck the checkbox <code>Start demo cache at the end of the installation</code> to disable this option from this screen. When you&apos;re finished, click Install.</p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/8-final.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="501" height="385"></figure><p>Once the installation finishes, our default browser will open with the Web Manager at <code>http://localhost:8251</code> </p><!--kg-card-begin: html--><!-- Ezoic - incontent_10 - incontent_10 -->
<div id="ezoic-pub-ad-placeholder-149"> </div>
<!-- End Ezoic - incontent_10 - incontent_10 --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/9-ncache-web-manager.webp" class="kg-image" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy" width="1912" height="271"></figure><p>The official site of NCache suggests a minimum of two servers for redundancy. However, for testing, let&apos;s use a single-node server.</p><p>At this point, we have successfully installed the NCache server on a windows machine. However, NCache can be installed in Linux and Docker containers and can be used on Azure and AWS as virtual machines.</p><h3 id="creating-a-clustered-cache">Creating a clustered cache</h3><p>Now, let&apos;s see how we can manually create a cluster cache from the web manager which is running at <code>http://localhost:8251/</code>.</p><p>In the left navigation bar, click on <em>Clustered Caches</em>. The page displays any clustered caches on your machine, as well as additional information such as topology, servers, and server platform.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_11 - incontent_11 -->
<div id="ezoic-pub-ad-placeholder-150"> </div>
<!-- End Ezoic - incontent_11 - incontent_11 --><!--kg-card-end: html--><p></p><!--kg-card-begin: markdown--><ol>
<li>
<p>To create a new distributed cache, click on New.<br>
<img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ncache-web-new-distributed-cache-7.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></p>
</li>
<li>
<p>Select Distributed Cache from the In-Memory Store Type dropdown menu and give your cache a name. Choose JSON or Binary from the Serialization dropdown option, depending on your needs. It is recommended that you use JSON serialization if you are using ASP.NET 5.0 and above.<br>
<img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ncache-web-new-distributed-cache-1.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></p>
</li>
<li>
<p>Choose the caching topology as well as advanced options such as Operation Timeout and Statistic Replication Interval. If you choose the Partition-Replica Cache topology, you must choose an Asynchronous or Synchronous Replication Strategy.<br>
<img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ncache-web-new-distributed-cache-2.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></p>
</li>
<li>
<p>If necessary, set the cache&apos;s maximum size. You can also add cache nodes to the cluster by specifying the node IP address and clicking on +. To add more nodes, click +.<br>
<img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ncache-web-new-distributed-cache-3.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></p>
</li>
<li>
<p>If necessary, change the Cluster Port and Port Range. Check the Enable Pipelining option if pipelining is necessary for the cache. Set the Batch Interval to the time in microseconds after which the commands will be sent across the network.<br>
<img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ncache-web-new-distributed-cache-4.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></p>
</li>
<li>
<p>Check the Enable Encryption and Enable Compression options to enable encryption and compression. Set the Providers and Key for encryption and the Threshold Size for compression if encryption is enabled.<br>
<img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ncache-web-new-distributed-cache-5.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></p>
</li>
<li>
<p>On the Advanced Options page, you can configure the following settings:</p>
<ul>
<li>By default, eviction is enabled. You can adjust the Eviction Policy as needed. Uncheck the box Enable Eviction if you wish to disable eviction.</li>
<li>You can also adjust the Eviction percentage; if eviction is enabled, items will be evicted from the cache using this % value.</li>
<li>You can change the Clean interval value. Default is 15 seconds.</li>
<li>If you click the Start this cache on Finish checkbox on this dialog box, this cache will be started automatically after this process is completed.</li>
<li>You can make the cache start automatically after service restart by checking the checkbox Autostart this cache on service startup.<br>
<img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ncache-web-new-distributed-cache-6.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></li>
</ul>
</li>
<li>
<p>The server nodes and status of the newly created cache will display in the Clustered Caches page.<br>
<img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/ncache-web-new-distributed-cache-8---Copy.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></p>
</li>
</ol>
<!--kg-card-end: markdown--><!--kg-card-begin: html--><!-- Ezoic - longer_content - longer_content -->
<div id="ezoic-pub-ad-placeholder-141"> </div>
<!-- End Ezoic - longer_content - longer_content --><!--kg-card-end: html--><h3 id="simulating-stress-and-monitoring-statistics">Simulating stress and monitoring statistics</h3><p>NCache provides the Test Stress option to simulate the usage of your created cache.</p><h4 id="test-stress-through-ncache-web-manager">Test Stress Through NCache Web Manager</h4><p>To simulate your cache utilization under stress using NCache Web Manager, follow the instructions below:</p><!--kg-card-begin: markdown--><ul>
<li>Launch NCache Web manager by browsing localhost:8251</li>
<li>From the left navigation bar, click on Clustered Caches.<br>
<img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/1.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></li>
<li>Click the Test-Stress button on the toolbar to bring up a dialog box containing various time options.<br>
<img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/2.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></li>
<li>You may choose how long you want the Test-Stress to run from the options provided. The choices are:
<ul>
<li>10 seconds</li>
<li>30 seconds</li>
<li>1 minute</li>
<li>3 minutes</li>
<li>5 minutes</li>
</ul>
</li>
<li>This is the duration for which the data will continue to be added to your cache, and once that time has passed, the data will be deleted from the cache.</li>
<li>There are two ways to see how these cache counts are updated. Either use the <em>Monitor</em> option on the toolbar to see the cache counts or use the <em>Statistics</em> option to keep track of your cache&apos;s statistics.</li>
<li>The following are the specifics for both of the above options.</li>
</ul>
<h4 id="view-simulation-through-ncache-web-monitor">View Simulation Through NCache Web Monitor</h4>
<p>NCache Web Monitor provides various cache counters in a graphical dashboard.<br>
<img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/3.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"><br>
The counters on NCache Web Monitor show that data is being added to the cache. The counters will show data being removed from the cache when the given expiration time has passed.</p>
<h4 id="view-simulation-through-ncache-statistics">View Simulation Through NCache Statistics</h4>
<p>NCache Statistics provides a report view of various cache counters. If you choose to simulate cache usage through statistics, then follow these steps:<br>
<img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/4.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></p>
<ul>
<li>Click the Test-Stress button on the toolbar to bring up a dialog box containing various time options.<br>
<img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/5.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></li>
<li>You can choose the Tess-Stress timer for 10 or 30 seconds or 1, 3, or 5 minutes, depending on your choice from the dialogue box.</li>
<li>As soon as you press the Start button, you can view the statistics for different operations on the cache like Additions/sec and Fetches/sec.</li>
<li>You can see the data being added to the cache by looking at the counters on the screen. The counters will indicate data being purged from the cache when the given expiration time has passed.<br>
<img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/6.webp" alt="Caching with NCache in&#xA0;ASP.NET&#xA0;Core" loading="lazy"></li>
</ul>
<!--kg-card-end: markdown--><!--kg-card-begin: html--><!-- Ezoic - longest_content - longest_content -->
<div id="ezoic-pub-ad-placeholder-142"> </div>
<!-- End Ezoic - longest_content - longest_content --><!--kg-card-end: html--><h4 id="test-stress-through-ncache-powershell-cmdlet">Test Stress Through NCache PowerShell Cmdlet</h4><p>You can quickly test that cache clients can make calls to cache servers using the Stress Test Tool that comes with NCache installation.</p><p>Run the following command in Windows PowerShell to begin this test on the cache you just created:</p><pre><code class="language-powershell">Test-Stress &#x2013;CacheName ClusteredCache</code></pre><h3 id="using-ncache-for-object-caching-in-aspnet-core">Using NCache for object caching in ASP.NET Core</h3><p>Before connecting to our NCache server, we need to first install the Nuget package. Let&apos;s Install the package by executing the following command in the Package Manager Console.</p><!--kg-card-begin: html--><!-- Ezoic - mid_content - mid_content -->
<div id="ezoic-pub-ad-placeholder-154"> </div>
<!-- End Ezoic - mid_content - mid_content --><!--kg-card-end: html--><h4 id="with-ncache-sdk-nuget-package">With NCache SDK NuGet package</h4><p><strong>For Enterprise</strong></p><pre><code>Install-Package NCache.Microsoft.Extensions.Caching</code></pre><p><strong><strong>For Professional</strong></strong></p><pre><code>Install-Package NCache.Microsoft.Extensions.Caching.Professional</code></pre><p><strong><strong>For OpenSource</strong></strong></p><pre><code>Install-Package NCache.Microsoft.Extensions.Caching.OpenSource
</code></pre><p>Now, to start the connection, we need the <code>GetCache()</code> method with a cache name. For our sample app, let&apos;s use the cache name that we created above.</p><p>Let&apos;s start writing some code to add and retrieve the cities from a cache.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_12 - incontent_12 -->
<div id="ezoic-pub-ad-placeholder-151"> </div>
<!-- End Ezoic - incontent_12 - incontent_12 --><!--kg-card-end: html--><pre><code class="language-csharp">[HttpGet(&quot;{id:int}&quot;)]
        public async Task&lt;IActionResult&gt; Get(int id)
        {
            ICache _cache = CacheManager.GetCache(_configuration.GetValue&lt;string&gt;(&quot;NCacheSettings:CacheName&quot;));
            var cacheKey = string.Format(&quot;city_{0}&quot;, id);
            
            var city = _cache.Get&lt;City&gt;(cacheKey);

            if (city is null)
            {
                city = await _cityRepository.GetByIdAsync(id);

                var cacheItem = new CacheItem(city)
                {
                    Expiration = new Expiration(ExpirationType.Sliding, TimeSpan.FromMinutes(10))
                };

                // Add CacheItem to cache
                await _cache.InsertAsync(cacheKey, cacheItem);
            }

            return Ok(city);
        }</code></pre><p>Notice we didn&#x2019;t have to use a connection string to connect to our cache. We only used a cache name that is defined in the appsettings.json file.</p><pre><code class="language-json">&quot;NCacheSettings&quot;: {
    &quot;CacheName&quot;: &quot;myClusteredCache&quot;,
    &quot;EnableLogs&quot;: true,
    &quot;EnableDetailLogs&quot;: false,
    &quot;ExceptionsEnabled&quot;: true,
    &quot;OperationRetry&quot;: 0,
    &quot;operationRetryInterval&quot;: 0
  }</code></pre><!--kg-card-begin: html--><!-- Ezoic - incontent_13 - incontent_13 -->
<div id="ezoic-pub-ad-placeholder-152"> </div>
<!-- End Ezoic - incontent_13 - incontent_13 --><!--kg-card-end: html--><p>Instead of connection strings, NCache uses a <code>client.ncconf</code> file. This file can be defined at the application or installation level. We rely on the configuration file at the installation level for our demo. As a result, we just need the cache name.</p><p>In the code snippet above, we are fetching the city from the cache first. The initial call will have an empty cache and it will get the data from the database and add it to the cache, so that the next time when we call this endpoint, the data will be returned from the cache instead of hitting the database.</p><p>Every item in the cache needs an expiration. The <code>CacheItem</code> has an <code>Expiration</code> property for that.</p><p>There are two basic expiration types: <code>Absolute</code> and <code>Sliding</code>. You can learn more about <a href="https://cloudcoders.xyz/blog/azure-cache-for-redis/#retry-guidance-with-stackexchangeredis">expiration types here</a>.</p><p>To add the item with the same key, we used <code>InsertAsync()</code> method. There&apos;s another method <code>Remove()</code> and <code>RemoveAsync()</code>. You might have already guessed what they do.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_14 - incontent_14 -->
<div id="ezoic-pub-ad-placeholder-153"> </div>
<!-- End Ezoic - incontent_14 - incontent_14 --><!--kg-card-end: html--><h4 id="with-idistributedcache">With IDistributedCache</h4><p>Up to this point, we have NCache installed and know how to add and retrieve items. </p><p>Using the IDistributedCache interface provided by Dotnet Core, we can connect our ASP.NET Core apps to any distributed cache cluster and utilize it for caching as needed. Almost all major cache providers provide IDistributedCache implementations, which we can register in the IoC container using IServiceCollection.</p><p>Now, let&apos;s look at how we can implement distributed caching with NCache as the caching provider. </p><p>To connect to the cache server, we need to install the NuGet package <code>Install-Package NCache.Microsoft.Extensions.Caching</code> which we have already installed in the previous section.</p><p>We can register the NCache DistributedCache into the IoC container, through which we can later access the caching service. We can place this inside <code>ConfigureServices()</code> method of &#xA0;<code>Startup.cs</code></p><pre><code class="language-csharp">services.AddNCacheDistributedCache(configuration =&gt;
    {
    configuration.CacheName = &quot;myClusteredCache&quot;;
    configuration.EnableLogs = true;
    configuration.ExceptionsEnabled = true;
    });</code></pre><p> We can also use these configuration values using another overload of the same method as below if you want to configure the cache settings in the appsettings.json file, which we will be doing in this demo.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_15 - incontent_15 -->
<div id="ezoic-pub-ad-placeholder-155"> </div>
<!-- End Ezoic - incontent_15 - incontent_15 --><!--kg-card-end: html--><pre><code class="language-csharp">services.AddNCacheDistributedCache(Configuration.GetSection(&quot;NCacheSettings&quot;));</code></pre><pre><code class="language-JSON">&quot;NCacheSettings&quot;: {
    &quot;CacheName&quot;: &quot;myClusteredCache&quot;,
    &quot;EnableLogs&quot;: true,
    &quot;EnableDetailLogs&quot;: false,
    &quot;ExceptionsEnabled&quot;: true,
    &quot;OperationRetry&quot;: 0,
    &quot;operationRetryInterval&quot;: 0
  }</code></pre><p>Now, let&apos;s look at the code on how to use it to retrieve the lists of cities.</p><pre><code class="language-csharp">[HttpGet]
        public async Task&lt;IActionResult&gt; Get()        
        {
            string recordKey = &quot;CitiesList_&quot; + DateTime.Now.ToString(&quot;yyyyMMdd_hhmm&quot;);
            var cities = await _cache.GetRecordAsync&lt;List&lt;City&gt;&gt;(recordKey);

            if (cities is null)
            {
                cities = (List&lt;City&gt;)await _cityRepository.ListAllAsync();

                // Add CacheItem to cache
                await _cache.SetRecordAsync(recordKey, cities);
            }

            return Ok(cities);
        }</code></pre><p>The above snippet attempts to get the list of cities based on the cache key, &#xA0;where if there is no item existing in the cache, the items are fetched from the database.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_16 - incontent_16 -->
<div id="ezoic-pub-ad-placeholder-156"> </div>
<!-- End Ezoic - incontent_16 - incontent_16 --><!--kg-card-end: html--><p>The implementation of <code>GetRecordAsync()</code> and <code>SetRecordAsync()</code> is as below.</p><pre><code class="language-csharp">public static class DistributedCacheExtensions
    {
        public static async Task SetRecordAsync&lt;T&gt;(this IDistributedCache cache,
              string recordId,
              T data,
              TimeSpan? absoluteExpireTime = null,
              TimeSpan? unusedExpireTime = null)
        {
            var options = new DistributedCacheEntryOptions
            {
                AbsoluteExpirationRelativeToNow = absoluteExpireTime ?? TimeSpan.FromMinutes(10),
                SlidingExpiration = unusedExpireTime
            };

            var jsonData = JsonSerializer.Serialize(data);
            await cache.SetStringAsync(recordId, jsonData, options);
        }

        public static async Task&lt;T&gt; GetRecordAsync&lt;T&gt;(this IDistributedCache cache, string recordId)
        {
            var jsonData = await cache.GetStringAsync(recordId);

            if (jsonData is null)
            {
                return default(T);
            }

            return JsonSerializer.Deserialize&lt;T&gt;(jsonData);
        }
    }</code></pre><p>You can read <a href="https://cloudcoders.xyz/blog/azure-cache-for-redis/">this article</a> to understand the concepts of the above snippet. </p><!--kg-card-begin: html--><!-- Ezoic - incontent_17 - incontent_17 -->
<div id="ezoic-pub-ad-placeholder-157"> </div>
<!-- End Ezoic - incontent_17 - incontent_17 --><!--kg-card-end: html--><h3 id="using-ncache-for-session-caching-in-aspnet-core">Using NCache for session caching in ASP.NET Core</h3><p>Since the HTTP protocol used by web applications is a stateless protocol, data is not stored anywhere; the browser opens a new HTTP connection for each web request. ASP.NET Core supports sessions for storing user data in situations when preserving your data is critical. The ASP.NET Core application itself maintains this datastore on the same server as the application.</p><p>Although ASP.NET Core has an in-memory session provider for storing sessions, the load must sometimes be balanced. Session storage strategies such as sticky sessions and distributed caching are used in these cases, however, sticky sessions are not recommended.</p><h4 id="with-ncache-sessions-services-nuget-package">With NCache sessions services NuGet package</h4><p>Let&apos;s see how we can configure the NCache session provider in ASP.NET Core.</p><p>First, we need to install the NuGet Package in our application. </p><!--kg-card-begin: html--><!-- Ezoic - incontent_18 - incontent_18 -->
<div id="ezoic-pub-ad-placeholder-158"> </div>
<!-- End Ezoic - incontent_18 - incontent_18 --><!--kg-card-end: html--><pre><code>Install-Package AspNetCore.Session.NCache</code></pre><p>To utilize the APIs, include the following namespace in your application in <code>Startup.cs</code></p><pre><code>using Alachisoft.NCache.Web.SessionState;</code></pre><p>Using NCache Session Management Services with ASP.NET Core requires two steps:</p><ol><li>Configuring the session management service.</li><li>Adding middleware to the application.</li></ol><p><strong>Serializing Session Objects</strong></p><p>Before you begin utilizing NCache to store and retrieve your ASP.NET session data, you should be aware that these objects cannot be directly stored within the cache. To save these session objects in the cache, they must first be serialized. You can serialize your session objects using different approaches. These techniques are as follows:</p><!--kg-card-begin: html--><!-- Ezoic - incontent_19 - incontent_19 -->
<div id="ezoic-pub-ad-placeholder-159"> </div>
<!-- End Ezoic - incontent_19 - incontent_19 --><!--kg-card-end: html--><p><strong>Binary Serialization</strong></p><p>If you have access to the application&apos;s source code, you can utilize this serialization approach. In this instance, you must make all of the objects (those you wish to keep in the cache) serializable. However, since of.NET 6.0, this approach is no longer supported.</p><p><br><strong>NCache Compact Serialization</strong></p><p>If you can&apos;t or don&apos;t want to utilize binary serialization, you can serialize your session objects using <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/dynamic-compact-serialization.html">NCahce Compact Serialization</a>. The key advantages of doing so are that it is quicker and simply requires you to alter your configuration files rather than the source code.</p><p>The only issue with this technique is that the configuration change might be significant if the number of classes to serialize is large.</p><p><strong>JSON Serialization</strong></p><p>If neither of the above serialization options works for you, you can use JSON serialization instead. The best aspect of this strategy is that it is really fast and easy since it only takes you to make one modification to your appsettings.json file, and the rest of the work is done automatically by NCache during runtime.</p><p>You only need to set the <code>usejsonserialization</code> setting to <code>true</code>. This flag&apos;s value is <code>false</code> by default.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_20 - incontent_20 -->
<div id="ezoic-pub-ad-placeholder-160"> </div>
<!-- End Ezoic - incontent_20 - incontent_20 --><!--kg-card-end: html--><p><strong>Step 1: Configure NCache Session Management Service</strong></p><p>The session management service needs to be initialized in <code>Startup.cs</code>. There are two methods to specify configurations:</p><ol><li>Through your application in <em>Startup class</em> or</li><li>In JSON format in <em>Appsettings.json</em></li></ol><p><strong><strong>Method 1: Specifying Configurations in Startup</strong> class</strong></p><p>The <code>AddNCacheSession()</code> extension method, which accepts an <code>IOptions&lt;NCacheSessionConfiguration&gt;</code> object as the configuration can be used to start the session.</p><p>Add the following code to your application&apos;s Startup class in the ConfigureServices() method:</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{

    //Add services to the container with configured session 
    services.AddNCacheSession(configuration =&gt;
    {
        configuration.CacheName = &quot;myClusteredCache&quot;;
        configuration.EnableLogs = true;
        configuration.SessionAppId = &quot;demoApp&quot;;
        configuration.SessionOptions.IdleTimeout = 5;
        configuration.SessionOptions.CookieName = &quot;AspNetCore.Session&quot;;
    });                   

}</code></pre><p><strong><strong>Method 2: Specifying Configurations in Appsettings.json</strong></strong></p><p>The configurations for the services can also be provided in JSON format as a section in <em>Appsettings.json</em> of your ASP.NET application:</p><pre><code class="language-JSON">{
  &quot;NCacheSettings&quot;: {
    &quot;SessionAppId&quot;: &quot;demoApp&quot;,
    &quot;SessionOptions&quot;: {
      &quot;CookieName&quot;: &quot;AspNetCore.Session&quot;,
      &quot;CookieDomain&quot;: null,
      &quot;CookiePath&quot;: &quot;/&quot;,
      &quot;CookieHttpOnly&quot;: &quot;True&quot;,
      &quot;IdleTimeout&quot;: &quot;5&quot;,
      &quot;CookieSecure&quot;: &quot;None&quot;,
     &quot;useJsonSerialization&quot;: true,
    },

    &quot;CacheName&quot;: &quot;myClusteredCache&quot;,
    &quot;EnableLogs&quot;: &quot;True&quot;,
    &quot;RequestTimeout&quot;: &quot;90&quot;
  },
}</code></pre><p>NCache provides the <code>AddNCacheSession()</code> method to initialize configurations from external files before adding the session services to the container. You can use this method to refer to the configurations by specifying the name of the section in Appsettings.json that contains JSON format configurations:</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{ 
    //Add services to the container                    
    services.AddNCacheSession(Configuration.GetSection(&quot;NCacheSettings&quot;));
}
</code></pre><p><strong>Step 2: Add Middleware to the Application</strong></p><p>After the services have been initialized, you can now set up the HTTP request pipeline by using the <code>Configure()</code> method to add middleware. The following is an example of how to add a middleware layer in <code>IApplicationBuilder</code> by using the <strong>UseNCacheSession()</strong> extension method. Always stack the NCache session middleware before the layer that uses the sessions.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_21 - incontent_21 -->
<div id="ezoic-pub-ad-placeholder-161"> </div>
<!-- End Ezoic - incontent_21 - incontent_21 --><!--kg-card-end: html--><pre><code class="language-csharp">public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.UseNCacheSession(); //store NCache session data 
        }</code></pre><p>Once NCache has been set as the default cache for ASP.NET Core sessions, you can execute all ASP.NET Core-specific operations without changing any code. All sessions will be cached in distributed NCache.</p><p>You can find the additional source code on <a href="https://github.com/nandkishor-yadav/NCacheDemo/blob/main/SessionCaching/Controllers/HomeController.cs">GitHub</a>.</p><h4 id="with-idistributedcache-1">With IDistributedCache</h4><p>ASP.NET Core sessions can also be used with NCache&apos;s IDistributedCache Provider. To add a default implementation of <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.caching.distributed.idistributedcache?view=dotnet-plat-ext-6.0&amp;viewFallbackFrom=aspnetcore-2.2">IDistributedCache</a>, use the <code>AddDistributedMemoryCache()</code> function in ASP.NET Core. To use NCache as a distributed cache to store ASP.NET sessions or objects, use the <code>AddNCacheDistributedCache()</code> extension method, which adds NCache as the default distributed cache as an implementation of IDistributedCache.</p><p>First, install the <a href="https://cloudcoders.xyz/blog/using-ncache-for-object-caching-in-aspnet-core-with-ncache-sdk-nuget-package">NuGet package</a> depending on the version of NCache you are using.</p><p>To utilize the APIs, include the following namespace in your application in <code>Startup.cs</code> of your application:</p><!--kg-card-begin: html--><!-- Ezoic - incontent_22 - incontent_22 -->
<div id="ezoic-pub-ad-placeholder-162"> </div>
<!-- End Ezoic - incontent_22 - incontent_22 --><!--kg-card-end: html--><pre><code>using Alachisoft.NCache.Caching.Distributed;</code></pre><p>You can configure NCache as a distributed cache for your ASP.NET Core application in two steps:</p><ol><li>Configuring services</li><li>Adding middleware to the application</li></ol><p><strong>Step 1: Configure Services</strong></p><p>The AddNCacheDistributedCache() extension method on IServiceCollection requires just a cache name in NCache and any optional parameters to store the sessions. The configuration object is the same as NCache ASP.NET Core Session Provider, and it can be started in the same way. The settings can also be given using the IOptions initializer.</p><p>There are two methods to specify configurations:</p><ul><li>Through your application in <em>Startup class</em> or</li><li>In JSON format in <em>Appsettings.json</em> of your application.</li></ul><p><strong>Method 1: Specifying Configurations In Startup class</strong></p><p><em><strong>Configure Startup class for Single Cache:</strong></em></p><p>The <strong>AddNCacheDistributedCache()</strong> method is an extension of the ASP.NET Core <strong>AddDistributedCache()</strong> method. This method takes configuration parameters from your application&apos;s Startup class file or reads them from the supplied JSON file.</p><p>Add the following methods and options to your application&apos;s Startup class:</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{
	services.AddNCacheDistributedCache(configuration =&gt;
    {
        configuration.CacheName = &quot;myClusteredCache&quot;;
        configuration.EnableLogs = true;
        configuration.ExceptionsEnabled = true; 
    });
}
</code></pre><!--kg-card-begin: html--><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5134801822845872" crossorigin="anonymous"></script>
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-5134801822845872" data-ad-slot="7673531100"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script><!--kg-card-end: html--><p><em><strong>Configure Startup class for multiple Cache:</strong></em></p><p>Using the AddNCacheDistributedCacheProvider method, you may configure multiple caches as follows:</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{
    services.AddNCacheDistributedCacheProvider( options =&gt;
             {
                options.CacheConfigurations = new NCacheConfiguration[] {
                new NCacheConfiguration() {
                    CacheName = &quot;myClusteredCache&quot;,
                    EnableLogs = true,
                    ExceptionsEnabled = true
                },
                new NCacheConfiguration(){
                    CacheName = &quot;demoCache&quot;,
                    EnableLogs = true,
                    ExceptionsEnabled = true }
                }; 
             });
} 
</code></pre><p><strong>Method 2: Specifying Configurations In Appsettings.json</strong></p><p>In the Appsettings.json file of your application, you can also specify the configurations within your application in JSON format. You can refer to the configurations using this method by specifying the name of the section in the Startup class that contains JSON format configurations.</p><pre><code class="language-JSON">{
  &quot;NCacheSettings&quot;: {
    &quot;CacheName&quot;: &quot;myClusteredCache&quot;,
    &quot;EnableLogs&quot;: &quot;True&quot;,
    &quot;RequestTimeout&quot;: &quot;90&quot;
  },
}</code></pre><p>Refer to these configurations in the Startup class as follows:</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{
	services.AddNCacheDistributedCache(Configuration.GetSection(&quot;NCacheSettings&quot;)); 

    services.AddSession();
}</code></pre><p><strong><strong>Configure Appsettings.json for Multiple Caches:</strong></strong></p><pre><code class="language-JSON">&quot;NCacheFactorySettings&quot;: {
    &quot;NCacheConfigurations&quot;: [
        {
            &quot;CacheName&quot;: &quot;myClusteredCache&quot;,
            &quot;EnableLogs&quot;: true,
            &quot;RequestTimeout&quot;: &quot;90&quot; 
        },
        {
            &quot;CacheName&quot;: &quot;demoCache&quot;,
            &quot;EnableLogs&quot;: true,
            &quot;RequestTimeout&quot;: &quot;90&quot;
        },
        {
            // Configure more caches
        }
    ]
}</code></pre><p>Use the <code>AddNCacheDistributedCacheProvider</code> method to refer the <code>NCacheFactorySettings</code> section in Startup.cs:</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{    services.AddNCacheDistributedCacheProvider(_config.GetSection(&quot;NCacheFactorySettings&quot;)); 

    services.AddSession();
}
</code></pre><!--kg-card-begin: html--><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5134801822845872" crossorigin="anonymous"></script>
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-5134801822845872" data-ad-slot="7673531100"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script><!--kg-card-end: html--><p><strong>Step 2: Add Middleware to the Application</strong></p><p>Sessions can store data in NCache once the distributed cache has been added to the service. The ASP.NET Core <strong>UseSession()</strong> extension method adds the default session middleware to the application, but it uses NCache as its cache.</p><p>The following block of code represents how to fetch an item from the cache and how to insert an item in it.</p><pre><code class="language-csharp">public IActionResult CacheOperations()
    {
        // Cache entry is of DateTime type
        DateTime cacheEntry;

        string cacheKey = &quot;MaxValue: &quot; + DateTime.MaxValue;

        // Look for cache key
        object retrieveObj = _cache.Get(cacheKey);

        // Check if key exists in cache
        if (retrieveObj != null)
        {
            // Return view with result
        }
        else
        {
            // Key not in cache, so populate data in cache entry
            cacheEntry = DateTime.MaxValue;

            // Configure SlidingExpiration for item 
            var cacheEntryOptions = new DistributedCacheEntryOptions();
            cacheEntryOptions.SlidingExpiration = TimeSpan.FromMinutes(30);

            // Insert item in cache
            _cache.Set(cacheKey, new byte[1024], cacheEntryOptions);

            // Return view with cacheEntry
        }
    }</code></pre><h3 id="using-ncache-for-response-caching-in-aspnet-core">Using NCache for response caching in ASP.NET Core</h3><p>The ability to cache web server responses using cache-related headers in HTTP response objects is referred to as <a href="https://docs.microsoft.com/en-us/aspnet/core/performance/caching/response?view=aspnetcore-6.0">response caching</a>. These headers indicate how to cache responses for all or a subset of requests. It is important to note that, unlike output caching, response caching in ASP.Net Core does not store responses in the web server&apos;s memory.</p><p>Response caching in ASP.Net Core is a more advanced and expandable version of output caching. It instructs web browsers to cache content by including cache-related headers in HTTP responses. This can drastically minimize the number of requests made by a client to the web server, as future requests can be served from the client&apos;s cache. It should be noted that response caching caches data in memory by default, but you can set up custom storage providers if necessary.</p><h4 id="when-to-use-response-caching">When to use Response Caching?</h4><p>You can use response caching to cache objects that are static and have little possibility of being updated, such as CSS, JavaScript files, &#xA0;media, or metadata of a webpage.</p><p>To use NCache as a distributed cache for response caching, NCache provides its own extension methods to configure services and middleware.</p><p><em>Installing the NuGet packages: </em>Install the following package from the package manager console in your project.</p><pre><code>Install-Package NCache.Microsoft.Extensions.Caching</code></pre><p>To use NCache&apos;s response caching methods, add the following namespace in your application:</p><pre><code>using Alachisoft.NCache.Caching.Distributed;
</code></pre><p><strong>Configure Response Caching Service</strong></p><p>For response caching, ASP.NET Core has its own middleware. This has to be added to the service collection using the <a href="https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.responsecachingservicesextensions.addresponsecaching?view=aspnetcore-2.0">AddResponseCaching()</a> method.</p><ul><li>Open the <code>Startup.cs</code> of your project</li><li>In the <code>ConfigureServices()</code> method, add the following service:</li></ul><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
{
    services.AddResponseCaching();

    //remaining services here
}
</code></pre><p>Then add the UseResponsecaching() method to add the response caching middleware to the pipeline.</p><pre><code class="language-csharp">public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // other code
            app.UseResponseCaching();
        }</code></pre><!--kg-card-begin: html--><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5134801822845872" crossorigin="anonymous"></script>
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-5134801822845872" data-ad-slot="7673531100"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script><!--kg-card-end: html--><h4 id="with-ncache-response-caching-middleware">With NCache response caching middleware</h4><p>ASP.NET Core has built-in response caching, which is a great feature. It can be used to limit the number of requests sent to a web server by a client. NCache can also be used as a middleware for response caching. Let&apos;s look at how we can do this.</p><p>To use NCache as a response cache middleware, you need to do the following:</p><ul><li>Specify the NCache settings in the Appsettings.json file</li><li>Invoke the AddResponseCaching and AddNCacheDistributedCache methods in the ConfigureServices method of the Startup class.</li></ul><p>You can configure NCache as a distributed cache in two ways:</p><ul><li>By specifying cache configuration in AppSettings.json</li><li>By specifying cache configuration in IOptions</li></ul><p><strong>Specify cache configuration in the AppSettings.json file</strong></p><pre><code class="language-JSON"> &quot;NCacheSettings&quot;: {
    &quot;CacheName&quot;: &quot;myClusteredCache&quot;,
    &quot;EnableLogs&quot;: true,
    &quot;EnableDetailLogs&quot;: false,
    &quot;ExceptionsEnabled&quot;: true,
    &quot;OperationRetry&quot;: 0,
    &quot;operationRetryInterval&quot;: 0
  }</code></pre><p>The NCache library implements the ASP.NET Core IDistributedCache interface. This enables you to use NCache in ASP.NET Core as a response cache middleware.</p><p>In the ConfigureServices() method, write the following code to use NCache as your response cache middleware.</p><pre><code class="language-chsarp">public void ConfigureServices(IServiceCollection services)
        {
            services.AddResponseCaching();
            services.AddNCacheDistributedCache(Configuration.GetSection(&quot;NCacheSettings&quot;));
            services.AddMvc();
        }</code></pre><p><strong>Specify cache configuration in IOptions</strong></p><p>NCache configuration details can also be specified as IOptions.</p><pre><code class="language-csharp">public void ConfigureServices(IServiceCollection services)
        {
            // other services.. 
            services.AddMvc();
            services.AddNCacheDistributedCache(options =&gt;
            {
                options.CacheName = &quot;myClusteredCache&quot;;
                options.EnableLogs = true;
                options.ExceptionsEnabled = true;
            });
        }</code></pre><p>Next, we&apos;ll look at how to use NCache as a response caching middleware in the action methods.</p><p>You can use the following code to take advantage of response caching in the action method, assuming that you have configured the response caching middleware successfully.</p><pre><code class="language-charp">        [ResponseCache(Duration = 60, Location = ResponseCacheLocation.None, NoStore = false)]
        public IActionResult ResponseCache()
        {
            return View();
        }</code></pre><p>The Duration option specifies how long the data will be stored in the cache. The ResponseCacheAttribute is used to specify response caching options. You can use the Location argument to specify whether any client or intermediate proxy will cache the data.</p><p><strong>Use Distributed Cache Tag Helper</strong></p><p>You can now specify the content that you would like to cache. You can take advantage of Distributed Cache Tag Helpers in ASP.NET Core.</p><p>The following code snippet illustrates how you can specify an item to remain in the cache forever.</p><pre><code class="language-csharp">&lt;distributed-cache name=&quot;Key:1&quot; &gt;
    &lt;div&gt;@DateTime.Now.ToString()&lt;/div&gt;
&lt;/distributed-cache&gt;</code></pre><p>To set an expiry for a cached item, use the below code</p><pre><code class="language-csharp">&lt;distributed-cache name=&quot;Key:2&quot; expires-after =&quot;TimeSpan.FromSeconds(10)&quot;&gt;
    &lt;div&gt;@DateTime.Now.ToString()&lt;/div&gt;&lt;br /&gt;
&lt;/distributed-cache&gt;</code></pre><p>To remove the item from the cache if the &quot;vary-by&quot; value is changed.</p><pre><code class="language-csharp">&lt;distributed-cache name=&quot;Key:3&quot; vary-by =&quot;test&quot;&gt;
    &lt;div&gt;@DateTime.Now.ToString()&lt;/div&gt;&lt;br /&gt;
&lt;/distributed-cache&gt;</code></pre><p>The source code used in this article is on <a href="https://github.com/nandkishor-yadav/NCacheDemo">GitHub</a>.</p><!--kg-card-begin: html--><!-- Ezoic - bottom_of_page - bottom_of_page -->
<div id="ezoic-pub-ad-placeholder-148"> </div>
<!-- End Ezoic - bottom_of_page - bottom_of_page --><!--kg-card-end: html--><h2 id="summary">Summary</h2><p>Caching is a proven technique used in web applications to improve performance and responsiveness. In this article, I tried to explain in-depth the different features of caching in ASP.NET Core using NCache. For more information on NCache and how it can be used in ASP.NET Core, you can refer to the online documentation for <a href="http://www.alachisoft.com/resources/docs/#ncache">NCache</a>.</p>]]></content:encoded></item><item><title><![CDATA[How to use SWR  in Next JS - client-side data-fetching technique]]></title><description><![CDATA[You've probably heard about SWR if you've lately worked with client-side data fetching in Next.js. It comes with useSWR, a React hook that simplifies all the difficult things in client-side data fetching (caching, revalidation, attention tracking, and so on).]]></description><link>https://cloudcoders.xyz/blog/how-to-use-swr-in-next-js-client-side-data-fetching-technique/</link><guid isPermaLink="false">61e5ca9934cb4f99f86c9ca4</guid><category><![CDATA[NextJs]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Tue, 19 Apr 2022 15:52:08 GMT</pubDate><media:content url="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/useSWR.webp" medium="image"/><content:encoded><![CDATA[<img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/useSWR.webp" alt="How to use SWR  in Next JS - client-side data-fetching technique"><p>Data fetching patterns are an essential component of every web framework. As a result, this aspect of every web technology has experienced constant improvements and innovations.</p><!--kg-card-begin: html--><!-- Ezoic - under_feature_image - under_page_title -->
<div id="ezoic-pub-ad-placeholder-137"> </div>
<!-- End Ezoic - under_feature_image - under_page_title --><!--kg-card-end: html--><p>Next.js offers several ways for fetching data since it supports both client and server-side rendering. One way is to use SWR, which is a collection of React hooks for getting data from a remote location.</p><p>In this article, we&apos;ll look at SWR, a library that helps with caching, pagination, revalidation, and other tasks. We&apos;ll also create a client-side Next.js app that uses SWR to retrieve data from a <a href="https://jsonplaceholder.typicode.com/">JSON Placeholder</a>.</p><!--kg-card-begin: html--><!-- Ezoic - under_first_paragraph - under_first_paragraph -->
<div id="ezoic-pub-ad-placeholder-138"> </div>
<!-- End Ezoic - under_first_paragraph - under_first_paragraph --><!--kg-card-end: html--><h2 id="what-is-swr">What is SWR?</h2><p><strong>SWR stands for <code>stale-while-revalidate</code>. It&apos;s a lightweight library made by the same people that made Next.js. It&apos;s essentially a set of React Hooks that come with built-in functionality like revalidation, mutation, and caching. </strong></p><!--kg-card-begin: html--><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5134801822845872" crossorigin="anonymous"></script>
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-5134801822845872" data-ad-slot="7673531100"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script><!--kg-card-end: html--><p>SWR works in three stages: </p><ul><li>it first returns the cache (stale), </li><li>then fetches the data from the server (revalidation), </li><li>and lastly returns the most recent data. By allowing you to present anything to your user while getting fresh data from the server, SWR improves your user experience.</li></ul><p>SWR is backend agnostic, which means it can fetch data from any server that supports HTTP requests. It also offers decent TypeScript and server-side rendering capabilities.</p><!--kg-card-begin: html--><!-- Ezoic - under_second_paragraph - under_second_paragraph -->
<div id="ezoic-pub-ad-placeholder-139"> </div>
<!-- End Ezoic - under_second_paragraph - under_second_paragraph --><!--kg-card-end: html--><h2 id="advantages-of-swr">Advantages of SWR</h2><ul><li><strong>Focus Revalidation</strong>: SWR automatically revalidates data when you refocus a page or switch between tabs in the browser.</li><li><strong>Fast Navigation</strong>: As soon as data is rendered from the cache, SWR immediately revalidates the data from the origin.</li><li><strong>Refetch on Interva</strong>l: SWR will allow you the option to retrieve data automatically, whereas prefetching will only take place of the component associated with the hook on the screen.</li><li><strong><strong>Local Mutation</strong></strong>: Applying changes to data locally, i.e. always updated to the most recent data.</li><li><strong><strong>Dependent Fetching</strong></strong>: You can use SWR to get data that is dependent on other data. It ensures maximum parallelism (to minimize waterfalls) and serial fetching when a piece of dynamic data is necessary for the next data fetch to take place.</li><li><strong><strong>Scalable</strong>: </strong>SWR scales extremely well because it requires very little effort to write applications that automatically and eventually converge to the most recent remote data.</li></ul><!--kg-card-begin: html--><!-- Ezoic - long_content - long_content -->
<div id="ezoic-pub-ad-placeholder-140"> </div>
<!-- End Ezoic - long_content - long_content --><!--kg-card-end: html--><h2 id="disadvantages-of-swr">Disadvantages of SWR</h2><ul><li>One of the biggest drawbacks of using SWR is that it may cause the user to view stale data, which can occur due to a lack of effective API implementation, an error in updating the displayed information, or a variety of other factors.</li><li>Apart from creating a poor user experience, this might also be the only cause of a company&apos;s failure! Consider a well-known financial firm: can they afford to have its users looking at stale data? No way, and that&apos;s why SWR must be implemented and used correctly.</li></ul><h2 id="where-should-you-use-swr-and-where-not-to">Where Should You Use SWR? (And Where Not To)</h2><!--kg-card-begin: html--><span id="ezoic-pub-video-placeholder-6"></span><!--kg-card-end: html--><p>SWR can be implemented in a variety of places, here are a few examples of sites categories where SWR would be a good fit:</p><ul><li><strong>Sites with live data must be updated often.</strong><br> Examples of such sites would be sports score sites and flight tracking. You should utilize the revalidate on interval option with a low interval value when creating these sites (one to five seconds).</li><li><strong>Sites offering real-time updates or postings in the form of a feed.</strong><br> The news sites that feature live blogging of events such as elections are a classic example of this.</li><li><strong>Sites that provide more passive data updates and are frequently left open in the background</strong><em><strong>.</strong></em><br>Weather pages or, in the 2020s, COVID-19 case number pages are examples of these web pages. Because these pages aren&apos;t updated as regularly as the preceding two, they don&apos;t require the same level of revalidation. However, having the data refresh would improve the user experience. In these circumstances, I&apos;d consider revalidating the date when the tab regains focus and the client reconnects to the internet; this ensures that if a user returns to the tab, expecting a tiny rise in COVID cases, they&apos;ll obtain that information promptly.</li><li><strong>Sites with small pieces of data that users can interact with.</strong><br>Consider the Youtube Subscribe Button: when you click subscribe, you want to see the number change and feel like you&apos;ve helped. In these circumstances, you can programmatically revalidate the data by retrieving the updated count and updating the displayed amount using SWR.<br>It&apos;s worth noting that all of them may be used with or without ISR.</li></ul><!--kg-card-begin: html--><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5134801822845872" crossorigin="anonymous"></script>
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-5134801822845872" data-ad-slot="7673531100"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script><!--kg-card-end: html--><p>Of course, there are some situations where you won&apos;t want to use SWR or SWR without ISR. SWR isn&apos;t very useful if your data doesn&apos;t change much or at all, and instead clogs your network requests and consumes mobile users&apos; bandwidth. SWR can be used on sites that need authentication, but you should utilize Server Side Rendering instead of Incremental Static Regeneration in these circumstances.</p><!--kg-card-begin: html--><!-- Ezoic - longer_content - longer_content -->
<div id="ezoic-pub-ad-placeholder-141"> </div>
<!-- End Ezoic - longer_content - longer_content --><!--kg-card-end: html--><h2 id="useswr-support-for-typescript">useSWR Support for TypeScript</h2><p>SWR is TypeScript-friendly and comes with type safety out of the box. By default, SWR will also infer the argument types of <code>fetcher</code> from <code>key</code>, so you can have the preferred types automatically. That being said, you can specify custom types for your own arguments in the most straightforward way, as follows:</p><pre><code class="language-javascript">import useSWR from &apos;swr&apos;
const { data } = useSWR(&apos;https://www.users.com&apos;, (apiURL: string) =&gt; fetch(apiURL).then(res =&gt; res.json())
</code></pre><p>Working with SWR does not need any extra TypeScript setups. More information regarding <a href="https://swr.vercel.app/docs/typescript">TypeScript and SWR</a> can be found here.</p><p>Let&#x2019;s dive in and set up a new app with Next.js and the useSWR hook.</p><h2 id="setting-up-a-nextjs-application">Setting up a Next.js application</h2><p>To quickly set up a Next.js application, open a terminal window and run the <code>create-next-app</code> a command like so:</p><pre><code class="language-bash">npx create-next-app next-swr-app</code></pre><p>Navigate into the application directory and install SWR with this command:</p><pre><code class="language-bash">cd next-swr-app # navigate into the project directory
npm install swr # install swr
npm run dev # run the dev server</code></pre><p>The commands above will install the SWR packages, as well as open the project &#xA0;<code>localhost:3000</code> &#xA0;in your browser. We should have the project up and running on that port as follows: </p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/data-fetching-next-js-useswr-welcome-next-js-page.webp" class="kg-image" alt="How to use SWR  in Next JS - client-side data-fetching technique" loading="lazy" width="1903" height="932"></figure><p>We&apos;ve successfully set up a Next.js application, which is fantastic. Let&apos;s get this thing built, shall we?</p><!--kg-card-begin: html--><!-- Ezoic - longest_content - longest_content -->
<div id="ezoic-pub-ad-placeholder-142"> </div>
<!-- End Ezoic - longest_content - longest_content --><!--kg-card-end: html--><h2 id="data-fetching-with-swr">Data fetching with SWR</h2><p>We may use <code>useSWR </code>or <code>useSWRInfinite</code> to get remote data using SWR. There are, however, certain distinctions between the hooks. The first hook is only for data fetching, whereas the second allows for data retrieval and pagination. You can use <code>useSWRInfinite</code> to quickly add infinite scrolling or pagination to your Next.js project.</p><p>Create a <code>components</code> folder in the project&apos;s root directory, add a <code>useRequest.js</code> file, and update it with the snippet below.</p><pre><code class="language-javascript">// components/useRequest.js

import useSWR from &apos;swr&apos;;

const fetcher = (url) =&gt; fetch(url).then((res) =&gt; res.json());

const url = &apos;https://jsonplaceholder.typicode.com/posts&apos;;

export const useGetPosts = () =&gt; {
  const { data, error } = useSWR(url, fetcher);

  return { data, error };
};</code></pre><p>Let&apos;s have a look at the code. We&apos;re using the useSWR() hook in the code above to get data for posts.</p><p>The useSWR hook takes two parameters and returns two results (based on the status of the request). It accepts the following:</p><ul><li>A <code>Key</code>: a string that serves as the unique identifier for the data we are fetching. This is usually the API URL we are calling.</li><li>A <code>fetcher</code>: a function that returns the fetched data.</li></ul><p>It returns:</p><ul><li><code>data</code> &#x2014; the result of the request (if it was successful)</li><li><code>error</code> &#x2014; the error that occurred (if there was an error)</li></ul><p>Create <code>Posts.js</code> file inside the components folder and update its contents with the following snippet.</p><pre><code class="language-javascript">// components/Posts.js

export default function Post({ post }) {
  const { title, body, id } = post;
  return (
    &lt;&gt;
      &lt;div className=&quot;p-4 mb-4 text-sm text-blue-700 bg-blue-100 rounded-lg&quot;&gt;
        &lt;p className=&quot;font-medium&quot;&gt;
          {id}. {title}
        &lt;/p&gt;
        &lt;p&gt;{body}&lt;/p&gt;
      &lt;/div&gt;
    &lt;/&gt;
  );
}</code></pre><p>As you can see, we have a simple component that receives the <code>post</code> &#xA0;to display as a parameter. Then, we use destructuring to pull out the elements from the object in order to show the post.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_5 - incontent_5 -->
<div id="ezoic-pub-ad-placeholder-143"> </div>
<!-- End Ezoic - incontent_5 - incontent_5 --><!--kg-card-end: html--><p>Now, let&apos;s update the <code>index.js</code> file.</p><pre><code class="language-javascript">import Head from &apos;next/head&apos;;
import Post from &apos;../components/Posts&apos;;
import { useGetPosts } from &apos;../components/useRequest&apos;;

export default function Home() {
  const { data: posts, error } = useGetPosts();
    
  if (error) return &lt;h1&gt;Something went wrong!&lt;/h1&gt;;
  if (!posts) return &lt;h1&gt;Loading...&lt;/h1&gt;;

  return (
    &lt;div&gt;
      &lt;Head&gt;
        &lt;title&gt;Next SWR App&lt;/title&gt;
        &lt;meta name=&quot;description&quot; content=&quot;Generated by create next app&quot; /&gt;
        &lt;link rel=&quot;icon&quot; href=&quot;/favicon.ico&quot; /&gt;
      &lt;/Head&gt;

      &lt;main className=&quot;max-w-xl mx-auto&quot;&gt;
        &lt;h1 className=&quot;font-bold m-5&quot;&gt;My Posts&lt;/h1&gt;
        {posts.map((post) =&gt; (
          &lt;Post post={post} key={post.id} /&gt;
        ))}
      &lt;/main&gt;
    &lt;/div&gt;
  );
}</code></pre><p>We first import the <code>useGetPosts</code> hook. It returns a list of posts to display as well as an error state if any.</p><p>After that, we use the <code>Post</code> component to display the array of data. If any error occurs, we handle it accordingly with the <code>error</code> provided by SWR.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_6 - incontent_6 -->
<div id="ezoic-pub-ad-placeholder-144"> </div>
<!-- End Ezoic - incontent_6 - incontent_6 --><!--kg-card-end: html--><p>When you return to the browser, you should see posts appear as expected:</p><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/how-to-use-swr-in-next-js-client-side-data-fetching-technique-posts.webp" class="kg-image" alt="How to use SWR  in Next JS - client-side data-fetching technique" loading="lazy" width="611" height="880"></figure><p>There! We&apos;ve got our posts. So, our <code>useSWR</code> hook is up and running. Is that it, though? What makes this different from other data retrieval methods? Continue reading to learn more...</p><!--kg-card-begin: html--><!-- Ezoic - incontent_7 - incontent_7 -->
<div id="ezoic-pub-ad-placeholder-145"> </div>
<!-- End Ezoic - incontent_7 - incontent_7 --><!--kg-card-end: html--><h3 id="why-useswr">Why <code>useSWR</code>?</h3><p>It&#x2019;s a likely question to ask at this point. I wouldn&apos;t say this is a significant improvement for me yet, except for being extremely declarative. This makes this a great time to discuss some of useSWR&apos;s features.</p><h3 id="pagination">Pagination</h3><p>Consider the following scenario: instead of loading only ten posts, we want to be able to generate posts on-demand and add them to this page. This is very useful when creating an app that requires users to scroll through numerous pages with the same content. We can show this by including a Load More button at the bottom of our post&apos;s page that, when clicked, generates more posts.</p><p>It&apos;s still possible to use the useSWR hook to paginate the data, but let&apos;s use <code>useSWRInfinite</code> hook to achieve it.</p><p>Let&apos;s add another function in <code>useRequest.js</code></p><pre><code class="language-javascript">// components/useRequest.js

import useSWRInfinite from &apos;swr/infinite&apos;;

const fetcher = (url) =&gt; fetch(url).then((res) =&gt; res.json());

const url = &apos;https://jsonplaceholder.typicode.com/posts&apos;;

export const usePaginatePosts = () =&gt; {
  const PAGE_LIMIT = 20;

  const { data, error, size, setSize } = useSWRInfinite(
    (index) =&gt; `${url}?_page=${index + 1}&amp;_limit=${PAGE_LIMIT}`,
    fetcher
  );

  const posts = data ? [].concat(...data) : [];
  const isLoadingInitialData = !data &amp;&amp; !error;
  const isLoadingMore =
    isLoadingInitialData ||
    (size &gt; 0 &amp;&amp; data &amp;&amp; typeof data[size - 1] === &apos;undefined&apos;);
  const isEmpty = data?.[0]?.length === 0;
  const isReachingEnd =
    isEmpty || (data &amp;&amp; data[data.length - 1]?.length &lt; PAGE_LIMIT);

  return { posts, error, isLoadingMore, size, setSize, isReachingEnd };
};</code></pre><!--kg-card-begin: html--><!-- Ezoic - incontent_8 - incontent_8 -->
<div id="ezoic-pub-ad-placeholder-146"> </div>
<!-- End Ezoic - incontent_8 - incontent_8 --><!--kg-card-end: html--><p>The <code>useSWRInfinite</code> hook expects as an argument a function that returns the request key, a <code>fetcher</code> function, and options. The request key (<code>index</code>) is what SWR uses to know what data (page) to retrieve. The initial value of the request key is <strong>0</strong>, so we have to increment it by <strong>1</strong> upon each request. The second argument to define the URL is PAGE_LIMIT, which is the number of items to fetch per request.</p><p><code>useSWRInfinite</code> returns more values than that. I removed the data that I don&apos;t need here. Let&apos;s explain what these variables do:</p><ul><li><code>posts</code> is the array of the data fetched from the server.</li><li><code>isLoadingInitialData</code> checks if there is still data to retrieve.</li><li><code>isLoadingMore</code> checks if we&apos;re currently retrieving data.</li><li><code>isEmpty</code> checks whether the array of data is empty or not.</li><li><code>isReachingEnd</code> checks if the page limit is reached or not.</li></ul><p>Next, we return the values in order to use them in our components.</p><pre><code class="language-javascript">// index.js
import Head from &apos;next/head&apos;;
import Post from &apos;../components/Posts&apos;;
import { usePaginatePosts } from &apos;../components/useRequest&apos;;

export default function Home() {
  const { posts, error, isLoadingMore, size, setSize, isReachingEnd } =
    usePaginatePosts();

  if (error) return &lt;h1&gt;Something went wrong!&lt;/h1&gt;;
  if (!posts) return &lt;h1&gt;Loading..&lt;/h1&gt;;

  return (
    &lt;div&gt;
      &lt;Head&gt;
        &lt;title&gt;Next SWR App&lt;/title&gt;
        &lt;meta name=&quot;description&quot; content=&quot;Generated by create next app&quot; /&gt;
        &lt;link rel=&quot;icon&quot; href=&quot;/favicon.ico&quot; /&gt;
      &lt;/Head&gt;

      &lt;main className=&quot;max-w-xl mx-auto&quot;&gt;
        &lt;h1 className=&quot;font-bold m-5&quot;&gt;My Posts&lt;/h1&gt;
        {posts.map((post) =&gt; (
          &lt;Post post={post} key={post.id} /&gt;
        ))}
        &lt;button
          disabled={isLoadingMore || isReachingEnd}
          onClick={() =&gt; setSize(size + 1)}
        &gt;
          {isLoadingMore
            ? &apos;Loading...&apos;
            : isReachingEnd
            ? &apos;No more posts&apos;
            : &apos;Load more&apos;}
        &lt;/button&gt;
      &lt;/main&gt;
    &lt;/div&gt;
  );
}</code></pre><p>We begin by importing <code>usePaginatePosts</code>. The values returned by the hook are then used to show the posts and load fresh data. SWR will forward the request to the next page and then return the data if the load more button is pressed. The data is now paginated using the <code>useSWRInfinite</code> hook.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_9 - incontent_9 -->
<div id="ezoic-pub-ad-placeholder-147"> </div>
<!-- End Ezoic - incontent_9 - incontent_9 --><!--kg-card-end: html--><h2 id="complex-use-case">Complex use case</h2><p>Let&#x2019;s explore a more complex use case. You can check out the <a href="https://swr.vercel.app/docs/getting-started" rel="noopener">SWR docs</a> for more details on usage and benefits.</p><h2 id="mutation-and-revalidation-with-useswr">Mutation and revalidation with useSWR</h2><p>So let&#x2019;s say that we had our own <code>/comments</code> endpoint where we can retrieve all our comments from the database and also post to the endpoint to add new comments.</p><p>We can immediately write the code to look like this:</p><pre><code class="language-javascript">import useSWR from &quot;swr&quot;;  
  const address = `http://localhost:3000/api/comments`;  
  const fetcher = (...args) =&gt; fetch(...args).then((res) =&gt; res.json());
  const { data, error } = useSWR(address, fetcher);
  const addComment = async () =&gt; {
    const newComment = {
      comment: &quot;This is a test comment&quot;,
      email: &quot;rb@doe.com&quot;,
    };
    await fetcher(address, {
      method: &quot;POST&quot;,
      body: JSON.stringify(newComment),
    });
  };</code></pre><p>When we click a button to trigger the <code>addComment()</code> function, we&apos;ll use <code>useSWR</code> to post to the <code>/comments</code> endpoint, effectively adding a new comment to the database. However, our site will not know that there&#x2019;s been an update and therefore we won&#x2019;t see that comment on screen.</p><p>This is where the useSWR mutation comes in. We can use mutation to revalidate our page to:</p><ol><li>Check if there&#x2019;s new data</li><li>If there is, revalidate the page and render the new data without triggering a full page reload:</li></ol><!--kg-card-begin: html--><!-- Ezoic - incontent_10 - incontent_10 -->
<div id="ezoic-pub-ad-placeholder-149"> </div>
<!-- End Ezoic - incontent_10 - incontent_10 --><!--kg-card-end: html--><pre><code class="language-javascript">import useSWR from &quot;swr&quot;;  
  const address = `http://localhost:3000/api/comments`;  
  const fetcher = (...args) =&gt; fetch(...args).then((res) =&gt; res.json());
  const { data, error } = useSWR(address, fetcher);
  const addComment = async () =&gt; {
    const newComment = {
      comment: &apos;This is a test comment&apos;,
      email: &apos;rb@doe.com&apos;,
    };
    await fetcher(address, {
      method: &apos;POST&apos;,
      body: JSON.stringify(newComment),
    });
    mutate(address);
  };</code></pre><p>useSWR will now revalidate the page when we update the database by posting a new comment, ensuring that we don&apos;t offer stale data.</p><p>However, useSWR will revalidate your page on focus automatically to ensure that your data is maintained up to date. You may disable revalidation on focus by passing the following option to SWR as an argument:</p><pre><code class="language-javascript">const { data, error } = useSWR(address, fetcher, {
    revalidateOnFocus: false
  });</code></pre><h2 id="conclusion">Conclusion</h2><p>We&apos;ve covered the basics of the useSWR hook in this post. We also used Next.js to create a blog post app to illustrate the SWR features. I hope this post has given you some insight into using useSWR to fetch data in Next.js apps. </p><p>If you like the contents then please share this article</p><!--kg-card-begin: html--><!-- Ezoic - bottom_of_page - bottom_of_page -->
<div id="ezoic-pub-ad-placeholder-148"> </div>
<!-- End Ezoic - bottom_of_page - bottom_of_page --><!--kg-card-end: html--><p>The source code can be found <a href="https://github.com/nandkishor-yadav/next-swr-app">here</a>.</p><!--kg-card-begin: html--><a href="https://www.buymeacoffee.com/nandkishor.y" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="How to use SWR  in Next JS - client-side data-fetching technique" style="height: 60px !important;width: 217px !important;"></a><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Grant write permissions to IIS on AWS Elastic Beanstalk]]></title><description><![CDATA[This article explains how to provide ASP.NET Core applications write access to specific folders in IIS App Pool.]]></description><link>https://cloudcoders.xyz/blog/grant-write-permissions-to-iis-on-elastic-beanstalk-using-an-asp-net-core-app/</link><guid isPermaLink="false">62570d4ab477d30563fae83e</guid><category><![CDATA[aws]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Thu, 14 Apr 2022 11:24:02 GMT</pubDate><media:content url="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/grant-write-permission-iis-elastic-beanstalk.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: html--><!-- Ezoic - under_feature_image - under_page_title -->
<div id="ezoic-pub-ad-placeholder-137"> </div>
<!-- End Ezoic - under_feature_image - under_page_title --><!--kg-card-end: html--><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/grant-write-permission-iis-elastic-beanstalk.png" alt="Grant write permissions to IIS on AWS Elastic Beanstalk"><p>This article explains how to provide ASP.NET Core applications write access to specific folders in IIS App Pool. When using AWS Beanstalk, this is necessary for apps to operate properly.</p><h3 id="the-problem">The problem</h3><p>User Content and files are often written to the <code>wwwroot</code> or any other specific folder by ASP.NET Core apps. SQL Server Compact (.mdf), XML files, text files, and other similar files are examples of such files. As a result, when hosting an ASP.NET Core site, the AppPool in which the application or website runs must have <code>write</code> access to the folder where we want to write files.</p><p>When we host an ASP.NET Core application on AWS Elastic Beanstalk, we don&apos;t have direct access to the application&apos;s file system. However, AWS has config files that can be used to provide permission to certain directories.</p><p>The error looks something like this:</p><p><code>System.UnauthorizedAccessException: Access to the path &apos;C:\inetpub\AspNetCoreWebApps\app\xxx\xxx&apos; is denied</code></p><!--kg-card-begin: html--><!-- Ezoic - under_first_paragraph - under_first_paragraph -->
<div id="ezoic-pub-ad-placeholder-138"> </div>
<!-- End Ezoic - under_first_paragraph - under_first_paragraph --><!--kg-card-end: html--><h3 id="the-solution">The Solution</h3><ol><li>Create a top-level folder called <code>.ebextensions</code> in your Visual Studio project.</li><li>Create a configuration file called <code>&lt;ApplicationName&gt;.config</code> inside <code>.ebextensions</code> folder, where <code>&lt;ApplicationName&gt;</code> is the name of your AWS application hosted on Elastic Beanstalk.</li><li>YAML script or JSON can be used in the configuration file. AWS attempts to parse the file using the YAML parser first, and if that fails, it attempts to parse it using the JSON parser. If both parsing attempts fail, the deployment is canceled, and the error is shown in the Elastic Beanstalk application console log.</li><li>Add the following JSON code to the config file.</li></ol><pre><code class="language-json">{
  &quot;container_commands&quot;: {
    &quot;01&quot;: {
      &quot;command&quot;: &quot;icacls \&quot;C:/inetpub/AspNetCoreWebApps\&quot; /grant DefaultAppPool:(OI)(CI)F&quot;
    }
  }
}</code></pre><!--kg-card-begin: html--><!-- Ezoic - under_second_paragraph - under_second_paragraph -->
<div id="ezoic-pub-ad-placeholder-139"> </div>
<!-- End Ezoic - under_second_paragraph - under_second_paragraph --><!--kg-card-end: html--><p>The <code>container_commands</code> execute commands that affect your application source code. Container commands run after the application and web server have been set up and the application version archive has been extracted, but before the application version is deployed. Non-container commands and other customization operations are performed prior to the application source code being extracted.</p><p><em><strong>Container commands are run from the staging directory</strong></em>, where your source code is extracted prior to being deployed to the application server. Any changes you make to your source code in the staging directory with a container command will be included when the source is deployed to its final location.</p><p>That is why we have to use the <a href="https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/cc753525(v=ws.11)?redirectedfrom=MSDN">icacls </a>command pointing to <code>C:\inetpub\AspNetCoreWebApps</code> only because <code>C:\inetpub\AspNetCoreWebApps\app<strong>\xxx\xxx</strong></code> folder is not created at the time of executing this command as it runs in the staging directory.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_5 - incontent_5 -->
<div id="ezoic-pub-ad-placeholder-143"> </div>
<!-- End Ezoic - incontent_5 - incontent_5 --><!--kg-card-end: html--><p>Once <code>&quot;icacls &quot;C:/inetpub/AspNetCoreWebApps&quot; /grant DefaultAppPool:(OI)(CI)F&quot;</code> executes in <code>C:/inetpub/AspNetCoreWebApps</code> folder, the write permission will be granted to all the subfolders inside it.</p><p>This script will be executed and Full access will be given to the folder for DefaultAppPool when this project is published to AWS Elastic Beanstalk. If you&apos;re using a custom AppPool, replace DefaultAppPool with the custom AppPool name in the script.</p><p></p><!--kg-card-begin: html--><!-- Ezoic - bottom_of_page - bottom_of_page -->
<div id="ezoic-pub-ad-placeholder-148"> </div>
<!-- End Ezoic - bottom_of_page - bottom_of_page --><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Pub/Sub Design Pattern in .NET Distributed Cache]]></title><description><![CDATA[The publish-Subscribe pattern also known as Pub/Sub is an indispensable tool for building enterprise-grade .NET applications.]]></description><link>https://cloudcoders.xyz/blog/pub-sub-design-pattern-in-net-distributed-cache/</link><guid isPermaLink="false">622f0dc673e068c9dc11a737</guid><category><![CDATA[NCache]]></category><category><![CDATA[caching]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Mon, 14 Mar 2022 10:17:55 GMT</pubDate><media:content url="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/pub-sub-ncache.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: html--><!-- Ezoic - under_feature_image - under_page_title -->
<div id="ezoic-pub-ad-placeholder-137"> </div>
<!-- End Ezoic - under_feature_image - under_page_title --><!--kg-card-end: html--><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/pub-sub-ncache.png" alt="Pub/Sub Design Pattern in .NET Distributed Cache"><p>The publish-Subscribe pattern also known as Pub/Sub is an indispensable tool for building enterprise-grade .NET applications. Just to refresh your memory, <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/publish-subscribe-topics.html">Pub/Sub</a> is a messaging paradigm where the senders of messages (publisher) do not have any knowledge about the intended recipients (subscribers). Moreover, the publisher and subscriber applications do not interact with each other directly but instead depend on a common medium known as a <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/publish-subscribe-topics.html?tabs=net%2Cnet1%2Cnet2%2Cnet3%2Cnet4%2Cnet5">topic</a>. Hence, it&apos;s a loosely coupled messaging model.</p><!--kg-card-begin: html--><!-- Ezoic - under_first_paragraph - under_first_paragraph -->
<div id="ezoic-pub-ad-placeholder-138"> </div>
<!-- End Ezoic - under_first_paragraph - under_first_paragraph --><!--kg-card-end: html--><p>Now, assume that you have multiple applications of different roles deployed within the same architecture and they need a mechanism to inform/notify each other about certain events. These events could either be transient (due to changes made on the run time) or database events (due to changes in the database). That&apos;s exactly where the publish-subscribe design pattern will help you to enable distributed events.</p><!--kg-card-begin: html--><!-- Ezoic - under_second_paragraph - under_second_paragraph -->
<div id="ezoic-pub-ad-placeholder-139"> </div>
<!-- End Ezoic - under_second_paragraph - under_second_paragraph --><!--kg-card-end: html--><h2 id="enabling-distributed-events">Enabling Distributed Events</h2><p>To design a distributed event-driven architecture, developers traditionally turn towards using either of the following methods below.</p><p><strong>Data Notifications provided by RDBMS</strong></p><p>If the datastore is limited to a relational database, using the database notification feature seems to be the best available option. It allows you to register your interest with the database server and notifies your applications when there is any change in the database result set due to update, add, or delete.</p><p>However, RDBMS are intrinsically unscalable and easily become a <a href="https://www.alachisoft.com/blogs/fixing-four-asp-net-performance-bottlenecks/">performance bottleneck</a> in applications. You do not want to put an unnecessary load on your databases. Besides, the database notifications feature itself is inherently slow and doesn&apos;t support <a href="https://www.alachisoft.com/ncache/run-time-data-sharing.html">runtime data sharing</a> as well.</p><p>Now you may understand why using the database as a messaging medium cannot be the best design choice for your applications.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_5 - incontent_5 -->
<div id="ezoic-pub-ad-placeholder-143"> </div>
<!-- End Ezoic - incontent_5 - incontent_5 --><!--kg-card-end: html--><p><strong>Messaging Queues</strong></p><p>The other option you have is to introduce a separate messaging queue in your architecture. While these messaging queues do a great job in helping you transmit messages among applications, these queues are not data-focused i.e. they do not monitor data changes in the databases or any other source. Also, these messaging queues cannot scale alongside your application tier.</p><p><strong>Implement a Custom Solution</strong></p><p>The last option left for you is to build your messaging platform/medium to suit your need. While this empty sandbox is very tempting at first, allowing you to develop your stuff however you want, there is complexity in terms of time and resources required. Although possible, building and managing a robust and scalable messaging platform is a very daunting task.</p><p>Now, the question remains which solution is easy to incorporate, scalable, highly available, and also very reliable?</p><!--kg-card-begin: html--><!-- Ezoic - incontent_6 - incontent_6 -->
<div id="ezoic-pub-ad-placeholder-144"> </div>
<!-- End Ezoic - incontent_6 - incontent_6 --><!--kg-card-end: html--><h2 id="a-distributed-cache-as-a-messaging-platform">A Distributed Cache as a Messaging Platform</h2><p>Fret not, there is an easy solution. A more modern way to incorporate a robust messaging platform is to use an in-memory distributed cache. NCache is the only truly native .NET/.NET Core distributed cache available in the market. It is an in-memory distributed cache that is extremely fast and <a href="https://www.alachisoft.com/blogs/scalability-in-ncache-architecture-an-insight/">scalable</a>. It enables your applications to handle extreme transaction loads without your database becoming a bottleneck.</p><p>NCache is usually deployed in the middle tier of your n-tier architecture. Take a look at the following diagram for a better understanding.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/image.png" class="kg-image" alt="Pub/Sub Design Pattern in .NET Distributed Cache" loading="lazy" width="795" height="644"><figcaption>Figure1: NCache deployed in an N-Tier architecture</figcaption></figure><p>NCache is a cluster of cache servers serving tens of thousands of requests per second for your .NET applications as well as Java apps by keeping frequently used data in memory and helps avoid the majority of the database trips.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_7 - incontent_7 -->
<div id="ezoic-pub-ad-placeholder-145"> </div>
<!-- End Ezoic - incontent_7 - incontent_7 --><!--kg-card-end: html--><p>Let&#x2019;s first see how NCache is inherently suitable to act as a messaging bus with its event-driven architecture.</p><p><strong>NCache Event-Driven Messaging</strong></p><p>The following figure shows how NCache acts as a messaging bus for .NET and Java applications.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/NCache-as-a-Messaging-Platform.jpg" class="kg-image" alt="Pub/Sub Design Pattern in .NET Distributed Cache" loading="lazy" width="325" height="458"><figcaption>Figure2: NCache as a Messaging Platform</figcaption></figure><p>Here NCache enables cross-platform communication by employing fast <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/dynamic-compact-serialization.html">compact serialization</a>, which converts your .NET or Java objects to binaries and then transfers them over to the cache cluster. So, this is how NCache allows your .NET applications to interact with Java applications and vice versa. For more information, take a look at portable data types.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_8 - incontent_8 -->
<div id="ezoic-pub-ad-placeholder-146"> </div>
<!-- End Ezoic - incontent_8 - incontent_8 --><!--kg-card-end: html--><p>NCache manages Pub/Sub design patterns under the name of <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/event-notifications.html">Events</a> and provides you with different methods to propagate your messages to other listening applications. Let&#x2019;s take a look at both message types and see how a distributed cache can propagate them.</p><p>First, consider the data changes your applications need to listen to. Since NCache is also a .NET key-value store, it provides you with features to update your applications in case of any data changes within the cache. Because all of this is in-memory therefore there is no performance bottleneck. These updates could either be;</p><ul><li>Cache level item changes, be it update or remove.</li><li>Whole cache level data changes.</li><li><a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/continuous-query.html">Continuous Query</a>, where you register an SQL-like query to be watchful for if the result set changes within the cache. If it does your applications are notified.</li><li>Cluster changes, if any new node is added or removed, or crashed. (For administration).</li></ul><p>NCache also allows you to register <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/notification-based-dependencies.html">dependency on databases</a> including SQL, Oracle, and OleDb. This helps to keep your cache up to date with the database and thus your applications. For a full list of supported dependency types, check the database dependency. These dependencies are data change notifications registered with different data stores but you let NCache handle it. You can also combine database notifications with NCache data notifications to enrich your specific use case.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_9 - incontent_9 -->
<div id="ezoic-pub-ad-placeholder-147"> </div>
<!-- End Ezoic - incontent_9 - incontent_9 --><!--kg-card-end: html--><p>On the other hand, if you want to just propagate simple messages to complex .NET or Java objects then you should use the custom messaging feature. Here one application can produce the data and fire an event, whereas the interested listeners will receive the event almost instantaneously. For further information in this regard, you can see custom events.</p><p><strong>NCache Pub/Sub API</strong></p><p>NCache provides an in-memory Publisher/Subscriber (Pub/Sub) feature and a dedicated Pub/Sub Messaging store to enable real-time information sharing in .NET web applications. We will see how combining NCache and Pub/Sub can address the above challenges and eventually help your applications communicate better.</p><p>The Pub/Sub model naturally decouples publishers and subscribers by providing a channel where messages are published and subscribed by the interested users. Now when NCache acts as a messaging bus, the Pub/Sub model benefits from the underlying <a href="https://www.alachisoft.com/resources/videos/distributed-cache-architecture.html">NCache distributed architecture</a> and numerous handy <a href="https://www.alachisoft.com/ncache/ncache-enterprise.html">features</a>.</p><p><strong>Basic Architecture</strong></p><p>Without further ado, let&apos;s first get to know the basic <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/publish-subscribe-ncache.html">components of NCache Pub/Sub</a> and their working. The general flow of the NCache Pub/Sub messaging is like this - the <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/publish-message-to-topic.html">publisher publishes messages</a> on a topic using the <a href="https://www.alachisoft.com/resources/docs/ncache/dotnet-api-ref/Alachisoft.NCache.Runtime.Caching.ITopic.html">ITopic</a>interface. The subscribers <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/subscribe-topic-messages.html">create subscriptions</a> to one or many topics and receive relevant messages. On successful message delivery, NCache receives the acknowledgment. Otherwise, NCache keeps retrying before the message expires (if expiration is set). Undelivered messages reside in the cache until eviction or expiration are triggered and enabled.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/NCache-Pub-Sub-messaging.webp" class="kg-image" alt="Pub/Sub Design Pattern in .NET Distributed Cache" loading="lazy" width="695" height="391"><figcaption>Figure 3: NCache Pub/Sub messaging</figcaption></figure><p><strong>Subscription Types</strong></p><!--kg-card-begin: html--><!-- Ezoic - incontent_10 - incontent_10 -->
<div id="ezoic-pub-ad-placeholder-149"> </div>
<!-- End Ezoic - incontent_10 - incontent_10 --><!--kg-card-end: html--><p>NCache provides two different types of subscriptions namely, non-durable and durable subscriptions for pub/sun messaging. Furthermore, NCache enables exclusive and shared subscription policies. The relevant details are discussed below.</p><ul><li><strong><em>Non-Durable Subscription:</em></strong> By default, all subscriptions created on a topic are non-durable subscriptions. It conveys intended messages to the subscriber-only until it remains connected. In case the subscriber&#x2019;s connection is lost due to any reason, it doesn&#x2019;t receive old messages on rejoining the network. This type of subscription is exclusive, which means that one subscription belongs to one subscriber.</li><li><em><strong>Durable Subscription:</strong></em> It takes account of a message loss on subscriber disconnectivity. NCache retains the subscription of a subscriber on connection loss. Hence, a subscriber can receive the published messages of interest on reconnecting. A durable subscription offers two policies:</li></ul><ol><li>Exclusive: One subscription belongs to one active subscriber at a time.</li><li>Shared: One subscription can have more than one subscriber registered at a time and the load is shared.</li></ol><!--kg-card-begin: html--><!-- Ezoic - incontent_11 - incontent_11 -->
<div id="ezoic-pub-ad-placeholder-150"> </div>
<!-- End Ezoic - incontent_11 - incontent_11 --><!--kg-card-end: html--><h2 id="getting-started-with-ncahce-pubsub">Getting Started with NCahce Pub/Sub</h2><p>Let&#x2019;s assume that there is an e-commerce store where new products are added to the store on regular basis by different vendors. Meanwhile, sales and offers are also provided on the products. The store managers and customers interested in the offered products need to stay updated about new products, products on sale, and discounts. NCache Pub/Sub feature can enable distributed notification system in this scenario. For that, NCache dedicated Pub/Sub Messaging store can be created first.</p><p>Let&#x2019;s discuss the step-by-step process of achieving distributed messaging in the above scenario by using NCache Pub/Sub Messaging API.</p><p><strong>Create a Topic</strong></p><p>As a first step, a topic needs to be created where updates on new products can be published by different vendors. A new topic with a unique name can be created using the NCache ITopic interface. Here is how the publisher application uses the method CreateTopic to create a topic with the name <em><code>newProducts</code></em>.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_12 - incontent_12 -->
<div id="ezoic-pub-ad-placeholder-151"> </div>
<!-- End Ezoic - incontent_12 - incontent_12 --><!--kg-card-end: html--><pre><code class="language-csharp">// Pre-condition: Cache is already connected
// Specify the topic name
string topicName = &#x201C;newProducts&#x201D;

// Create topic
ITopic topic = cache.MessagingService.CreateTopic(topicName);</code></pre><p>In case a topic with the provided name already exists, an instance of the topic is returned as ITopic.</p><p>NCache allows to <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/publish-subscribe-topics.html?tabs=net%2Cnet1%2Cnet2%2Cnet3%2Cnet4%2Cnet5#topic-priority">set topic priority</a> while creating the topic. It is useful when certain events need to be communicated on a higher priority than others. For instance, the information about finished goods is urgent. Similarly, the update in product prices due to discount or sale can be most important being a seller/buyer. In that case, the topic priority can be set to high while creating it, and the relevant notifications can be received without any delay.</p><p><strong>Publish Messages</strong></p><!--kg-card-begin: html--><!-- Ezoic - incontent_13 - incontent_13 -->
<div id="ezoic-pub-ad-placeholder-152"> </div>
<!-- End Ezoic - incontent_13 - incontent_13 --><!--kg-card-end: html--><p>Once a topic is created, the publisher application can publish relevant messages to that topic using Publish method. For that, an instance of the topic is first obtained by specifying the topic name. NCache provides the following two delivery modes while publishing messages:</p><ul><li><strong>All (default):</strong> Delivers the message to all the registered subscribers. It is useful when the information needs to be broadcasted.</li><li><strong>Any:</strong> Delivers the message to any of the registered subscribers.</li></ul><p>Furthermore, to efficiently manage the storage space of your Pub/Sub cache, you can also set <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/publish-subscribe-messages.html">expirations for messages.</a></p><p>In the following code, messages about new products are broadcasted by a publisher on an already existing topic <em><code>newProducts</code>.</em></p><pre><code class="language-csharp">// Pre-condition: Cache is already connected
// Topic &#x201C;newProducts&#x201D; already created
string topicName = &#x201C;newProducts&#x201D;

// Get the topic
ITopic productTopic = cache.MessagingService.GetTopic(topicName);

// Create the object to be sent in message
Product product = FetchProductFromDB(10248);

// Create the new message with the object order
var productMessage = new Message(product);

// Publish the order with delivery option set as all
orderTopic.Publish(productMessage, DeliveryOption.All, true);</code></pre><p><strong>Subscribe for Topic Messages</strong></p><p>Once the topic is created, a subscriber application can receive the messages published to that topic by getting a subscription. Since different types of subscriptions are supported, a subscriber interested in a non-durable subscription can use the <code>CreateSubscription</code> method. For durable subscriptions, the <code>CreateDurableSubscription</code> method can be used.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_13 - incontent_13 -->
<div id="ezoic-pub-ad-placeholder-152"> </div>
<!-- End Ezoic - incontent_13 - incontent_13 --><!--kg-card-end: html--><p>The code below shows how a subscriber application can create a subscription for the topic <em><code>newProducts</code></em>. <code>MessageReceived</code> the callback is registered to perform any intended operation on being notified. For instance, a subscriber can update product prices in the <code>MessageReceived</code> callback on receiving a sale notification.</p><pre><code class="language-csharp">// Pre-condition: Cache is already connected
// Topic &#x201C;newProducts&#x201D; already created
string topicName = &#x201C;newProducts&#x201D;

// Get the topic
ITopic productTopic = cache.MessagingService.GetTopic(topicName);

// Create and register subscribers for topic newProducts
// MessageReceived callback is specified
ITopicSubscription orderSubscriber = orderTopic.CreateSubscription(MessageReceived);</code></pre><p>In the above example, a non-durable subscription is created. Besides, a subscriber can <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/subscribe-topic-messages.html?tabs=net%2Cnet1%2Cnet2%2Cnet3%2Cnet4%2Cnet5%2Cnet6">create a durable subscription</a> when there is a need to receive the old messages from subscribed topic/topics on reconnection.</p><p>NCache also provides a <a href="https://www.alachisoft.com/resources/docs/ncache/prog-guide/subscribe-topic-messages.html?tabs=net%2Cnet1%2Cnet2%2Cnet3%2Cnet4%2Cnet5%2Cnet6">pattern-based method of subscription</a> where NCache supports multiple wildcards to subscribe for single/multiple topics falling under the provided pattern.</p><p><strong>Register Notifications</strong></p><!--kg-card-begin: html--><!-- Ezoic - incontent_14 - incontent_14 -->
<div id="ezoic-pub-ad-placeholder-153"> </div>
<!-- End Ezoic - incontent_14 - incontent_14 --><!--kg-card-end: html--><p>NCache empowers the publishers to know the status of messages and the availability of topics. The following notifications can be registered by the publisher applications:</p><ul><li><strong>MessageDeliveryFailure:</strong> Notifies the publisher if a message has failed to deliver because of any issue.</li><li><strong>OnTopicDeleted:</strong> Notifies a publisher when a message gets deleted.</li></ul><p>Here is how simply the publisher can register for these two types of notifications.</p><pre><code class="language-csharp">// You have an instance productTopic of existing topic

// Register message delivery failure
productTopic.MessageDeliveryFailure += OnFailureMessageReceived;

//Register topic deletion notification
productTopic.OnTopicDeleted = TopicDeleted;</code></pre><p>By following the above steps a basic Pub/Sub Messaging architecture can be integrated into any ASP.NET/.NET Core application.</p><h2 id="conclusion">Conclusion</h2><p>To this point, you are familiar with the NCache Pub/Sub feature. Let&#x2019;s summarize what benefits Ncache Pub/Sub offers to handle the limitations of existing solutions.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_15 - incontent_15 -->
<div id="ezoic-pub-ad-placeholder-155"> </div>
<!-- End Ezoic - incontent_15 - incontent_15 --><!--kg-card-end: html--><ul><li>Due to the <a href="https://www.alachisoft.com/blogs/how-net-cache-improves-performance-and-scalability/">linear scalability</a>, NCache Pub/Sub can handle the increasing number of subscription requests by adding cache servers and performing load balancing on the go. The scaling up occurs transparently to the users without hindering the communication process. Hence, you can easily scale up your communication performance using NCache Pub/Sub.</li><li>NCache Pub/Sub facilitates durable subscriptions, message delivery retires and delivery failure notifications to avoid message loss. Moreover, the distributed and replicated architecture of NCache ensures the high availability of NCache that accommodates subscribers&apos; connectivity in dynamic environments. Altogether these features ensure reliable communication.</li><li>Since NCache is an in-memory distributed cache, the message store residing in the cache is inherently fast. In addition, NCache allows expiration and evictions on items residing in the cache to intelligently manage the storage space.</li></ul><p>The scalability, reliability, and storage efficiency of NCache together with loose coupling and async messaging mode of Pub/Sub make NCache Pub/Sub feature highly promising for distributed messaging in the future .NET/.NET Core applications.</p><!--kg-card-begin: html--><!-- Ezoic - bottom_of_page - bottom_of_page -->
<div id="ezoic-pub-ad-placeholder-148"> </div>
<!-- End Ezoic - bottom_of_page - bottom_of_page --><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Real-Time Data/Stream Processing with NCache]]></title><description><![CDATA[Real-time data/stream processing is attractive for data-driven applications with low latency requirements, such as network monitoring and real-time price analysis]]></description><link>https://cloudcoders.xyz/blog/real-time-data-stream-processing-with-distributed-caching/</link><guid isPermaLink="false">62287b9169dbfb43c51a39df</guid><category><![CDATA[NCache]]></category><category><![CDATA[caching]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Wed, 09 Mar 2022 11:58:45 GMT</pubDate><media:content url="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/real-time-datastream-processing-with-distributed-caching-ncache.png" medium="image"/><content:encoded><![CDATA[<img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/real-time-datastream-processing-with-distributed-caching-ncache.png" alt="Real-Time Data/Stream Processing with NCache"><p><strong>Key Takeaways</strong></p><ul><li>Real-time data/stream processing is attractive for data-driven applications with low latency requirements such as network monitoring and real-time price analysis applications.</li><li>An in-memory distributed is an ideal platform for the development of real-time stream processing applications due to extremely fast data access and linear scalability.</li><li>Modern distributed caching solutions facilitate real-time communication for .NET and .NET Core stream processing applications through Pub/Sub messaging, SQL and LINQ searching, events, and continuous query.</li><li>NCache is a .NET/.NET Core distributed cache that helps such applications to process fast and scale out with ease.</li></ul><h2 id="real-time-datastream-processing-with-distributed-caching">Real-Time Data/Stream Processing with Distributed Caching</h2><p>With technological advancement, data-driven applications with low latency requirements are emerging rapidly. Real-time stream processing applications in .NET/.NET Core are particularly attractive since they quickly process huge amounts of incoming data from various sources before it is stored in the database. This allows quick decision-making for businesses and in turn, reduces the response time for data events in an application.</p><h2 id="in-memory-storage-and-computing-the-de-facto-standard">In-memory storage and computing: the de facto standard</h2><p>Real-time stream processing is used for a wide range of business applications that deal with incoming data at high volume and require immediate analysis. For example, e-commerce, risk management, fraud detection, network monitoring, real-time price analysis applications, etc. The applications that work with data streams crave storage and processing to record large streams of data and perform computations. The legacy databases aren&#x2019;t fast enough to meet the real-time processing needs and easily become a performance bottleneck when it comes to scalability.</p><h2 id="distributed-caching-paradigm">Distributed caching paradigm</h2><p>Recently, distributed caching has emerged as a promising paradigm for in-memory storage and computing. A distributed cache is a system where random-access memory (RAM) of multiple networked computers is pooled into a single in-memory cache cluster for providing fast access to data. With the distributed architecture, a distributed cache can grow beyond the memory limits of a single physical server. Hence, the capacity and processing power are aggregated by avoiding any single point of failure.</p><p>Distributed caches are particularly useful in environments with high transaction data and load. The distributed architecture attributes scaling by adding more physical servers to the cluster and thus allows the cache to scale with an increase in data. The popular distributed caches used in the industry are <em>Eh-cache, Memcache, Redis, Riak, Hazelcast, and NCache.</em></p><h2 id="rethinking-stream-processing-with-distributed-caching">Rethinking stream processing with distributed caching</h2><!--kg-card-begin: markdown--><p>In-memory distributed caching is an ideal platform for real-time stream processing applications. With different streaming modes in a cache you can easily:</p>
<ul>
<li>Add or update cache data with streams in write mode.</li>
<li>Read data from a stream with or without locking.</li>
<li>Write data in parallel to read operations without locking.</li>
<li>Read data simultaneously for multiple clients with locking.</li>
</ul>
<!--kg-card-end: markdown--><p>Here, we discuss why and how distributed caching compliments real-time stream processing applications.</p><h2 id="distributed-caching-features-benefiting-stream-processing">Distributed caching features benefiting stream processing</h2><p>Let us see what specific features in a distributed cache assist real-time stream processing applications.</p><p><strong>Pub/Sub Messaging</strong></p><p>A typical stream processing app consists of various several producers including data ingestion, integration, and real-time analytics. The underlying responsibilities are handled by different modules which are usually codependent. &#xA0;Hence, these modules need to communicate with each other to collaborate. Pub/Sub messaging feature allows asynchronous microservice communication while maintaining decoupling. Therefore, it can enable real-time information sharing on a large scale for stream processing applications.</p><p>The performance of Pub/Sub messaging can be scaled when it is integrated with a distributed in-memory cache that acts as a messaging bus. The basic working of the Pub/Sub mechanism is something like this: A Topic is created inside the cache. A publisher publishes messages on this Topic. Client applications (also known as subscribers) make a subscription against this Topic to receive the messages published on it by the Publisher. The subscription made by the subscribers against a topic is of two types:</p><ul><li><em>Durable</em>: Subscribers can receive messages intended for them even after a period of disconnection. Meaning, the messages are maintained for them.</li><li><em>Non-Durable: </em>Subscribers receive messages from the topic as long as they are connected to the network. Once a subscriber leaves the network and then, later on, re-joins the network, it will not receive messages intended for it during that disconnection phase. Meaning, messages for a subscriber aren&#x2019;t maintained.</li></ul><p>Let&apos;s assume an e-commerce application, that processes thousands of customers each day for their online purchases. The customers can belong to different categories based on their purchases. To make the processing of customers efficient, the unfiltered customers are categorized and filtered as <em>Gold</em>, <em>Silver</em>, and <em>Bronze</em> customers based on the number of their orders. Using the Pub/Sub messaging feature of a cache, &#xA0;a Publisher can create a topic <em>Orders</em> and publish relevant updates to it. Meanwhile, a subscriber can subscribe to the topic for order information to further process the customers.</p><p><strong>Searching with SQL &amp; LINQ in Cache</strong></p><p>Stream processing applications handle the aggregation and filtering of huge datasets. Similar to a database, caches also offer a searching mechanism where you can fetch the cache keys/data using SQL-like query<strong> syntax</strong> while using a rich set of operators. Hence, you can bring SQL querying capabilities to your data streams.</p><p>LINQ or Language Integrated Query is a Microsoft .NET component that adds data querying features to .NET languages. Syntax-wise it&#x2019;s quite similar to SQL. LINQ can be integrated seamlessly into a cache via a <a href="https://docs.microsoft.com/en-us/dynamics365/fin-ops-core/dev-itpro/dev-tools/linq-provider-c">LINQ provider</a>. The LINQ provider facilitates the execution of LINQ queries over the distributed cache while improving the application&#x2019;s performance without changing the LINQ object model.</p><p><strong>Event Notifications</strong></p><p>The stream processing applications work on data in motion where actions need to be performed on the data flow as soon as possible. Meanwhile, the underlying events generated need to be handled efficiently since the real-time response is the fundamental requirement here. A distributed cache seamlessly enables real-time notifications through events. These notifications are sent asynchronously to the client so there is no overhead on the client&#x2019;s activities.</p><p>It allows the client applications to register events for cache activities of their interest. This facilitates run-time data sharing when a single cache is shared by separate applications or separate modules of the same application. Hence, the client applications can monitor the state of their data and perform actions accordingly. You have the flexibility to register for cache-level events, item-level events, and management-level events. Moreover, you can either get data or metadata along with the event by using event filters in a cache.</p><p>In cache level events, the registered clients can be notified of the addition, insertion, and removal of any cache item. On the other hand, item-level events can be registered for specific keys or chunk of keys. In that case, the cache is responsible for monitoring changes for the specified key/keys, and notifications are triggered when data against those keys are altered. As the name indicates, management level events can be registered for notifying when any management operation such as cache clear and cache stop are performed.</p><p><strong>Continuous Queries (CQ)</strong></p><p>A typical stream application consists of several producers generating new events and a set of consumers processing these events. In this regard, there is a need to monitor a <em>Window of time</em> for specific types of data additions and changes. Cache provides Continuous Query for runtime monitoring and sharing of data related to an observable data set. This allows applications to be notified of all changes that occur within the queried result set in the cache.</p><h2 id="scalable-distributed-stream-processing">Scalable distributed stream processing</h2><p>Designing scalable applications is crucial while working with streaming data. An in-memory distributed cache is extremely fast due to the storage mode and underlying architecture. And, it also provides linear scalability due to which it never becomes a bottleneck for your .NET / .NET Core Stream Processing application performance even under peak loads.</p><p>While handling incoming data from various sources and in varying formats, your system should be able to tolerate disruptions from a single point of failure. A distributed cache provides a self-healing peer-to-peer clustering architecture that has no single point of failure. Additionally, caches implement intelligent replication strategies with minimum replication cost so there is no data loss in case a cache server goes down.</p><p><a href="https://www.alachisoft.com/ncache/">NCache</a> is the only truly native .NET/.NET Core distributed cache available in the market. All others are developed in C++ on Linux and later ported to Windows with limited compatibility of .NET. NCache fits nicely into your .NET / .NET Core application stack and simplifies your cost of development and maintenance. Meanwhile, it provides different streaming modes, a dedicated Pub/Sub store, event notifications, cache searching with SQL queries, and LINQ. It&apos;s an ideal choice for your .NET/.NET Core stream processing applications.</p>]]></content:encoded></item><item><title><![CDATA[Create Protected Routes In NextJS and NextAuth]]></title><description><![CDATA[I'll show you exactly how to create protected routes in your NextJS application using NextAuth.]]></description><link>https://cloudcoders.xyz/blog/create-protected-routes-in-nextjs/</link><guid isPermaLink="false">61dcc56eb3be2971432fb711</guid><category><![CDATA[NextJs]]></category><category><![CDATA[NextAuth]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Mon, 06 Dec 2021 15:56:41 GMT</pubDate><media:content url="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/protected-routes-nextjs-nextauth.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: html--><!-- Ezoic - under_feature_image - under_page_title -->
<div id="ezoic-pub-ad-placeholder-137"> </div>
<!-- End Ezoic - under_feature_image - under_page_title --><!--kg-card-end: html--><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/protected-routes-nextjs-nextauth.png" alt="Create Protected Routes In NextJS and NextAuth"><p>Protecting Routes from unauthenticated users is a crucial part of any app.</p><p>In this article, I&apos;ll show you exactly how to create protected routes in your <a href="https://www.educative.io/courses/next-js-build-react-apps?aff=xvLn">NextJS </a>application using NextAuth.</p><p>I&apos;ll use a JWT token as an example, with the <code>accessToken</code> &#xA0;being saved in the session. Check <a href="https://cloudcoders.xyz/blog/nextauth-credentials-provider-with-external-api-and-login-page/">this article</a> for more information.</p><p>Check out this article which explains <a href="https://cloudcoders.xyz/blog/react-hooks-explained/">7 React Hooks</a> in detail. </p><!--kg-card-begin: html--><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5134801822845872" crossorigin="anonymous"></script>
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-5134801822845872" data-ad-slot="7673531100"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script><!--kg-card-end: html--><p>Because of the way <a href="https://www.educative.io/courses/next-js-build-react-apps?aff=xvLn">Next.js</a> handles <code>getServerSideProps</code> and <code>getInitialProps</code>, every protected page load must make a server-side request to determine whether the session is valid before generating the requested page (SSR). This increases server load, but there is an option if you are comfortable making requests from the client. You can use <code>useSession</code> to ensure that you always have a valid session. If no session is identified after the initial loading state, you can determine the appropriate action to take.</p><!--kg-card-begin: html--><!-- Ezoic - under_first_paragraph - under_first_paragraph -->
<div id="ezoic-pub-ad-placeholder-138"> </div>
<!-- End Ezoic - under_first_paragraph - under_first_paragraph --><!--kg-card-end: html--><p>First, let&apos;s modify our <code>_app.js</code> file.</p><pre><code class="language-javascript">import { SessionProvider, useSession, signIn } from &apos;next-auth/react&apos;;
export default function App({
  Component,
  pageProps: { session, ...pageProps },
}) {
  return (
    &lt;SessionProvider session={session}&gt;
      {Component.auth ? (
        &lt;Auth&gt;
          &lt;Component {...pageProps} /&gt;
        &lt;/Auth&gt;
      ) : (
        &lt;Component {...pageProps} /&gt;
      )}
    &lt;/SessionProvider&gt;
  )
}

function Auth({ children }) {
  const { data: session, status } = useSession()
  const isUser = !!session?.user
  React.useEffect(() =&gt; {
    if (status === &quot;loading&quot;) return
    if (!isUser) signIn()
  }, [isUser, status])

  if (isUser) {
    return children
  }

  // Session is being fetched, or no user.
  // If no user, useEffect() will redirect.
  return &lt;div&gt;Loading...&lt;/div&gt;
}</code></pre><p>Line #23: Do nothing while in the loading state.</p><p>Line #24: If the user is not authenticated, force the user to the login page.</p><!--kg-card-begin: html--><!-- Ezoic - under_second_paragraph - under_second_paragraph -->
<div id="ezoic-pub-ad-placeholder-139"> </div>
<!-- End Ezoic - under_second_paragraph - under_second_paragraph --><!--kg-card-end: html--><h2 id="custom-client-session-handling">Custom Client Session Handling</h2><!--kg-card-begin: html--><span id="ezoic-pub-video-placeholder-6"></span><!--kg-card-end: html--><p>Because of how <a href="https://www.educative.io/courses/next-js-build-react-apps?aff=xvLn">Next.js</a> handles <code>getServerSideProps</code> / <code>getInitialProps</code>, every protected page load must make a server-side request to determine whether the session is valid and then build the requested page. This alternate technique enables for the display of a loading status on the initial check, and all subsequent page transitions will be client-side, eliminating the need to check with the server and regenerate pages.</p><p>Consider the &quot;/dashboard&quot; page. Only authorized users should be able to view this page.</p><!--kg-card-begin: html--><!-- Ezoic - mid_content - mid_content -->
<div id="ezoic-pub-ad-placeholder-154"> </div>
<!-- End Ezoic - mid_content - mid_content --><!--kg-card-end: html--><pre><code class="language-javascript">export default function Dashboard() {
  const { data: session } = useSession()
  return &quot;Some super secret dashboard&quot;
}

Dashboard.auth = true</code></pre><!--kg-card-begin: html--><!-- Ezoic - incontent_6 - incontent_6 -->
<div id="ezoic-pub-ad-placeholder-144"> </div>
<!-- End Ezoic - incontent_6 - incontent_6 --><!--kg-card-end: html--><p>The session is always non-null inside this page, all the way down the React tree.</p><p>Notice that we are using <code>Dashboard.auth = true</code> to check if the user is authenticated, if not redirect to the login page.</p><p>We need to add <code>auth = true</code> to every page that we want to protect from unauthenticated users. </p><p>It is simple to extend/modify to support something similar to an options object for role-based authentication on pages. As an example:</p><!--kg-card-begin: html--><!-- Ezoic - incontent_5 - incontent_5 -->
<div id="ezoic-pub-ad-placeholder-143"> </div>
<!-- End Ezoic - incontent_5 - incontent_5 --><!--kg-card-end: html--><pre><code class="language-javascript">Dashboard.auth = {
  role: &quot;admin&quot;,
  loading: &lt;LoadingSkeleton /&gt;,
  unauthorized: &quot;/login-with-different-user&quot;, // redirect to this url
}</code></pre><p>I hope this post helps.</p><!--kg-card-begin: html--><!-- Ezoic - bottom_of_page - bottom_of_page -->
<div id="ezoic-pub-ad-placeholder-148"> </div>
<!-- End Ezoic - bottom_of_page - bottom_of_page --><!--kg-card-end: html--><p></p><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[How to implement NextAuth credentials provider with external API and login page]]></title><description><![CDATA[In this post, we'll learn how to use NextAuth credentials provider with a custom backend and a custom login page.]]></description><link>https://cloudcoders.xyz/blog/nextauth-credentials-provider-with-external-api-and-login-page/</link><guid isPermaLink="false">61dcc56eb3be2971432fb710</guid><category><![CDATA[NextAuth]]></category><category><![CDATA[NextJs]]></category><category><![CDATA[authentication]]></category><category><![CDATA[credentailslogin]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Mon, 06 Dec 2021 09:32:26 GMT</pubDate><media:content url="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/nextauth-credentials-provider.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: html--><!-- Ezoic - under_feature_image - under_page_title -->
<div id="ezoic-pub-ad-placeholder-137"> </div>
<!-- End Ezoic - under_feature_image - under_page_title --><!--kg-card-end: html--><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/nextauth-credentials-provider.png" alt="How to implement NextAuth credentials provider with external API and login page"><p>When it comes to adding authentication to your next.js project, NextAuth is a wonderful option. It&apos;s easy to see why, given its extensive provider support, which includes Apple, GitHub, Azure Active Directory, Azure Active Directory B2C, Google, and more. It can help you set up your authentication in minutes!</p><!--kg-card-begin: html--><!-- Ezoic - under_first_paragraph - under_first_paragraph -->
<div id="ezoic-pub-ad-placeholder-138"> </div>
<!-- End Ezoic - under_first_paragraph - under_first_paragraph --><!--kg-card-end: html--><p>However, for different reasons, you may need to implement your custom backend or external API with an email/password login. That&apos;s where the credentials provider associated with your API server comes in handy. I was in the same situation and couldn&apos;t find a clear description with examples, so I had to pull together the details myself (especially handling errors from the custom backend and handling them on your custom login page). If you&apos;re in a similar boat, I hope this helps!</p><!--kg-card-begin: html--><!-- Ezoic - under_second_paragraph - under_second_paragraph -->
<div id="ezoic-pub-ad-placeholder-139"> </div>
<!-- End Ezoic - under_second_paragraph - under_second_paragraph --><!--kg-card-end: html--><h2 id="starting-your-project">Starting your Project</h2><p>Open a command prompt or terminal window in the location where you wish to save your project and run the following command.</p><pre><code class="language-bash">npx create-next-app -e with-tailwindcss my-project</code></pre><p>This creates a new project in the my-project directory. I have also included Tailwind CSS. You should see something like this in the my-project directory.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/image-1.webp" class="kg-image" alt="How to implement NextAuth credentials provider with external API and login page" loading="lazy" width="483" height="577"><figcaption>File structure after running the create-next-app command</figcaption></figure><!--kg-card-begin: html--><!-- Ezoic - incontent_5 - incontent_5 -->
<div id="ezoic-pub-ad-placeholder-143"> </div>
<!-- End Ezoic - incontent_5 - incontent_5 --><!--kg-card-end: html--><p>After that, change the directory to my-projects and type <em><strong>yarn dev</strong></em> from your terminal to start the next development server. You can now go to http://localhost:3000 and see the following.</p><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/image-2.webp" class="kg-image" alt="How to implement NextAuth credentials provider with external API and login page" loading="lazy" width="1198" height="828"></figure><!--kg-card-begin: html--><!-- Ezoic - incontent_6 - incontent_6 -->
<div id="ezoic-pub-ad-placeholder-144"> </div>
<!-- End Ezoic - incontent_6 - incontent_6 --><!--kg-card-end: html--><h2 id="setting-up-the-api">Setting up the API</h2><!--kg-card-begin: html--><span id="ezoic-pub-video-placeholder-6"></span><!--kg-card-end: html--><p>Now let&apos;s add the NextAuth package by running the following command.</p><pre><code class="language-bash">yarn add next-auth@beta</code></pre><p>In our .env file, we need to create a NEXTAUTH URL. Add the following to your .env file.</p><pre><code class="language-bash">NEXTAUTH_URL=http://localhost:3000
</code></pre><p>Now, create a file called <code>[...nextauth].js</code> in <code>pages/api/auth</code> to include NextAuth.js in your project. This contains the NextAuth.js dynamic route handler, as well as all of your global NextAuth.js configuration.</p><p>We need to add the following to the <code>[...nextauth].js</code>, each section will be described later.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_7 - incontent_7 -->
<div id="ezoic-pub-ad-placeholder-145"> </div>
<!-- End Ezoic - incontent_7 - incontent_7 --><!--kg-card-end: html--><pre><code class="language-javascript">import NextAuth from &apos;next-auth&apos;;
import CredentialsProvider from &apos;next-auth/providers/credentials&apos;;

export default NextAuth({
  providers: [
    CredentialsProvider({
      // The name to display on the sign in form (e.g. &apos;Sign in with...&apos;)
      name: &apos;my-project&apos;,
      // The credentials is used to generate a suitable form on the sign in page.
      // You can specify whatever fields you are expecting to be submitted.
      // e.g. domain, username, password, 2FA token, etc.
      // You can pass any HTML attribute to the &lt;input&gt; tag through the object.
      credentials: {
        email: {
          label: &apos;email&apos;,
          type: &apos;email&apos;,
          placeholder: &apos;jsmith@example.com&apos;,
        },
        password: { label: &apos;Password&apos;, type: &apos;password&apos; }
      },
      async authorize(credentials, req) {
        const payload = {
          email: credentials.email,
          password: credentials.password,
        };

        const res = await fetch(&apos;https://cloudcoders.azurewebsites.net/api/tokens&apos;, {
          method: &apos;POST&apos;,
          body: JSON.stringify(payload),
          headers: {
            &apos;Content-Type&apos;: &apos;application/json&apos;,
          },
        });

        const user = await res.json();
        if (!res.ok) {
          throw new Error(user.message);
        }
        // If no error and we have user data, return it
        if (res.ok &amp;&amp; user) {
          return user;
        }

        // Return null if user data could not be retrieved
        return null;
      },
    }),
    // ...add more providers here
  ],
  secret: process.env.JWT_SECRET,
  pages: {
    signIn: &apos;/login&apos;,
  },
  callbacks: {
    async jwt({ token, user, account }) {
      if (account &amp;&amp; user) {
        return {
          ...token,
          accessToken: user.token,
          refreshToken: user.refreshToken,
        };
      }

      return token;
    },

    async session({ session, token }) {
      session.user.accessToken = token.accessToken;
      session.user.refreshToken = token.refreshToken;
      session.user.accessTokenExpires = token.accessTokenExpires;

      return session;
    },
  },
  theme: {
    colorScheme: &apos;auto&apos;, // &quot;auto&quot; | &quot;dark&quot; | &quot;light&quot;
    brandColor: &apos;&apos;, // Hex color code #33FF5D
    logo: &apos;/logo.png&apos;, // Absolute URL to image
  },
  // Enable debug messages in the console if you are having problems
  debug: process.env.NODE_ENV === &apos;development&apos;,
});
</code></pre><!--kg-card-begin: html--><!-- Ezoic - longest_content - longest_content -->
<div id="ezoic-pub-ad-placeholder-142"> </div>
<!-- End Ezoic - longest_content - longest_content --><!--kg-card-end: html--><p>All requests to <code>/api/auth/*</code> (<code>signIn</code>, callback, <code>signOut</code>etc.) will automatically be handled by NextAuth.js.</p><p>The first section is the providers section:</p><pre><code class="language-javascript">providers: [
    CredentialsProvider({
      id: &apos;credentials&apos;,
      name: &apos;my-project&apos;,
      credentials: {
        email: {
          label: &apos;email&apos;,
          type: &apos;email&apos;,
          placeholder: &apos;jsmith@example.com&apos;,
        },
        password: { label: &apos;Password&apos;, type: &apos;password&apos; }
      },
      async authorize(credentials, req) {
        const payload = {
          email: credentials.email,
          password: credentials.password,
        };

        const res = await fetch(&apos;https://cloudcoders.azurewebsites.net/api/tokens&apos;, {
          method: &apos;POST&apos;,
          body: JSON.stringify(payload),
          headers: {
            &apos;Content-Type&apos;: &apos;application/json&apos;,
          },
        });

        const user = await res.json();
        if (!res.ok) {
          throw new Error(user.message);
        }
        // If no error and we have user data, return it
        if (res.ok &amp;&amp; user) {
          return user;
        }

        // Return null if user data could not be retrieved
        return null;
      },
    }),
    // ...add more providers here
  ],</code></pre><!--kg-card-begin: html--><!-- Ezoic - mid_content - mid_content -->
<div id="ezoic-pub-ad-placeholder-154"> </div>
<!-- End Ezoic - mid_content - mid_content --><!--kg-card-end: html--><p>This returns an array of providers; we only have one in our example, which is the credentials provider, but you may add others like GitHub, Google, or Apple.</p><p>When we execute the signin method from the frontend, the id is utilized to trigger the provider that we require, in this case, the credentials.</p><p>Next, we have an async authorize method. This method takes a parameter called credentials. Credentials will hold the user, password, and any other payloads required by the custom backend API that you will send from the frontend with the sign-in information.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_7 - incontent_7 -->
<div id="ezoic-pub-ad-placeholder-145"> </div>
<!-- End Ezoic - incontent_7 - incontent_7 --><!--kg-card-end: html--><p>The next section is secret and custom pages.</p><pre><code class="language-javascript">  secret: process.env.JWT_SECRET,
  pages: {
    signIn: &apos;/login&apos;,
  },</code></pre><p></p><p>A secret to using for a key generation - you should set this explicitly. This is used to generate the actual signing key and produces a warning message if not defined explicitly.</p><p>If you wish to create custom sign-in, sign-out, or error pages, you can utilize pages to provide URLs. I have put the custom login page at &#xA0;<code>pages/login.js</code>.</p><p>Next up we have a series of callbacks. Note that the callbacks will accept a variety of parameters, but not all of them are required for the provider we&apos;re using, and some information may vary depending on the provider - the information below is only applicable for the <code>credentials</code> provider.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_8 - incontent_8 -->
<div id="ezoic-pub-ad-placeholder-146"> </div>
<!-- End Ezoic - incontent_8 - incontent_8 --><!--kg-card-end: html--><pre><code class="language-javascript">callbacks: {
    async jwt({ token, user, account }) {
      if (account &amp;&amp; user) {
        return {
          ...token,
          accessToken: user.token,
          refreshToken: user.refreshToken,
        };
      }

      return token;
    },

    async session({ session, token }) {
      session.user.accessToken = token.accessToken;
        
      return session;
    },
  },</code></pre><!--kg-card-begin: html--><!-- Ezoic - incontent_9 - incontent_9 -->
<div id="ezoic-pub-ad-placeholder-147"> </div>
<!-- End Ezoic - incontent_9 - incontent_9 --><!--kg-card-end: html--><p>The JWT callback is called first, which sets up the data for the session.</p><p>The signing method returns the user parameter which contains the user model, but only on the first call, i.e. when the user first signs in, so here, add the user key to the token and set it to be the value of the user model, otherwise it just returns the token.</p><p>The session callback sets this in the session with the user key.</p><h2 id="using-the-nextauth-api-in-the-frontend">Using the NextAuth API in the frontend</h2><!--kg-card-begin: html--><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-5134801822845872" crossorigin="anonymous"></script>
<ins class="adsbygoogle" style="display:block; text-align:center;" data-ad-layout="in-article" data-ad-format="fluid" data-ad-client="ca-pub-5134801822845872" data-ad-slot="7673531100"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script><!--kg-card-end: html--><p>The custom <code>login.js</code> page should look like this. I am also using <a href="https://formik.org/">Formik</a> and <a href="https://github.com/jquense/yup">Yup</a> for client-side validation. </p><pre><code class="language-javascript">import { useState } from &apos;react&apos;;
import { signIn, getCsrfToken } from &apos;next-auth/react&apos;;
import { Formik, Field, ErrorMessage } from &apos;formik&apos;;
import * as Yup from &apos;yup&apos;;
import { useRouter } from &apos;next/router&apos;;

export default function SignIn({ csrfToken }) {
  const router = useRouter();
  const [error, setError] = useState(null);

  return (
    &lt;&gt;
      &lt;Formik
        initialValues={{ email: &apos;&apos;, password: &apos;&apos;, tenantKey: &apos;&apos; }}
        validationSchema={Yup.object({
          email: Yup.string()
            .max(30, &apos;Must be 30 characters or less&apos;)
            .email(&apos;Invalid email address&apos;)
            .required(&apos;Please enter your email&apos;),
          password: Yup.string().required(&apos;Please enter your password&apos;),
         })}
        onSubmit={async (values, { setSubmitting }) =&gt; {
          const res = await signIn(&apos;credentials&apos;, {
            redirect: false,
            email: values.email,
            password: values.password,
            callbackUrl: `${window.location.origin}`,
          });
          if (res?.error) {
            setError(res.error);
          } else {
            setError(null);
          }
          if (res.url) router.push(res.url);
          setSubmitting(false);
        }}
      &gt;
        {(formik) =&gt; (
          &lt;form onSubmit={formik.handleSubmit}&gt;
            &lt;div 
            className=&quot;bg-red-400 flex flex-col items-center 
            justify-center min-h-screen py-2 shadow-lg&quot;&gt;
              &lt;div className=&quot;bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4&quot;&gt;
                &lt;input
                  name=&quot;csrfToken&quot;
                  type=&quot;hidden&quot;
                  defaultValue={csrfToken}
                /&gt;

                &lt;div className=&quot;text-red-400 text-md text-center rounded p-2&quot;&gt;
                  {error}
                &lt;/div&gt;
                &lt;div className=&quot;mb-4&quot;&gt;
                  &lt;label
                    htmlFor=&quot;email&quot;
                    className=&quot;uppercase text-sm text-gray-600 font-bold&quot;
                  &gt;
                    Email
                    &lt;Field
                      name=&quot;email&quot;
                      aria-label=&quot;enter your email&quot;
                      aria-required=&quot;true&quot;
                      type=&quot;text&quot;
                      className=&quot;w-full bg-gray-300 text-gray-900 mt-2 p-3&quot;
                    /&gt;
                  &lt;/label&gt;

                  &lt;div className=&quot;text-red-600 text-sm&quot;&gt;
                    &lt;ErrorMessage name=&quot;email&quot; /&gt;
                  &lt;/div&gt;
                &lt;/div&gt;
                &lt;div className=&quot;mb-6&quot;&gt;
                  &lt;label
                    htmlFor=&quot;password&quot;
                    className=&quot;uppercase text-sm text-gray-600 font-bold&quot;
                  &gt;
                    password
                    &lt;Field
                      name=&quot;password&quot;
                      aria-label=&quot;enter your password&quot;
                      aria-required=&quot;true&quot;
                      type=&quot;password&quot;
                      className=&quot;w-full bg-gray-300 text-gray-900 mt-2 p-3&quot;
                    /&gt;
                  &lt;/label&gt;

                  &lt;div className=&quot;text-red-600 text-sm&quot;&gt;
                    &lt;ErrorMessage name=&quot;password&quot; /&gt;
                  &lt;/div&gt;
                &lt;/div&gt;
                &lt;div className=&quot;flex items-center justify-center&quot;&gt;
                  &lt;button
                    type=&quot;submit&quot;
                    className=&quot;bg-green-400 text-gray-100 p-3 rounded-lg w-full&quot;
                  &gt;
                    {formik.isSubmitting ? &apos;Please wait...&apos; : &apos;Sign In&apos;}
                  &lt;/button&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;
          &lt;/form&gt;
        )}
      &lt;/Formik&gt;
    &lt;/&gt;
  );
}

// This is the recommended way for Next.js 9.3 or newer
export async function getServerSideProps(context) {
  return {
    props: {
      csrfToken: await getCsrfToken(context),
    },
  };
}</code></pre><!--kg-card-begin: html--><!-- Ezoic - longest_content - longest_content -->
<div id="ezoic-pub-ad-placeholder-142"> </div>
<!-- End Ezoic - longest_content - longest_content --><!--kg-card-end: html--><p>Line #26 - 31: This uses the credentials provider to call the sign-in function and passes the email and password we need to authenticate against. You can also set the callback Url where you want to redirect after a successful login. </p><p>You should be able to log in at this stage if you&apos;ve entered the correct credentials and your API endpoint is working as expected.</p><p>We can also display the error message on our custom login page in any way we want with this configuration. For example, I&apos;m displaying the following server error message:</p><!--kg-card-begin: html--><!-- Ezoic - incontent_10 - incontent_10 -->
<div id="ezoic-pub-ad-placeholder-149"> </div>
<!-- End Ezoic - incontent_10 - incontent_10 --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/next-auth-credentials-provider-custom-login-page.png" class="kg-image" alt="How to implement NextAuth credentials provider with external API and login page" loading="lazy" width="360" height="362"></figure><p>The easiest way to check if someone is logged in is to use <code>useSession()</code> React Hook. Make sure that <code>&lt;SessionProvider&gt;</code> is added to <code>pages/_app.js</code>.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_11 - incontent_11 -->
<div id="ezoic-pub-ad-placeholder-150"> </div>
<!-- End Ezoic - incontent_11 - incontent_11 --><!--kg-card-end: html--><pre><code class="language-javascript">import { useSession, signIn, signOut } from &quot;next-auth/react&quot;

export default function Component() {
  const { data: session } = useSession()
  if(session) {
    return &lt;&gt;
      Signed in as {session.user.email} &lt;br/&gt;
      &lt;button onClick={() =&gt; signOut()}&gt;Sign out&lt;/button&gt;
    &lt;/&gt;
  }
  return &lt;&gt;
    Not signed in &lt;br/&gt;
    &lt;button onClick={() =&gt; signIn()}&gt;Sign in&lt;/button&gt;
  &lt;/&gt;
}</code></pre><!--kg-card-begin: html--><!-- Ezoic - incontent_12 - incontent_12 -->
<div id="ezoic-pub-ad-placeholder-151"> </div>
<!-- End Ezoic - incontent_12 - incontent_12 --><!--kg-card-end: html--><p>The source code used in this article is <a href="https://github.com/nandkishor-yadav/nextauth-credentials-provider">here</a>.</p><p>Read about how to create <a href="https://cloudcoders.xyz/blog/create-protected-routes-in-nextjs/">protected routes</a> in NextJs.</p><p>I hope this post helps, I&apos;ve only recently started looking into NextJS and NEXTAuth so if you spot any issues or areas where it can be improved then let me know in the comments and if you like the contents then please share this article.</p><!--kg-card-begin: html--><!-- Ezoic - bottom_of_page - bottom_of_page -->
<div id="ezoic-pub-ad-placeholder-148"> </div>
<!-- End Ezoic - bottom_of_page - bottom_of_page --><!--kg-card-end: html--><!--kg-card-begin: html--><a href="https://www.buymeacoffee.com/nandkishor.y" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-green.png" alt="How to implement NextAuth credentials provider with external API and login page" style="height: 60px !important;width: 217px !important;"></a><!--kg-card-end: html-->]]></content:encoded></item><item><title><![CDATA[Localization with JSON files in .NET 6]]></title><description><![CDATA[We'll learn how to use JSON-based localization in.NET 6 and how to combine it with caching to make it even more efficient.]]></description><link>https://cloudcoders.xyz/blog/localization-with-json-files-in-net6/</link><guid isPermaLink="false">61dcc56eb3be2971432fb70e</guid><category><![CDATA[.net 6]]></category><category><![CDATA[Localization]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Tue, 30 Nov 2021 15:30:26 GMT</pubDate><media:content url="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/JSON-Based-Localization-in-NET-6.jpg" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: html--><!-- Ezoic - under_feature_image - under_page_title -->
<div id="ezoic-pub-ad-placeholder-137"> </div>
<!-- End Ezoic - under_feature_image - under_page_title --><!--kg-card-end: html--><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/JSON-Based-Localization-in-NET-6.jpg" alt="Localization with JSON files in .NET 6"><p>We&apos;ll learn how to use JSON-based localization in.NET 6 and how to combine it with caching to make it even more efficient. We&apos;ll save the localized strings in JSON files and utilize middleware to swap languages using language keys in the request header.</p><p>The source code can be found <a href="https://github.com/nandkishor-yadav/dotnet-6-json-localization">here</a></p><!--kg-card-begin: html--><!-- Ezoic - under_first_paragraph - under_first_paragraph -->
<div id="ezoic-pub-ad-placeholder-138"> </div>
<!-- End Ezoic - under_first_paragraph - under_first_paragraph --><!--kg-card-end: html--><h2 id="what-well-build">What we&apos;ll Build?</h2><p>We&apos;ll create a .NET 6 Web API that provides messages based on the Accepted Language in the request header. We&apos;ll use IDistributedCache to cache the string. The main purpose of this approach is to read language strings from a JSON file instead of a RESX file. We&apos;ll do this by adding a new IStringLocalizer implementation. This will be straightforward, but it will be extremely useful. Who doesn&apos;t want to work with JSON files?</p><p>It&apos;ll just need three new classes and a few service registrations. Let&apos;s get this started!</p><!--kg-card-begin: html--><!-- Ezoic - under_second_paragraph - under_second_paragraph -->
<div id="ezoic-pub-ad-placeholder-139"> </div>
<!-- End Ezoic - under_second_paragraph - under_second_paragraph --><!--kg-card-end: html--><h2 id="getting-started-with-json-based-localization-in-net-6">Getting started with JSON based localization in .NET 6</h2><p>Create a new ASP.NET Core Web API project in your favorite IDE (I use Visual Studio 2022 Community). Make sure you&apos;re using the .NET 6.0 Framework.</p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/JSON-Based-Localization-in-.NET-6.webp" class="kg-image" alt="Localization with JSON files in .NET 6" loading="lazy" width="1014" height="671"></figure><!--kg-card-begin: html--><!-- Ezoic - incontent_5 - incontent_5 -->
<div id="ezoic-pub-ad-placeholder-143"> </div>
<!-- End Ezoic - incontent_5 - incontent_5 --><!--kg-card-end: html--><p>I&apos;m not going to include any other class files in this implementation because I want it to be as basic as possible. To clear up the project, I deleted the weather controllers and related files from the WebAPI solution.</p><p>There are two aspects to this implementation:</p><ul><li>A Middleware that can determine the language code passed in at the request header by the client (which will be a postman in our case).</li><li>An implementation of the IStringLocalizer to support JSON files. I intend to store the JSON file by the locale name (en-US.json) under a Resources folder. Note that we will also use IDistributedCache to make our system more efficient.</li></ul><p>Let&#x2019;s create a new class and name it JsonStringLocalizer.cs</p><!--kg-card-begin: html--><!-- Ezoic - incontent_6 - incontent_6 -->
<div id="ezoic-pub-ad-placeholder-144"> </div>
<!-- End Ezoic - incontent_6 - incontent_6 --><!--kg-card-end: html--><pre><code class="language-csharp">    public class JsonStringLocalizer : IStringLocalizer
    {
        private readonly IDistributedCache _cache;
        private readonly JsonSerializer _serializer = new();

        public JsonStringLocalizer(IDistributedCache cache)
        {
            _cache = cache;
        }

        public LocalizedString this[string name]
        {
            get
            {
                var value = GetString(name);
                return new LocalizedString(name, value ?? name, value == null);
            }
        }

        public LocalizedString this[string name, params object[] arguments]
        {
            get
            {
                var actualValue = this[name];
                return !actualValue.ResourceNotFound
                    ? new LocalizedString(name, string.Format(actualValue.Value, arguments), false)
                    : actualValue;
            }
        }

        public IEnumerable&lt;LocalizedString&gt; GetAllStrings(bool includeParentCultures)
        {
            var filePath = $&quot;Resources/{Thread.CurrentThread.CurrentCulture.Name}.json&quot;;
            using var str = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            using var sReader = new StreamReader(str);
            using var reader = new JsonTextReader(sReader);
            while (reader.Read())
            {
                if (reader.TokenType != JsonToken.PropertyName)
                    continue;
                string? key = reader.Value as string;
                reader.Read();
                var value = _serializer.Deserialize&lt;string&gt;(reader);
                yield return new LocalizedString(key, value, false);
            }
        }
        private string? GetString(string key)
        {
            string? relativeFilePath = $&quot;Resources/{Thread.CurrentThread.CurrentCulture.Name}.json&quot;;
            var fullFilePath = Path.GetFullPath(relativeFilePath);
            if (File.Exists(fullFilePath))
            {
                var cacheKey = $&quot;locale_{Thread.CurrentThread.CurrentCulture.Name}_{key}&quot;;
                var cacheValue = _cache.GetString(cacheKey);
                if (!string.IsNullOrEmpty(cacheValue))
                {
                    return cacheValue;
                }

                var result = GetValueFromJSON(key, Path.GetFullPath(relativeFilePath));

                if (!string.IsNullOrEmpty(result))
                {
                    _cache.SetString(cacheKey, result);

                }
                return result;
            }
            return default;
        }
        private string? GetValueFromJSON(string propertyName, string filePath)
        {
            if (propertyName == null) {
                return default;
            }
            if (filePath == null) {
                return default;
            }
            using var str = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
            using var sReader = new StreamReader(str);
            using var reader = new JsonTextReader(sReader);
            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.PropertyName &amp;&amp; reader.Value as string == propertyName)
                {
                    reader.Read();
                    return _serializer.Deserialize&lt;string&gt;(reader);
                }
            }
            return default;
        }
    }</code></pre><!--kg-card-begin: html--><!-- Ezoic - longest_content - longest_content -->
<div id="ezoic-pub-ad-placeholder-142"> </div>
<!-- End Ezoic - longest_content - longest_content --><!--kg-card-end: html--><p>Line #3: We use IDistributedCache here.</p><p>Line #31 - 46: With GetAllStrings(), we try to read the JSON file name according to CurrentCulture and return a list of LocalizedString objects. The key and values of all the entries in the retrieved JSON file would be included in this list. Deserialization is performed on each of the read JSON values.</p><!--kg-card-begin: html--><!-- Ezoic - mid_content - mid_content -->
<div id="ezoic-pub-ad-placeholder-154"> </div>
<!-- End Ezoic - mid_content - mid_content --><!--kg-card-end: html--><p>Line #47 - 70: String localization is handled by the GetString() method. In this case, the file path is also determined by the request&apos;s current culture. If the file exists, a cache key with a unique name is generated. The system would look in cache memory to determine if the matched key contains any value. If a value is discovered in the cache, it is returned. Otherwise, the app opens the JSON file and tries to get and return the string it finds.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_7 - incontent_7 -->
<div id="ezoic-pub-ad-placeholder-145"> </div>
<!-- End Ezoic - incontent_7 - incontent_7 --><!--kg-card-end: html--><p>Line #11 - 18: <em><strong>this[string name] &#xA0;</strong></em>This is the entry method in our controller that we will use. It accepts a key and uses the previously described approach to try to find the associated values in the JSON file. It&apos;s worth noting that if no value is discovered in the JSON file, the method will return the same key.</p><p>Next, we&apos;ll create a Factory class that will be responsible for generating the JsonStringLocalizer instance internally. Name the new class as JsonStringLocalizerFactory.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_8 - incontent_8 -->
<div id="ezoic-pub-ad-placeholder-146"> </div>
<!-- End Ezoic - incontent_8 - incontent_8 --><!--kg-card-end: html--><pre><code class="language-csharp">    public class JsonStringLocalizerFactory : IStringLocalizerFactory
    {
        private readonly IDistributedCache _cache;

        public JsonStringLocalizerFactory(IDistributedCache cache)
        {
            _cache = cache;
        }

        public IStringLocalizer Create(Type resourceSource) =&gt;
            new JsonStringLocalizer(_cache);

        public IStringLocalizer Create(string baseName, string location) =&gt;
            new JsonStringLocalizer(_cache);
    }</code></pre><p>Then comes the fun part: writing a Middleware that can read the Accept-Language key from the request header and set the current thread&apos;s language if the culture is valid.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_9 - incontent_9 -->
<div id="ezoic-pub-ad-placeholder-147"> </div>
<!-- End Ezoic - incontent_9 - incontent_9 --><!--kg-card-end: html--><p>Create a new class and name it LocalizationMiddleware.</p><pre><code class="language-csharp">    public class LocalizationMiddleware : IMiddleware
    {
        public async Task InvokeAsync(HttpContext context, RequestDelegate next)
        {
            var cultureKey = context.Request.Headers[&quot;Accept-Language&quot;];
            if (!string.IsNullOrEmpty(cultureKey))
            {
                if (DoesCultureExist(cultureKey))
                {
                    var culture = new CultureInfo(cultureKey);
                    Thread.CurrentThread.CurrentCulture = culture;
                    Thread.CurrentThread.CurrentUICulture = culture;
                }
            }
            await next(context);
        }
        private static bool DoesCultureExist(string cultureName)
        {
            return CultureInfo.GetCultures(CultureTypes.AllCultures)
                .Any(culture =&gt; string.Equals(culture.Name, cultureName,
              StringComparison.CurrentCultureIgnoreCase));
        }
    }</code></pre><!--kg-card-begin: html--><!-- Ezoic - incontent_10 - incontent_10 -->
<div id="ezoic-pub-ad-placeholder-149"> </div>
<!-- End Ezoic - incontent_10 - incontent_10 --><!--kg-card-end: html--><p>Line #5: The Accept-Language of the current HTTP context is read here from the request header.</p><p>Line #8-13: The current thread culture is set if a valid culture is found.</p><p>Let&apos;s start by adding some language files. Create a new Resources folder and add two new JSON files to it. The JSON files will be named en-US.json and de-DE.json</p><p>Sample of en-US.json</p><pre><code class="language-json">{
  &quot;hi&quot;: &quot;Hello&quot;,
  &quot;welcome&quot;: &quot;Welcome {0}, How are you?&quot;
}</code></pre><p>Next,de-DE.json. PS, the following was translated via Google Translate.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_11 - incontent_11 -->
<div id="ezoic-pub-ad-placeholder-150"> </div>
<!-- End Ezoic - incontent_11 - incontent_11 --><!--kg-card-end: html--><pre><code class="language-json">{
  &quot;hi&quot;: &quot;Hallo&quot;,
  &quot;welcome&quot;: &quot;Willkommen {0}, wie geht es dir?&quot;
}</code></pre><p>As you can see, we have two keys, hello and welcome, that the program is supposed to translate based on the request header.</p><p>Now comes the crucial phase, where we register our middleware and the JSONLocalizer as services. Add the following to the ConfigureServices function in Startup.cs.</p><pre><code class="language-csharp">services.AddLocalization();
services.AddSingleton&lt;LocalizationMiddleware&gt;();
services.AddDistributedMemoryCache();
services.AddSingleton&lt;IStringLocalizerFactory, JsonStringLocalizerFactory&gt;();</code></pre><p>Add the following to the Configure method. It&apos;s worth noting that we&apos;ve set en-US as our application&apos;s default culture. This can also be made configurable by moving it to the appsettings.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_12 - incontent_12 -->
<div id="ezoic-pub-ad-placeholder-151"> </div>
<!-- End Ezoic - incontent_12 - incontent_12 --><!--kg-card-end: html--><pre><code class="language-csharp">var options = new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture(new CultureInfo(&quot;en-US&quot;))
};
app.UseRequestLocalization(options);
app.UseStaticFiles();
app.UseMiddleware&lt;LocalizationMiddleware&gt;();</code></pre><p>Finally, let&apos;s create a new API Controller to show how our JSON localizer works. Create a new Controller with the name HomeController.</p><pre><code class="language-csharp">    public class HomeController : ControllerBase
    {
        private readonly IStringLocalizer&lt;HomeController&gt; _stringLocalizer;

        public HomeController(IStringLocalizer&lt;HomeController&gt; stringLocalizer)
        {
            _stringLocalizer = stringLocalizer;
        }
        [HttpGet]
        public IActionResult Get()
        {
            var message = _stringLocalizer[&quot;hi&quot;].ToString();
            return Ok(message);
        }
        [HttpGet(&quot;{name}&quot;)]
        public IActionResult Get(string name)
        {
            var message = string.Format(_stringLocalizer[&quot;welcome&quot;], name);
            return Ok(message);
        }
        [HttpGet(&quot;all&quot;)]
        public IActionResult GetAll()
        {
            var message = _stringLocalizer.GetAllStrings();
            return Ok(message);
        }
    }</code></pre><!--kg-card-begin: html--><!-- Ezoic - long_content - long_content -->
<div id="ezoic-pub-ad-placeholder-140"> </div>
<!-- End Ezoic - long_content - long_content --><!--kg-card-end: html--><p>Line #3: Constructor Injection of IStringLocalizer instance.</p><p>Line #10 - 14: Here&apos;s a test to see whether we can output the localized version of the key &apos;hi&apos; to the console and then return it as a response.</p><p>Line #16 - 20: The application should return a localized version of &quot;Welcome xxxx, how are you?&quot; when we give this endpoint a random name. That&apos;s all there is to it.</p><p>Line #22 - 26: This method would ideally return all the keys and values found in the corresponding JSON file.</p><h2 id="testing-with-postman">Testing with Postman</h2><p>Let&apos;s fire up Postman and perform some basic tests.</p><p>Here is what you get as a response when you send a GET request to the /api/home endpoint with the Accept-Language as de-DE</p><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/JSON-Based-Localization-in-.NET-6-de-DE.webp" class="kg-image" alt="Localization with JSON files in .NET 6" loading="lazy" width="1805" height="628"></figure><p>Accept-Language is set to en-US.</p><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/JSON-Based-Localization-in-.NET-6-en-US.webp" class="kg-image" alt="Localization with JSON files in .NET 6" loading="lazy" width="1797" height="615"></figure><p>Now, I try to send a GET request to the /api/home endpoint along with the name. Accept-Language set to en-US</p><!--kg-card-begin: html--><!-- Ezoic - longer_content - longer_content -->
<div id="ezoic-pub-ad-placeholder-141"> </div>
<!-- End Ezoic - longer_content - longer_content --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res-3.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/JSON-Based-Localization-in-.NET-6-en-US-name.webp" class="kg-image" alt="Localization with JSON files in .NET 6" loading="lazy" width="1811" height="458"></figure><p>Accept-Language set to de-DE.</p><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/JSON-Based-Localization-in-.NET-6-de-DE-name.webp" class="kg-image" alt="Localization with JSON files in .NET 6" loading="lazy" width="1805" height="607"></figure><p>Finally, when you send a GET request to the /api/home/all endpoint, you get to see all the key/value pairs of our strings in the JSON file related to the relevant accept-language.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/JSON-Based-Localization-in-.NET-6-all.webp" class="kg-image" alt="Localization with JSON files in .NET 6" loading="lazy" width="1787" height="762"></figure><p>Isn&apos;t it great to have in your projects?</p><!--kg-card-begin: html--><!-- Ezoic - bottom_of_page - bottom_of_page -->
<div id="ezoic-pub-ad-placeholder-148"> </div>
<!-- End Ezoic - bottom_of_page - bottom_of_page --><!--kg-card-end: html--><h2 id="summary">Summary</h2><p>We learned a quick and easy technique to implement JSON-based localization in .NET 6 applications in this article. The source code can be found <a href="https://github.com/nandkishor-yadav/dotnet-6-json-localization">here</a>.</p>]]></content:encoded></item><item><title><![CDATA[Azure resource manager Templates Tutorial For Beginners]]></title><description><![CDATA[If you are an Azure administrator or you are developing the application for Azure, you should know how to manage your infrastructure from code. It provides several benefits while migrating or managing multiple resources.]]></description><link>https://cloudcoders.xyz/blog/azure-resource-manager-templates/</link><guid isPermaLink="false">61dcc56eb3be2971432fb70d</guid><category><![CDATA[arm template]]></category><category><![CDATA[azure]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Tue, 15 Jun 2021 11:10:34 GMT</pubDate><media:content url="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/azure-arm-work-flow.png" medium="image"/><content:encoded><![CDATA[<h2 id="what-is-azure-resources-manager-arm">What is Azure Resources Manager (ARM)?</h2><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/azure-arm-work-flow.png" alt="Azure resource manager Templates Tutorial For Beginners"><p>Azure Resource Manager is the deployment and management service for Azure. It provides a management layer that enables you to create, update, and delete resources in your Azure account. You use management features, like access control, locks, and tags, to secure and organize your resources after deployment.</p><p><strong>Key service characteristics</strong></p><ul><li>Deployment and Management service</li><li>Centralized layer for resource Manager</li></ul><p><strong>How does it work?</strong></p><p>First, let&apos;s talk about how we can deploy resources in Azure.</p><figure class="kg-card kg-image-card"><img src="https://res-1.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/azure-arm-work-flow.png" class="kg-image" alt="Azure resource manager Templates Tutorial For Beginners" loading="lazy" width="647" height="357"></figure><p>There are several ways of deploying resources to Azure such as Azure Portal, Azure PowerShell, Azure CLI, rest client.</p><p>For Azure PowerShell and Azure CLI, we use SDKs, however, all those interfaces are communicating with the single <strong>Azure Resource Manager</strong> endpoint which is the centralized layer.</p><p>It is secured by default because it is secured with Active Directory.</p><p>Once the request is received, the resource manager talks to <strong>Resource Provider</strong>. Every single resource in Azure has its own Resource Provider and that resource provider handles everything related to that specific resource.</p><p>In Azure, everything is managed in hierarchical scope and the scope goes from the management groups to the lowest level of Resources.</p><figure class="kg-card kg-image-card"><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/azure-arm-hierarchical-scope.png" class="kg-image" alt="Azure resource manager Templates Tutorial For Beginners" loading="lazy" width="569" height="368"></figure><h2 id="arm-templates-overview">ARM templates overview.</h2><p>They are the unified language for you to manage resources in Azure using a declarative approach using very simple files.</p><p><strong>HOW IT WORKS</strong></p><p>The way it works is very simple. Imagine you have a resource group in which you have a virtual machine and a storage account. You can create a very simple template to deploy all that in a single go.</p><p>The format of the file is JSON. The format has standard properties of which some are the same and some are mandatory.</p><p>The template will look like this.</p><pre><code class="language-json">{
  &quot;$schema&quot;: &quot;https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#&quot;,
  &quot;contentVersion&quot;: &quot;1.0.0.0&quot;,
  &quot;parameters&quot;: {},
  &quot;functions&quot;: [],
  &quot;variables&quot;: {},
  &quot;resources&quot;: [
        {

            /* Resource A */
        },
        {
            /* Resource B */
        }
       
  ],
  &quot;outputs&quot;: {}
}</code></pre><p><em><strong>$schema:</strong></em> Describes properties available in the template.</p><p><em><strong>contentVersion:</strong></em> Versioning system in the template for development purpose. If you are using git for versioning, then this field is not important to keep it up-to-date.</p><p><em><strong>parameters:</strong></em> This field is optional but if you want to parameterize your template then you can use this to pick up some input parameters for the template.</p><p><em><strong>variables:</strong></em> If you want to calculate something dynamically then you can use variables section to calculate some dynamic properties during the execution of the template based on your input parameters and other variables.</p><p><em><strong>resources:</strong></em> The most important section of the template. It&apos;s an Array of JSON objects, where each objects describes the service that is going to be deploying and you can multiple resources deployed using the single template.</p><p><em><strong>output:</strong></em> This section allows you to return some properties and information from the template execution. This is useful for chaining multiple templates together. For example, you can capture the Id of the component you have created and pass that to another template.</p><p><em><strong>function:</strong></em> You can define expressions here and reuse across your template.</p><h2 id="benefits-of-using-arm-templates">Benefits of using ARM Templates</h2><ul><li>Infrastructure as Code (IaC), Policy and Roles as Code</li><li>Declarative syntax (what is it)</li><li>Repeatable results</li><li>Orchestration</li><li>Built-in Validation</li><li>Modular files</li><li>Tracked templates</li><li>Many authoring tools</li><li>Functions and expressions</li><li>Linked and nested templates</li><li>Dependencies</li><li>References</li><li>Export</li><li>Loops</li><li>Conditions</li></ul><h2 id="when-to-use-arm-templates">When to use ARM Templates</h2><ol><li>Application development and maintenance</li><li>CI/CD scenarios</li><li>Azure governance</li></ol><ul><li>Policies</li><li>Roles</li><li>Etc.</li></ul><p>The most typical and common scenario is application development and maintenance. It can also be used for CI/CD of those applications and it is very helpful when you are moving resources across multiple environments that ensure consistent results.</p><p>If you are an administrator for managing resources, you can use ARM templates for governance. You can define policies, roles, and many more.</p><p>By now, we have some concepts about the Azure Resource Manager, now let&#x2019;s dive into the demo.</p><p>I will be using VS Code for editing files and deploying them to Azure. There is one extension from Microsoft called Azure Resource Manager (ARM) tools. I am using this extension in VS Code because it gives great IntelliSense and snippets to work with.</p><figure class="kg-card kg-image-card"><img src="https://res-2.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/azure-resource-manager-tool.png" class="kg-image" alt="Azure resource manager Templates Tutorial For Beginners" loading="lazy" width="940" height="204"></figure><pre><code class="language-json">{
  &quot;$schema&quot;: &quot;https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#&quot;,
  &quot;contentVersion&quot;: &quot;1.0.0.0&quot;,
  &quot;parameters&quot;: {},
  &quot;functions&quot;: [],
  &quot;variables&quot;: {},
  &quot;resources&quot;: [
{
    &quot;name&quot;: &quot;storageaccount1&quot;,
    &quot;type&quot;: &quot;Microsoft.Storage/storageAccounts&quot;,
    &quot;apiVersion&quot;: &quot;2019-06-01&quot;,
    &quot;tags&quot;: {
        &quot;displayName&quot;: &quot;storageaccount1&quot;
    },
    &quot;location&quot;: &quot;[resourceGroup().location]&quot;,
    &quot;kind&quot;: &quot;StorageV2&quot;,
    &quot;sku&quot;: {
        &quot;name&quot;: &quot;Standard_LRS&quot;,
        &quot;tier&quot;: &quot;Standard&quot;
    }
}
  ],
  &quot;outputs&quot;: {}
}
</code></pre><p>As we have hardcoded the name of the resource, which is not the best approach because we need to update our templates several times. So, let&#x2019;s add parameters in our template. We can add parameters for storage name as below.</p><pre><code class="language-json">&quot;parameters&quot;: {
      &quot;storageName&quot;: {
           &quot;type&quot;:&quot;string&quot;,
        &quot;minLength&quot;:3,
        &quot;maxLength&quot;:24
      }
  }</code></pre><p>We can also add validation. Now we have our parameters ready, we can get the value by calling function. To call function in ARM Templates, we can call the function inside [] brackets. The function for the parameters is called <strong>parameters</strong> which takes the name of the parameter as argument.</p><pre><code class="language-json">&quot;name&quot;: &quot;[parameters(&apos;storageName&apos;)]&quot;,</code></pre><p>Now, we need to provide the parameter name in the PowerShell script.</p><p>We can also add parameters for list of allowed values for storage SKU, which will run validation before it gets deployed.</p><pre><code class="language-json">&quot;storageSKU&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;allowedValues&quot;: [
        &quot;Standard_LRS&quot;,
        &quot;Standard_GRS&quot;,
        &quot;Standard_RAGRS&quot;,
        &quot;Standard_ZRS&quot;,
        &quot;Premium_LRS&quot;,
        &quot;Premium_ZRS&quot;,
        &quot;Standard_GZRS&quot;,
        &quot;Standard_RAGZRS&quot;
      ]
    }
</code></pre><p>The final template will look like this</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  &quot;$schema&quot;: &quot;https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#&quot;,
  &quot;contentVersion&quot;: &quot;1.0.0.0&quot;,
  &quot;parameters&quot;: {
    &quot;storageName&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;minLength&quot;: 3,
      &quot;maxLength&quot;: 24
    },
    &quot;storageSKU&quot;: {
      &quot;type&quot;: &quot;string&quot;,
      &quot;allowedValues&quot;: [
        &quot;Standard_LRS&quot;,
        &quot;Standard_GRS&quot;,
        &quot;Standard_RAGRS&quot;,
        &quot;Standard_ZRS&quot;,
        &quot;Premium_LRS&quot;,
        &quot;Premium_ZRS&quot;,
        &quot;Standard_GZRS&quot;,
        &quot;Standard_RAGZRS&quot;
      ]
    }
  },
  &quot;functions&quot;: [],
  &quot;variables&quot;: {},
  &quot;resources&quot;: [
    {
      &quot;name&quot;: &quot;[parameters(&apos;storageName&apos;)]&quot;,
      &quot;type&quot;: &quot;Microsoft.Storage/storageAccounts&quot;,
      &quot;apiVersion&quot;: &quot;2019-06-01&quot;,
      &quot;tags&quot;: {
        &quot;displayName&quot;: &quot;storageaccount1&quot; // optional
      },
      &quot;location&quot;: &quot;[resourceGroup().location]&quot;,
      &quot;kind&quot;: &quot;StorageV2&quot;,
      &quot;sku&quot;: {
        &quot;name&quot;: &quot;[parameters(&apos;storageSKU&apos;)]&quot;,
        &quot;tier&quot;: &quot;Standard&quot;
      }
    }
  ],
  &quot;outputs&quot;: {}
}
</code></pre><figcaption>storage.json</figcaption></figure><p>Now, you can create a PowerShell script to deploy the template like this.</p><figure class="kg-card kg-code-card"><pre><code class="language-PowerShell">$rg = &apos;arm-demo-01&apos;
New-AzResourceGroup -Name $rg -Location northeurope -Force

New-AzResourceGroupDeployment `
    -Name &apos;new-storage&apos; `
    -ResourceGroupName $rg `
    -TemplateFile &apos;storage.json&apos; `
    -storageName &apos;armdemostorage01a&apos; `
    -storageSKU &apos;Standard_LRS&apos;</code></pre><figcaption>storage.ps1</figcaption></figure><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/powershell-script.webp" class="kg-image" alt="Azure resource manager Templates Tutorial For Beginners" loading="lazy" width="764" height="213"></figure><p>Now, the template can be deployed using the terminal. Navigate to the folder where template file is stored. First connect to Azure account by typing the following command in the terminal.</p><pre><code class="language-PowerShell">Connect-AZAccount</code></pre><p>Then, execute the PowerShell file.</p><figure class="kg-card kg-image-card"><img src="https://res-5.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/arm-storage-deployment.webp" class="kg-image" alt="Azure resource manager Templates Tutorial For Beginners" loading="lazy" width="1697" height="589"></figure><p>Now, you can see that the resource has been deployed successfully.</p><p>Additional resources:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://azure.microsoft.com/en-us/resources/templates/?WT.mc_id=AZ-MVP-5003556"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Azure Quickstart Templates</div><div class="kg-bookmark-description">Deploy Azure resources through the Azure Resource Manager with community contributed&lt;br&gt;templates to get more done. Deploy, learn, fork and contribute back.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://azurecomcdn.azureedge.net/cvt-834141be0b76f09d6ccddc47fc8dd12ba0d658fdcf526b0e685554f88b39179c/images/icon/apple-touch/180x180.png" alt="Azure resource manager Templates Tutorial For Beginners"><span class="kg-bookmark-author">Microsoft Azure</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://azurecomcdn.azureedge.net/cvt-834141be0b76f09d6ccddc47fc8dd12ba0d658fdcf526b0e685554f88b39179c/images/shared/social/azure-icon-250x250.png" alt="Azure resource manager Templates Tutorial For Beginners"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/Azure/azure-quickstart-templates?WT.mc_id=AZ-MVP-5003556"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Azure/azure-quickstart-templates</div><div class="kg-bookmark-description">Azure Quickstart Templates. Contribute to Azure/azure-quickstart-templates development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/favicons/favicon.svg" alt="Azure resource manager Templates Tutorial For Beginners"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">Azure</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://repository-images.githubusercontent.com/34407651/61f18e00-69e1-11ea-901f-d030a57d4391" alt="Azure resource manager Templates Tutorial For Beginners"></div></a></figure>]]></content:encoded></item><item><title><![CDATA[How to use Azure Key Vault in ASP.NET Core apps]]></title><description><![CDATA[Azure Key Vault is a tool for securely storing and accessing secrets. A secret is anything that you want to tightly control access.]]></description><link>https://cloudcoders.xyz/blog/how-to-use-azure-key-vault-in-aspnetcore-apps/</link><guid isPermaLink="false">61dcc56eb3be2971432fb70c</guid><category><![CDATA[azure key vault]]></category><category><![CDATA[aspnetcore]]></category><dc:creator><![CDATA[Nandkishor]]></dc:creator><pubDate>Sat, 05 Jun 2021 17:08:00 GMT</pubDate><media:content url="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/azure-key-vault-cloudcoders.png" medium="image"/><content:encoded><![CDATA[<h2 id="azure-key-vault-%E2%80%93-what-is-it">Azure Key Vault &#x2013; what is it?</h2><!--kg-card-begin: html--><!-- Ezoic - under_feature_image - under_page_title -->
<div id="ezoic-pub-ad-placeholder-137"> </div>
<!-- End Ezoic - under_feature_image - under_page_title --><!--kg-card-end: html--><img src="https://res-4.cloudinary.com/nandkishor-yadav/image/upload/q_auto/v1/cloudcoders-images/azure-key-vault-cloudcoders.png" alt="How to use Azure Key Vault in ASP.NET Core apps"><p>Azure Key Vault is a tool for securely storing and accessing secrets. A secret is anything that you want to tightly control access to, such as API keys, passwords, or certificates. A vault is a logical group of secrets. Essentially, Azure Key Vault can be thought of as well, a vault! You put your secret things in, and they are kept secure by the vault. Azure Key Vault is of course more complex and offers many features. Feel free to dig more into the details in case you are interested.</p><!--kg-card-begin: html--><!-- Ezoic - under_first_paragraph - under_first_paragraph -->
<div id="ezoic-pub-ad-placeholder-138"> </div>
<!-- End Ezoic - under_first_paragraph - under_first_paragraph --><!--kg-card-end: html--><h2 id="motivation">Motivation</h2><p>The aim here is to configure the data protection system in such a way as to store its keys outside the app server, but also to do so in a secure way. The data security keys can be stored in a local folder by default (see default settings), and the keys may or may not be encrypted at rest. Azure Key Vault, in combination with managed identities for Azure resources, enables your Azure web app to access secret configuration values easily and securely without needing to store any secrets in your source control or configuration.</p><!--kg-card-begin: html--><!-- Ezoic - under_second_paragraph - under_second_paragraph -->
<div id="ezoic-pub-ad-placeholder-139"> </div>
<!-- End Ezoic - under_second_paragraph - under_second_paragraph --><!--kg-card-end: html--><h2 id="prerequisite">Prerequisite</h2><ul><li>Azure portal access</li><li>Visual studio or visual studio code</li></ul><p>If you don&apos;t have an Azure account, you can create one for free here: <a href="https://portal.azure.com/">https://portal.azure.com/</a></p><p>We need an Azure App Registration in the Azure Active Directory together with Azure Key Vault to access key vault secrets.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_5 - incontent_5 -->
<div id="ezoic-pub-ad-placeholder-143"> </div>
<!-- End Ezoic - incontent_5 - incontent_5 --><!--kg-card-end: html--><h2 id="using-azure-key-vault-with-aspnet-core-apps">Using Azure Key Vault with ASP.NET Core apps</h2><p>To use Azure Key Vault as one of the configuration providers for your app you&apos;d need to do some work, such as adding specific NuGet packages, getting the Vault URL, creating your clientId and secret, connecting to the vault, and reading the secrets.</p><h2 id="steps-of-our-demo">Steps of our demo</h2><ol><li>Creating the key vault.</li><li>Adding a database connection string to our key vault.</li><li>Configuring the access policy on the Key Vault for our App Service.</li><li>Creating a system-assigned identity for our App Service.</li><li>Creating ASP.NET Core 3.1 web application in visual studio and configuring the key vault.</li></ol><!--kg-card-begin: html--><!-- Ezoic - incontent_6 - incontent_6 -->
<div id="ezoic-pub-ad-placeholder-144"> </div>
<!-- End Ezoic - incontent_6 - incontent_6 --><!--kg-card-end: html--><h2 id="creating-the-key-vault">Creating the Key Vault</h2><p>On the Azure Portal, go to <strong>Resource groups &gt;&gt; &lt;your resource group&gt; &lt;add new resource&gt; &lt;key vault&gt; &lt;create&gt;</strong></p><ol><li>Fill in the Instance details: Name, Region, and Pricing tier.</li><li>Review the things and click on create. We will talk about Access Policy later in this post.</li></ol><figure class="kg-card kg-image-card"><img src="https://res.cloudinary.com/nandkishor-yadav/image/upload/cloudcoders/cloudcoders-create-key-vault.webp" class="kg-image" alt="How to use Azure Key Vault in ASP.NET Core apps" loading="lazy"></figure><!--kg-card-begin: html--><!-- Ezoic - mid_content - mid_content -->
<div id="ezoic-pub-ad-placeholder-154"> </div>
<!-- End Ezoic - mid_content - mid_content --><!--kg-card-end: html--><h2 id="adding-a-database-connection-string-to-our-key-vault">Adding a database connection string to our Key Vault</h2><p>Navigate to your Key Vault once deployment finishes. Look at the left menu and click <strong>Secrets</strong> and then <strong>Generate/Import</strong></p><figure class="kg-card kg-image-card"><img src="https://res.cloudinary.com/nandkishor-yadav/image/upload/cloudcoders/cloudcoders-kye-vault-secrets.webp" class="kg-image" alt="How to use Azure Key Vault in ASP.NET Core apps" loading="lazy"></figure><p>Enter the connection string to your database and click <strong>Create</strong>. I have added my connection string and the page looks like this:</p><!--kg-card-begin: html--><!-- Ezoic - incontent_7 - incontent_7 -->
<div id="ezoic-pub-ad-placeholder-145"> </div>
<!-- End Ezoic - incontent_7 - incontent_7 --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res.cloudinary.com/nandkishor-yadav/image/upload/cloudcoders/cloudcoders-create-secret.webp" class="kg-image" alt="How to use Azure Key Vault in ASP.NET Core apps" loading="lazy"></figure><!--kg-card-begin: html--><!-- Ezoic - incontent_8 - incontent_8 -->
<div id="ezoic-pub-ad-placeholder-146"> </div>
<!-- End Ezoic - incontent_8 - incontent_8 --><!--kg-card-end: html--><h2 id="configuring-the-access-policy-on-the-key-vault-for-our-app-service">Configuring the access policy on the Key Vault for our App Service</h2><p>We need to grant permission to our web app to read the secrets from the Key Vault. To do this go to Key Vault Page, and from the left menu click on <strong>Access Policies</strong>.</p><p>Once on the <strong>Access policies</strong> page, click on <strong>Add access policy</strong>. Select <strong>Get</strong> for the <strong>Secret permissions</strong> field. Next, click on the <strong>Select principal</strong> field. A sidebar will appear on the right side of the screen. There, you need to search for our managed identity, which matches the name of your App Service. Click Select on the window. In the end, it should look like this:</p><!--kg-card-begin: html--><!-- Ezoic - incontent_9 - incontent_9 -->
<div id="ezoic-pub-ad-placeholder-147"> </div>
<!-- End Ezoic - incontent_9 - incontent_9 --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res.cloudinary.com/nandkishor-yadav/image/upload/cloudcoders/cloudcoders-add-access-policy.webp" class="kg-image" alt="How to use Azure Key Vault in ASP.NET Core apps" loading="lazy"></figure><p>Click on <strong>Add</strong> then on <strong>Save</strong> to save changes. Now our app service has <strong>Get access</strong> to secrets in the Vault.</p><h2 id="creating-a-system-assigned-identity-for-our-app-service">Creating a system-assigned identity for our App Service.</h2><p>Our App Service needs to have access to it to be able to consume the secrets from the Key Vault. In Azure, you can configure one resource to access another by creating what&#x2019;s called a managed identity. Once your resource has a managed identity, you can modify another resource and allow access to it.</p><!--kg-card-begin: html--><!-- Ezoic - incontent_10 - incontent_10 -->
<div id="ezoic-pub-ad-placeholder-149"> </div>
<!-- End Ezoic - incontent_10 - incontent_10 --><!--kg-card-end: html--><figure class="kg-card kg-image-card"><img src="https://res.cloudinary.com/nandkishor-yadav/image/upload/cloudcoders/cloudcoders-key-vault-assign-identity.webp" class="kg-image" alt="How to use Azure Key Vault in ASP.NET Core apps" loading="lazy"></figure><h2 id="creating-aspnet-core-31-web-application-in-visual-studio-and-configuring-the-key-vault">Creating ASP.NET Core 3.1 web application in visual studio and configuring the key vault</h2><!--kg-card-begin: html--><!-- Ezoic - incontent_11 - incontent_11 -->
<div id="ezoic-pub-ad-placeholder-150"> </div>
<!-- End Ezoic - incontent_11 - incontent_11 --><!--kg-card-end: html--><p>After creating the project, install <strong>Microsoft.Extensions.Configuration.AzureKeyVault</strong> NuGet package to the project.</p><p>Now, let&#x2019;s modify the CreateHostBuilder method in the Program.cs file.</p><pre><code class="language-csharp">using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration.AzureKeyVault;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;


namespace AzureKeyVaultDemo
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }


        public static IHostBuilder CreateHostBuilder(string[] args) =&gt;
            Host.CreateDefaultBuilder(args)


            .ConfigureAppConfiguration((context, config) =&gt;
            {
                var keyVaultEndpoint = GetKeyVaultEndpoint();
                if (!string.IsNullOrEmpty(keyVaultEndpoint))
                {
                    var azureServiceTokenProvider = new AzureServiceTokenProvider();
                    var keyVaultClient = new KeyVaultClient(
                        new KeyVaultClient.AuthenticationCallback(
                            azureServiceTokenProvider.KeyVaultTokenCallback));
                    config.AddAzureKeyVault(keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
                }
            })


            .ConfigureWebHostDefaults(webBuilder =&gt;
            {
                webBuilder.UseStartup&lt;Startup&gt;();
            });
        private static string GetKeyVaultEndpoint() =&gt; &quot;https://kvdemo-01.vault.azure.net/&quot;; //Endpoint of the Azure Key Vault.
    }
}</code></pre><!--kg-card-begin: html--><!-- Ezoic - longest_content - longest_content -->
<div id="ezoic-pub-ad-placeholder-142"> </div>
<!-- End Ezoic - longest_content - longest_content --><!--kg-card-end: html--><p>Now we can access the value in our controller like this.</p><pre><code class="language-csharp">public class HomeController : Controller
    {
        private readonly ILogger&lt;HomeController&gt; _logger;
        private readonly IConfiguration _configuration;

        public HomeController(ILogger&lt;HomeController&gt; logger, IConfiguration  configuration)
        {
            _logger = logger;
            _configuration = configuration;
        }

        public IActionResult Index()
        {
            TempData[&quot;mysecrets&quot;] = _configuration[&quot;mysecret01&quot;];
            return View();
        }

        public IActionResult Privacy()
        {
            return View();
        }

        [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
        public IActionResult Error()
        {
            return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
        }
    }</code></pre><!--kg-card-begin: html--><!-- Ezoic - bottom_of_page - bottom_of_page -->
<div id="ezoic-pub-ad-placeholder-148"> </div>
<!-- End Ezoic - bottom_of_page - bottom_of_page --><!--kg-card-end: html--><p>The sample project can be found on my <a href="https://github.com/nandkishor-yadav/AzureKeyVaultDemo" rel="nofollow noopener">GitHub</a> repository.</p>]]></content:encoded></item></channel></rss>