<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mahesh More</title>
    <description>The latest articles on DEV Community by Mahesh More (@maheshmore2691).</description>
    <link>https://dev.to/maheshmore2691</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F358872%2Fe96ae717-b296-4890-91bd-01e2f1a481f2.png</url>
      <title>DEV Community: Mahesh More</title>
      <link>https://dev.to/maheshmore2691</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maheshmore2691"/>
    <language>en</language>
    <item>
      <title>Hangfire Jobs -Background processing with DotNet core</title>
      <dc:creator>Mahesh More</dc:creator>
      <pubDate>Sat, 28 Jan 2023 15:04:32 +0000</pubDate>
      <link>https://dev.to/maheshmore2691/hangfire-jobs-background-processing-with-dotnet-core-1d28</link>
      <guid>https://dev.to/maheshmore2691/hangfire-jobs-background-processing-with-dotnet-core-1d28</guid>
      <description>&lt;h2&gt;
  
  
  What's Hangfire?
&lt;/h2&gt;

&lt;p&gt;Hangfire is an open-source library that allows you to kick-start the process in the background so you don't need a separate process or windows service for processing. It's also backed with persistent storage so you can pause, resume, stop and restart failed jobs at any point and it will keep track of activity in the persistent database, and everything is stored in storage which helps background jobs to survive &lt;strong&gt;application restart, server reboot&lt;/strong&gt;, etc.&lt;/p&gt;

&lt;p&gt;This library consists of three main components: &lt;code&gt;Client, Storage, and Server&lt;/code&gt;. Below diagram will give you a high-level view of how these three components work together to complete the particular background process.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Overview diagram:&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xg3I5rbI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0s76twxcblchuslirhx.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xg3I5rbI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i0s76twxcblchuslirhx.PNG" alt="Image description" width="608" height="351"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Types of background jobs
&lt;/h2&gt;

&lt;p&gt;Hangfire supports several kinds of background tasks, below is the list of jobs that you can create using Hangfire. For more information about each type click &lt;a href="https://www.hangfire.io/overview.html#many-types-of-background-jobs"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fire-And-Forget&lt;/li&gt;
&lt;li&gt;Delayed&lt;/li&gt;
&lt;li&gt;Recurring&lt;/li&gt;
&lt;li&gt;Continuation&lt;/li&gt;
&lt;li&gt;Batches&lt;/li&gt;
&lt;li&gt;Batch Continuation&lt;/li&gt;
&lt;li&gt;Background process&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;In this article, we will be implementing the Hangfire server in the DotNet core application and SQL as persistent storage. So let's start with actual implementations. Here we are implementing recurring jobs, but you can follow the same project for other types of jobs too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recurring Jobs:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create a new DotNet core application using Visual Studio:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Either you can create a new web application using VS or using a command prompt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yt-4cs1R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6os5hrseeeg8e0h9qua.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yt-4cs1R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f6os5hrseeeg8e0h9qua.PNG" alt="Image description" width="880" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Hangfire:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hangfire is available as a NuGet package so you can install the below packages from the NuGet feed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hangfire.Core&lt;/li&gt;
&lt;li&gt;Hangfire.SqlServer&lt;/li&gt;
&lt;li&gt;Hangfire.AspNetCore
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package Hangfire.Core
dotnet add package Hangfire.SqlServer
dotnet add package Hangfire.AspNetCore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have all the required Hangfire packages so the next step is to prepare persistent storage, here I'm assuming that you have SQL Server installed and configured properly for use.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new Database:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As I mentioned earlier we will be using SQL Server as job storage, so connect to the local instance of the SQL server using the SSMS tool and create the database using the below command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE [Hangfire]
GO
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Configure Hangfire Database in WebApp:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open &lt;code&gt;appsettings.json&lt;/code&gt; file and add a connection string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "ConnectionStrings": {
      "Hangfire": "Server=.;Database=Hangfire;Integrated Security=SSPI;"
    }
  .
  .
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Register services:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have created the app using &lt;code&gt;DotNet Core 6&lt;/code&gt; so I don't have &lt;code&gt;Startup.cs&lt;/code&gt; file so I will be configuring hangfire in &lt;code&gt;Program.cs&lt;/code&gt; file, if you have &lt;code&gt;DotNet 3.1&lt;/code&gt; application you can use a similar configuration in &lt;code&gt;Startup.cs&lt;/code&gt;. First, we need to import the required namespaces.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//...
using Hangfire;
using Hangfire.SqlServer;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default DotNet core supports dependency injection and &lt;code&gt;Hangfire.AspNetCore&lt;/code&gt; the NuGet package contains all the extension methods to register/configure &lt;code&gt;Hangfire Server&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.AddHangfire(config =&amp;gt; config
                                .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                                .UseSimpleAssemblyNameTypeSerializer()
                                .UseRecommendedSerializerSettings()
                                .UseSqlServerStorage(builder.Configuration.GetConnectionString("Hangfire"), new SqlServerStorageOptions
                                {
                                    CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
                                    SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
                                    QueuePollInterval = TimeSpan.Zero,
                                    UseRecommendedIsolationLevel = true,
                                    DisableGlobalLocks = true
                                })
                            );

builder.Services.AddHangfireServer();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Adding Dashboard UI:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hangfire does have a super cool feature where it provides you a dashboard and you can enqueue, dequeue, re-queue, and many more operations you can perform from this UI. The following code snippet shows you how to add a dashboard UI in the web app, so you can use all features from the user-friendly UI itself and no need to remember complex commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseEndpoints(endpoints =&amp;gt;
{
    endpoints.MapHangfireDashboard();
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So finally your Program.cs file will look like the one below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Hangfire;
using Hangfire.SqlServer;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

//Configure Hangfire

builder.Services.AddHangfire(config =&amp;gt; config
                                .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                                .UseSimpleAssemblyNameTypeSerializer()
                                .UseRecommendedSerializerSettings()
                                .UseSqlServerStorage(builder.Configuration.GetConnectionString("Hangfire"), new SqlServerStorageOptions
                                {
                                    CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
                                    SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
                                    QueuePollInterval = TimeSpan.Zero,
                                    UseRecommendedIsolationLevel = true,
                                    DisableGlobalLocks = true
                                })
                            );

builder.Services.AddHangfireServer();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseRouting();

app.UseEndpoints(endpoints =&amp;gt;
{
    endpoints.MapControllers();
    endpoints.MapHangfireDashboard();
});

app.Run();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Run the app:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now we have everything configured to run the application so either you can press &lt;code&gt;F5&lt;/code&gt;or run the app using the command &lt;code&gt;dotnet run&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SQL Database Schema:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;code&gt;step 3&lt;/code&gt; we have created separate DB for Hangfire jobs and in &lt;code&gt;step 4&lt;/code&gt; configured the connection in &lt;code&gt;appsettings.json&lt;/code&gt; file, so as soon as we run the application it will initialize the SQL table schema. You can find the list of tables in the below image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CE_Ymcpi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ljzgs8yjif2mvf24cjb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CE_Ymcpi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ljzgs8yjif2mvf24cjb.png" alt="Image description" width="250" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hangfire Dashboard:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now our application is started, open the following URL to access the Hangfire Dashboard interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://localhost:8057/hangfire"&gt;https://localhost:8057/hangfire&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sTaXkbXH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmq70kcb3psd9683vowd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sTaXkbXH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mmq70kcb3psd9683vowd.png" alt="Image description" width="720" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, the hangfire server runs on port &lt;code&gt;8057&lt;/code&gt;and dashboard can be served on &lt;code&gt;/hangfire&lt;/code&gt; endpoint path but you can configure this endpoint path while registering the dashboard in &lt;code&gt;Program/Startup.cs&lt;/code&gt; file. The following snippet will configure a custom path for accessing Dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.UseEndpoints(endpoints =&amp;gt;
{
    endpoints.MapControllers();
    endpoints.MapHangfireDashboard("/dashboard");
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3luyYl7z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5een7v3gruyodlw55wj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3luyYl7z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a5een7v3gruyodlw55wj.png" alt="Image description" width="720" height="441"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Now we have everything configured to run &lt;code&gt;Hangfire Server&lt;/code&gt; but still, we don't have any &lt;code&gt;recurring job&lt;/code&gt; configured that's why on Recurring Jobs tab we are seeing &lt;code&gt;0&lt;/code&gt; jobs on the dashboard, so let's configure one and see how we can queue and re-queue jobs from UI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new project:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can create new recurring jobs in the same project as well but just to keep everything isolated I have created new &lt;code&gt;class library&lt;/code&gt; project within the same solution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IriCBb4W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2rsjdyl3cz2bd2g04ir6.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IriCBb4W--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2rsjdyl3cz2bd2g04ir6.PNG" alt="Image description" width="880" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add UserMigration job:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now create IUsersMigration interface and UsersMigration class which will have an actual implementation of the job.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;IUsersMigration.cs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  public interface IUsersMigration
    {
        Task ExecuteAsync();
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;UsersMigration.cs&lt;/code&gt; I have created this job for demo purposes so it contains basic implementation but you can implement your own logic, but I believe you got an idea about how we can create a new job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  public class UsersMigration : IUsersMigration
    {
        public Task ExecuteAsync()
        {
            Console.WriteLine("Successfully completed!");

            return Task.CompletedTask;
        }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So our entire solution structure will look like the below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4D93idGA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9omgblrdohlf4z3qla5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4D93idGA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9omgblrdohlf4z3qla5h.png" alt="Image description" width="343" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Register newly created Job:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;code&gt;Program.cs&lt;/code&gt; file you have to register all the jobs with cronschedule. The following snippet will register recurring jobs as Never but you can change that schedule as per your requirement.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RecurringJob.AddOrUpdate&amp;lt;IUsersMigration&amp;gt;(x =&amp;gt; x.ExecuteAsync(), Cron.Never);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your final &lt;code&gt;Program.cs&lt;/code&gt; file will look as below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Hangfire;
using Hangfire.SqlServer;
using Workbench.Hangfire.Jobs.Migrations.Interfaces;
using Workbench.Hangfire.Jobs.Migrations.Jobs;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

//Configure Hangfire

builder.Services.AddHangfire(config =&amp;gt; config
                                .SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
                                .UseSimpleAssemblyNameTypeSerializer()
                                .UseRecommendedSerializerSettings()
                                .UseSqlServerStorage(builder.Configuration.GetConnectionString("Hangfire"), new SqlServerStorageOptions
                                {
                                    CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
                                    SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
                                    QueuePollInterval = TimeSpan.Zero,
                                    UseRecommendedIsolationLevel = true,
                                    DisableGlobalLocks = true
                                })
                            );

builder.Services.AddHangfireServer();

// Configure job's dependencies
builder.Services.AddScoped&amp;lt;IUsersMigration, UsersMigration&amp;gt;();

var app = builder.Build();

app.UseHttpsRedirection();

app.UseRouting();

app.UseEndpoints(endpoints =&amp;gt;
{
    endpoints.MapControllers();
    endpoints.MapHangfireDashboard("/dashboard");
});

// Register job
RecurringJob.AddOrUpdate&amp;lt;IUsersMigration&amp;gt;(x =&amp;gt; x.ExecuteAsync(), Cron.Never);

app.Run();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Enqueue job:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can select as many jobs as you wanted to enqueue and click on &lt;code&gt;Trigger now&lt;/code&gt; button, as soon as you trigger the jobs it will maintain the information in persistent storage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_Rj7EBB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/13evega28cq2kg4yzydg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q_Rj7EBB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/13evega28cq2kg4yzydg.png" alt="Image description" width="720" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To check the status you can visit the &lt;code&gt;Jobs&lt;/code&gt; tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2quftodl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ms9ftzayfetnpuqq63ez.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2quftodl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ms9ftzayfetnpuqq63ez.PNG" alt="Image description" width="880" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here you can filter the list of jobs by their status so in the above image we are in &lt;code&gt;Succeeded&lt;/code&gt; tab so all successful jobs will be listed here.&lt;/p&gt;

&lt;p&gt;You can also check the status from SQL Server as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT * FROM [HangFire].[Job];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  GitHub Repo &lt;a href="https://github.com/maheshmore2691/Workbench.Hangfire.Server"&gt;link&lt;/a&gt;.
&lt;/h3&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hangfire is an open-source library and is free to use for commercial use. It also provides you with a dashboard so non-technical users can use the dashboard to queue, re-queue, and delete scheduled jobs from the server. It also supports authentication to view the dashboard so no need to worry about anonymous user access. Hangfire supports SQL, Redis, and In-Memory as persistent storage so jobs can survive application restarts and even machine reboots, etc.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Different ways to implement IHttpClientFactory in .NET core apps</title>
      <dc:creator>Mahesh More</dc:creator>
      <pubDate>Mon, 28 Feb 2022 10:32:34 +0000</pubDate>
      <link>https://dev.to/maheshmore2691/different-ways-to-implement-ihttpclientfactory-in-net-core-apps-2oko</link>
      <guid>https://dev.to/maheshmore2691/different-ways-to-implement-ihttpclientfactory-in-net-core-apps-2oko</guid>
      <description>&lt;h2&gt;
  
  
  Why not HttpClient?
&lt;/h2&gt;

&lt;p&gt;We have been using the &lt;code&gt;HttpClient&lt;/code&gt; class for REST API calls and I am not saying this is bad practice but most of the times developer use it wrongly and it has some limitations which cause serious issues, I have noted a few of them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Even we dispose of instance underlying socket doesn't release immediately, which leads to &lt;a href="https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/"&gt;socket exhaustion&lt;/a&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using(var client = new HttpClient())
{
    //do something with HTTP client
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you think creating an instance using the &lt;code&gt;using&lt;/code&gt; block will work? The answer is it won't work. If you are curious about what is the current state or wanted to confirm that the underline socket is closed or not then run the below command and it will show a list of connections that are in a wait or established state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; netstat -na | find 'Port_Number'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To avoid socket exhaustion if you create a singleton or static instance throughout the application lifetime then it's not the ultimate solution because when you reuse the instance which means you are reusing the connection until the socket is closed. So the connection won't get updates from the server, effectively it will fail to handle DNS changes when we switch from &lt;code&gt;staging&lt;/code&gt; to &lt;code&gt;production&lt;/code&gt; environment. You can find more details &lt;a href="http://byterot.blogspot.com/2016/07/singleton-httpclient-dns.html"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating an instance inside the &lt;code&gt;using&lt;/code&gt; directive is not good practice as it tries to dispose of instances of &lt;code&gt;HttpClient&lt;/code&gt; along with that it will dispose of the &lt;code&gt;HttpClientHandler&lt;/code&gt; as well. Under the hood, &lt;code&gt;HttpClient&lt;/code&gt; uses the &lt;code&gt;HttpClientHandler&lt;/code&gt; for actual socket connection, but underhood implementation is out of scope for this article but I will create a separate detailed article on it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To address the above issue .Net core introduced the &lt;code&gt;IHttpClientFactory&lt;/code&gt; interface which we can use for &lt;code&gt;HttpClient&lt;/code&gt; instance creation using DI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Different ways to use IHttpClientFactory:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Basic usage:&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;You can register &lt;code&gt;IHttpClientFactory&lt;/code&gt; using &lt;code&gt;AddHttpClient&lt;/code&gt; extension method.&lt;br&gt;
&lt;code&gt;Program.cs&lt;/code&gt; or &lt;code&gt;Startup.cs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddHttpClient();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;TestController.cs&lt;/code&gt;: DI will inject the dependency in the constructor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class TestController : Controller
{
   private readonly IHttpClientFactory  _factory;

   public TestController(IHttpClientFactory factory)
   {
     _factory = factory;
   }

   [HttpGet]
   public async Task&amp;lt;IActionResult&amp;gt; Get()
   {
     var httpClient = _factory.CreateClient();
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Named Clients:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you need a different configuration for each HttpClient then you can use named client DI and get an instance using the same name. Let's say you need to interact with 2 third-party APIs using HTTP REST calls and both need to be configured differently using the named client as below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Startup.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.Services.AddHttpClient("ClientA", httpClient =&amp;gt;
{
    httpClient.BaseAddress = new Uri("https://apiA.com/");
    //ToDo more configuration
});

builder.Services.AddHttpClient("ClientB", httpClient =&amp;gt;
{
    httpClient.BaseAddress = new Uri("https://apiB.com/");
    //ToDo more configuration
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;TestController.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var httpClientA = _factory.CreateClient("ClientA");

var httpClientB = _factory.CreateClient("ClientB");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Typed Clients&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It provides the same capabilities as the named client but instead of identifying the client based on the key it actually intelligently resolve HttpClient in a specific &lt;code&gt;HttpHandler&lt;/code&gt; class. Another advantage of this approach is you don't need to create &lt;code&gt;HttpClient&lt;/code&gt; manually using &lt;code&gt;IHttpClientFactory.CreateClient()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Let's say you decided to write one custom &lt;code&gt;HttpHandler&lt;/code&gt; which would be the single source for every REST call, so your implementation would look something like below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HttpCommands.cs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class HttpCommands
{
  private readonly HttpClient _httpClient;

  public HttpCommands(HttpClient httpClient)
  {
    _httpClient = httpClient;
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the constructor we are injecting &lt;code&gt;HttpClient&lt;/code&gt; itself and not &lt;code&gt;IHttpClientFactory&lt;/code&gt;, which means &lt;code&gt;_factory.CreateClient()&lt;/code&gt; is not required anymore because .Net core is smart enough to resolve the dependency.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Startup.cs&lt;/code&gt;: To register typed &lt;code&gt;HttpClient&lt;/code&gt; using generic version of &lt;code&gt;AddHttpClient()&lt;/code&gt; extension method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddHttpClient&amp;lt;HttpCommands&amp;gt;();

//Or if you need custom configuration you can configure that too as we did for the named client

services.AddHttpClient&amp;lt;HttpCommands&amp;gt;(client =&amp;gt;
{
  client.BaseAddress = new Uri("https://apiA.com/");
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What are the issues in traditional &lt;code&gt;HttpClient&lt;/code&gt; usage?&lt;/li&gt;
&lt;li&gt;What are the issues with the &lt;code&gt;static&lt;/code&gt; or &lt;code&gt;singleton&lt;/code&gt; &lt;code&gt;HttpClient&lt;/code&gt; instance.&lt;/li&gt;
&lt;li&gt;What are the different ways to use the &lt;code&gt;IHttpClientFactory&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>httpclient</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Looking for a way to initialize IOptions&lt;T&gt; manually?</title>
      <dc:creator>Mahesh More</dc:creator>
      <pubDate>Tue, 22 Feb 2022 11:41:55 +0000</pubDate>
      <link>https://dev.to/maheshmore2691/looking-for-a-way-to-initialize-ioptions-manually-idg</link>
      <guid>https://dev.to/maheshmore2691/looking-for-a-way-to-initialize-ioptions-manually-idg</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Ok ... I know what you are thinking you must have thought that DotNet Core's dependency injection handles it for you and we just need to register configuration class then what is the need for manual initialization? And I completely agree with you but sometimes you may need to create an instance of a class that is dependent on IOptions dependency (take an example of Unit test cases) and then real struggle starts.&lt;/p&gt;

&lt;p&gt;Let's say we have &lt;code&gt;ValueController.cs&lt;/code&gt; and it's accepting one parameter of type &lt;code&gt;IOptions&amp;lt;AppSettings&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ValueController : Controller
{
   public ValueController(IOptions&amp;lt;AppSettings&amp;gt; options)
   {
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, we have some app configuration in &lt;code&gt;appsettings.json&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
   "AppSettings": {
       "SettingOne": "ValueOne"
   }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Issue
&lt;/h2&gt;

&lt;p&gt;If you try to pass an instance of AppSettings class to ValueController then DotNet core will not allow it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var settings = new AppSettings { SettingOne = "ValueOne" };
var obj = new ValueController(settings);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even it will not allow you to explicitly cast the instance to &lt;code&gt;IOptions&amp;lt;AppSettings&amp;gt;&lt;/code&gt; type. Take a look at the below code which will not work. The below code will throw a runtime exception.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var settings = (IOptions&amp;lt;AppSettings&amp;gt;) new AppSettings { SettingOne = "ValueOne" };
var obj = new ValueController(settings);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then how to get it fixed? &lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Luckily DotNet core provides a static method to create an object of &lt;code&gt;IOptions&amp;lt;T&amp;gt;&lt;/code&gt; type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var settings = Options.Create(new AppSettings { SettingOne = "ValueOne" });
var obj = new ValueController(settings);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done! You are all set to initialize &lt;code&gt;IOptions&amp;lt;T&amp;gt;&lt;/code&gt; manually.&lt;/p&gt;

&lt;p&gt;Happy Coding!&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>dotnetcore</category>
      <category>dependancyinjection</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Identity Server 4 with .NET core app</title>
      <dc:creator>Mahesh More</dc:creator>
      <pubDate>Wed, 15 Jul 2020 09:19:07 +0000</pubDate>
      <link>https://dev.to/maheshmore2691/identity-server-4-with-net-core-app-4ih0</link>
      <guid>https://dev.to/maheshmore2691/identity-server-4-with-net-core-app-4ih0</guid>
      <description>&lt;p&gt;&lt;strong&gt;What is Identity Server?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Identity Server 4 (IdS4) is an OpenID Connect and OAuth 2.0 framework for .NET core application. It's an authentication service that provides you centralized authentication logic for different types of applications(Web, Mobile, or Services).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implement IdS4 in ASP.NET Core Web app&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;First, you need to create an empty ASP.NET Core web app using the below command.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dotnet new web&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;Alternatively, you can achieve the same from Visual Studio by choosing the &lt;code&gt;ASP.NET Core Web Application&lt;/code&gt; project using an empty template.&lt;/p&gt;

&lt;p&gt;Now, let's add IdS4 by installing the NuGet package.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dotnet add package IdentityServer4&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;You have successfully installed the IdS4 package, now open your project's &lt;code&gt;Startup.cs&lt;/code&gt; file and add the below code in &lt;code&gt;ConfigureServices()&lt;/code&gt; function. Please keep in mind that the below sample code is just referring to an empty list, so you need to make sure that you have a valid list of In-Memory resources and clients in your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddIdentityServer()
                .AddInMemoryClients(new List&amp;lt;Client&amp;gt;())
                .AddInMemoryApiResources(new List&amp;lt;ApiResource&amp;gt;())
                .AddInMemoryIdentityResources(new List&amp;lt;IdentityResource&amp;gt;())
                .AddInMemoryPersistedGrants()
                .AddTestUsers(new List&amp;lt;TestUser&amp;gt;())
                .AddDeveloperSigningCredential();
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above code will include IdS4 dependency and now you need to update &lt;code&gt;Configure&lt;/code&gt; method with below code snippet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {            
            app.UseHttpsRedirection();            
            app.UseIdentityServer();
        }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let's understand the configuration, we have added IdS4 dependency using &lt;code&gt;.AddIdentityServer()&lt;/code&gt; with default signing certificate using &lt;code&gt;.AddDeveloperSigningCredential()&lt;/code&gt; extension method. Then we have updated &lt;code&gt;Configure()&lt;/code&gt; method with &lt;code&gt;.UseIdentityServer()&lt;/code&gt; method here we are actually enabling OpenIdConnect endpoints. Please see below list of endpoints provided by IdS4:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;connect/token&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;connect/authorize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;connect/userinfo&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;connect/endsession&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;connect/revocation&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;connect/introspect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;connect/deviceauthorization&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can get a list of available endpoints using &lt;code&gt;/.well-known/openid-configuration&lt;/code&gt; endpoint.&lt;/p&gt;

&lt;p&gt;The above list of endpoints are provided by IdS4/OpenIdConnect/OAuth2 framework. In case you need your own endpoint for your business need, yes you can definitely create your custom endpoint!&lt;/p&gt;

&lt;p&gt;Follow below steps to add custom endpoint:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Register custom endpoint:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddIdentityServer(options =&amp;gt;
{
 //Adding custom endpoint in the discovery document          
 options.Discovery.ExpandRelativePathsInCustomEntries = true;
 options.Discovery.CustomEntries = new Dictionary&amp;lt;string, object&amp;gt;
             {
                { "myCustomEndpoint", "connect/myCustomEndpoint"}
              };
})
.AddEndpoint&amp;lt;MyCustomEndpoint&amp;gt;("myCustomEndpoint", "connect/myCustomEndpoint");
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Implement Handler:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The above code adds a custom endpoint in IdS4's endpoints, now you need to write a handler class for actual implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using IdentityServer4.Hosting;

public class MyCustomEndpoint : IEndpointHandler
    {
       public async Task&amp;lt;IEndpointResult&amp;gt; ProcessAsync(HttpContext 
                                                        context)
        {
         // ToDo: Here you can add your custom business-specific 
                  logic
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to use these endpoints?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use these endpoints to get &lt;code&gt;access/refresh/identity&lt;/code&gt; token from the IdS4 token provider, each endpoint serves a different purpose. e.g. &lt;code&gt;connect/authorize&lt;/code&gt; endpoint used in a public-facing application where you can use IdS4 login screen for authentication (using implicit &lt;a href="https://identityserver4.readthedocs.io/en/latest/topics/grant_types.html"&gt;grant type&lt;/a&gt;). Similarly &lt;code&gt;connect/token&lt;/code&gt; endpoint provides you access token programmatically (using password grant type).&lt;/p&gt;

&lt;p&gt;Request for &lt;code&gt;Password/ResourceOwner&lt;/code&gt; grant type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /connect/token

Headers:
Content-Type: application/x-www-form-urlencoded

Body:
grant_type=password&amp;amp;scope=api1&amp;amp;client_id=testClient&amp;amp;client_secret=testSecret&amp;amp;username=test.user&amp;amp;password=testPassword
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above request will provide you accessToken, so now you can use this access token to pass along with your REST API request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to protect your API using IdS4?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can protect your existing API or create a new one using &lt;code&gt;dotnet new webapi&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;To protect your API you need to install below NuGet package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet add package IdentityServer4.AccessTokenValidation
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This NuGet provides JWT and Reference token validation middleware, for reference token validation it provides caching as well. To validate your access token you will need to add below code in &lt;code&gt;ConfigureService&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddAuthentication("Bearer")
    .AddIdentityServerAuthentication("Bearer", options =&amp;gt;
    {
        options.ApiName = "api1";
        options.Authority = "https://localhost:44385";
    });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here &lt;code&gt;Authority&lt;/code&gt; is the IdentityServer4's URL and &lt;code&gt;ApiName&lt;/code&gt; is the &lt;code&gt;Audience&lt;/code&gt; from the access token and API resource name from IdS4 configuration.&lt;/p&gt;

&lt;p&gt;To add IdS4 authentication middleware you need to update your &lt;code&gt;Configure&lt;/code&gt; method with the below code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public void Configure(IApplicationBuilder app)
{
    app.UseAuthentication();
    app.UseAuthorization();
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you look at the business need Authenticated user isn't always authorized to access all resources. So to allow access to the authorized users you can implement &lt;a href="https://www.red-gate.com/simple-talk/dotnet/c-programming/policy-based-authorization-in-asp-net-core-a-deep-dive/"&gt;policy-based authorization&lt;/a&gt;. e.g. In case you have decided to authorize a user if the user's accessToken contains specific scope then you can create a simple policy using &lt;code&gt;.AddPolicy()&lt;/code&gt; method. You need to update the &lt;code&gt;ConfigureServices&lt;/code&gt; method with the below sample code.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Startup.cs&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services.AddAuthorization(option =&amp;gt;
            {
                option.AddPolicy("MyPolicy", p =&amp;gt;
               {
                   p.RequireAuthenticatedUser();
                   p.RequireClaim(JwtClaimTypes.Scope, 
                      new List&amp;lt;string&amp;gt;
                        {
                         "api1.read",
                         "api1.write:
                        }
                      );
               });
            });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Now your API is protected by IdS4 authentication provider, so any endpoint decorated with &lt;code&gt;[Authorize]&lt;/code&gt; attribute is protected. To call these REST endpoints you need to pass an accessToken using the &lt;code&gt;Authorization&lt;/code&gt; header.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/v1.0/getuser

Headers:
Authorization: Bearer &amp;lt;AccessToken&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note: We have implemented/integrated IdS4 in .Net project but we haven't introduced the user interface yet, so to add UI for the IdS4 project you can copy-paste code from &lt;a href="https://github.com/IdentityServer/IdentityServer4.Quickstart.UI"&gt;QuickStart&lt;/a&gt; folder.&lt;/p&gt;

&lt;p&gt;In this blog, I am using In-Memory clients and users, which is definitely not acceptable for a production app so you can use entity framework to update/get clients/users/resources from SQL DB or you can create your &lt;a href="https://www.scottbrady91.com/Identity-Server/Creating-Your-Own-IdentityServer4-Storage-Library"&gt;own storage library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

&lt;p&gt;Picture Source: &lt;a href="//identityserver4.readthedocs.io/en/latest/intro/terminology.html"&gt;Identity Server 4 docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>dotnet</category>
      <category>identityserver4</category>
      <category>tokenprovider</category>
    </item>
  </channel>
</rss>
