<?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: Ghassan Karwchan</title>
    <description>The latest articles on DEV Community by Ghassan Karwchan (@gkarwchan).</description>
    <link>https://dev.to/gkarwchan</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%2F134695%2Fa2999545-db1b-47c9-8877-b1417f964804.png</url>
      <title>DEV Community: Ghassan Karwchan</title>
      <link>https://dev.to/gkarwchan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gkarwchan"/>
    <language>en</language>
    <item>
      <title>Design and implement Git branching strategies for CI/CD integration</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sun, 22 Sep 2024 22:57:42 +0000</pubDate>
      <link>https://dev.to/gkarwchan/design-and-implement-git-branching-strategies-for-cicd-integration-b4o</link>
      <guid>https://dev.to/gkarwchan/design-and-implement-git-branching-strategies-for-cicd-integration-b4o</guid>
      <description>&lt;p&gt;Establishing a standardized development process that integrates a Git workflow with Continuous Integration/Continuous Deployment (CI/CD) is crucial before writing any code. This post will explore a widely-used approach: the Trunk-Based Development Workflow, which is adopted by many leading companies, including Microsoft.&lt;/p&gt;

&lt;h1&gt;
  
  
  Choosing a branching strategy:
&lt;/h1&gt;

&lt;p&gt;Every team should adopt a consistent code release process to maintain quality and reduce risks. This starts with selecting a Git workflow, continues through integrating CI/CD, and culminates in defining a release strategy.  &lt;/p&gt;

&lt;p&gt;In this post, we’ll focus on the Git workflow, starting with the basic steps of a typical release flow: creating branches, pushing changes, submitting pull requests, and merging code.  &lt;/p&gt;

&lt;p&gt;Choosing the right Git workflow for your team can significantly boost productivity. Consider the following when selecting the best strategy for your team:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scalability: Will this workflow scale as the team grows?&lt;/li&gt;
&lt;li&gt;Error Recovery: How easy is it to recover from mistakes?&lt;/li&gt;
&lt;li&gt;Overhead: How much additional work, such as resolving merge conflicts or waiting on CI/CD, will the workflow introduce?&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  What is Trunk-Based Development?:
&lt;/h1&gt;

&lt;p&gt;The core principle of &lt;a href="https://trunkbaseddevelopment.com/" rel="noopener noreferrer"&gt;Trunk-based Development Workflow&lt;/a&gt; is that all development work happens directly on the main branch (commonly called “trunk” or “master”). This method encourages continuous integration, with developers frequently committing small, incremental changes. Automated testing and integration play a pivotal role in maintaining high code quality.&lt;/p&gt;

&lt;p&gt;Notably, Microsoft uses this workflow internally, and it's a slight variation of the &lt;a href="https://docs.github.com/en/get-started/using-github/github-flow" rel="noopener noreferrer"&gt;GitHub flow&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branching:
&lt;/h3&gt;

&lt;p&gt;For every new feature or bug fix, a developer creates a dedicated branch. Once the work is complete, this branch will be merged into the trunk via a pull request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pull Request with review policies:
&lt;/h3&gt;

&lt;p&gt;After completing their work, developers submit a pull request (PR) to merge their branch into the trunk. Direct check-ins to the trunk are not permitted—merging must happen through a PR.&lt;/p&gt;

&lt;p&gt;To ensure code quality, additional policies can be enforced on PRs:&lt;/p&gt;

&lt;p&gt;Mandatory code reviews by other developers&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All PR comments must be resolved&lt;/li&gt;
&lt;li&gt;CI/CD builds must pass all tests (unit tests, code scanning) before merging&lt;/li&gt;
&lt;li&gt;This process safeguards the integrity of the codebase while maintaining a consistent flow of changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Releases and Release branches:
&lt;/h3&gt;

&lt;p&gt;When it’s time to release code to production, a &lt;code&gt;Release branch&lt;/code&gt; is created. This branch is then deployed to production.&lt;/p&gt;

&lt;p&gt;If a bug is found in production, the fix is made on the trunk using the same process: a bug-fix branch is created, a PR is submitted, and after merging into the trunk, the fix is &lt;code&gt;cherry-picked&lt;/code&gt; into the release branch for deployment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1m31k9ls0w72x77eqmis.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1m31k9ls0w72x77eqmis.png" alt="Branch Release" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(Image above courtesy for Microsoft Learn)&lt;/p&gt;

&lt;h3&gt;
  
  
  Branche policies and permissions:
&lt;/h3&gt;

&lt;p&gt;The Trunk-Based Development workflow allows for the enforcement of policies to enhance security, code quality, and team efficiency.&lt;/p&gt;

&lt;h5&gt;
  
  
  * Branch hierarchy and permissions
&lt;/h5&gt;

&lt;p&gt;A structured branch hierarchy can help maintain organization and control. For instance, user-created branches could reside in &lt;code&gt;/users&lt;/code&gt; or &lt;code&gt;/features&lt;/code&gt;, while release branches live under &lt;code&gt;/releases&lt;/code&gt;. Permissions can be set accordingly—only administrators would have the authority to create or modify release branches.&lt;/p&gt;

&lt;h5&gt;
  
  
  Enforcing Branch policies:
&lt;/h5&gt;

&lt;p&gt;To further ensure code quality, the following policies can be applied to the trunk and release branches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mandatory Code Reviews: Every PR must be approved by another developer before it can be merged.&lt;/li&gt;
&lt;li&gt;Successful Builds: CI processes ensure that a PR’s build passes unit tests or code scans before allowing a merge.&lt;/li&gt;
&lt;li&gt;CD Automation for Releases: Creating a release branch can trigger automated deployment to a pre-production environment, along with performance and stability checks.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>git</category>
    </item>
    <item>
      <title>Enhancing Your Git Workflow with Git Credential Manager Core</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sun, 22 Sep 2024 22:00:16 +0000</pubDate>
      <link>https://dev.to/gkarwchan/enhancing-your-git-workflow-with-git-credential-manager-core-gmp</link>
      <guid>https://dev.to/gkarwchan/enhancing-your-git-workflow-with-git-credential-manager-core-gmp</guid>
      <description>&lt;p&gt;Git’s credential helper is a handy tool that saves your credentials, so you won’t need to re-enter your username and password for every &lt;code&gt;git pull&lt;/code&gt; or &lt;code&gt;git push&lt;/code&gt;. However, depending on the age of the tutorial you're following and the platform you're using, the instructions for setting up credential storage may vary.&lt;/p&gt;

&lt;p&gt;In August 2021, GitHub introduced a new cross-platform tool called the &lt;a href="https://github.blog/open-source/git/git-credential-manager-core-building-a-universal-authentication-experience/" rel="noopener noreferrer"&gt;Git Credential Manager Core&lt;/a&gt;. Let’s explore how this tool can streamline your team’s workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before Git Credential Manager Core:
&lt;/h2&gt;

&lt;p&gt;Historically, Git offered several options for managing credentials, which you can see &lt;a href="https://git-scm.com/doc/credential-helpers" rel="noopener noreferrer"&gt;their list here&lt;/a&gt;, and we’ll briefly review:&lt;/p&gt;

&lt;h4&gt;
  
  
  Git Credential Store:
&lt;/h4&gt;

&lt;p&gt;Before &lt;code&gt;Git Credential Manager Core&lt;/code&gt;, the only cross-platform option was &lt;a href="https://git-scm.com/docs/git-credential-store" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;Git Credential Store&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;, which stores the credentials as plain-text.&lt;br&gt;&lt;br&gt;
With the rise of two-factor authentication (2FA), this method became obsolete since it could not handle 2FA.&lt;/p&gt;
&lt;h4&gt;
  
  
  Platform-Specific Encryption Store:
&lt;/h4&gt;

&lt;p&gt;Credential storage methods that used encryption were platform-specific, relying on the operating system’s native encryption capabilities. These included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git-credential-osxkeychain for Mac: which use Mac's keyChain to store the credentials.&lt;/li&gt;
&lt;li&gt;git-credential-libsecret for Linux: which use Linux secret service.&lt;/li&gt;
&lt;li&gt;git-credential-wincred for Windows: which use Windows Credential Manager.&lt;/li&gt;
&lt;li&gt;deprecated &lt;a href="https://github.com/microsoft/Git-Credential-Manager-for-Windows" rel="noopener noreferrer"&gt;Git Credential Manager for Windows&lt;/a&gt;: This tool was deprecated after the Core one was created, and it is no longer maintained.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Other special stores:
&lt;/h4&gt;

&lt;p&gt;There are two stores that are less used:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;git-credential-cache (not for windows): which stores the credential in memory for 15 minuntes.&lt;/li&gt;
&lt;li&gt;git-credential-oauth for Linux: which use OAuth authentication.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  The arrival of Git Credential Manager Core:
&lt;/h2&gt;

&lt;p&gt;As mentioned above, there wasn’t a single tool that could both encrypt credentials and work across all platforms—until &lt;a href="https://github.blog/open-source/git/git-credential-manager-core-building-a-universal-authentication-experience/" rel="noopener noreferrer"&gt;&lt;code&gt;Git Credential Manager Core&lt;/code&gt;&lt;/a&gt; was introduced. This tool addresses both of these needs: it's cross-platform and encrypts credentials securely.&lt;/p&gt;

&lt;p&gt;Although it was created by GitHub, it has since been adopted by the broader Git community and integrated into Git installations for Windows as well.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to set it up.
&lt;/h2&gt;

&lt;p&gt;If you installed git on your machinge with version 2.39 and later, then you installed that tool by default.&lt;br&gt;&lt;br&gt;
To know if you have that tool, check the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; credential.helper
&lt;span class="c"&gt;## the output depend on the version you use&lt;/span&gt;

&lt;span class="c"&gt;# for Git 2.38.1 on Windows , core was called manager-core&lt;/span&gt;
credential.helper&lt;span class="o"&gt;=&lt;/span&gt;manager-core

&lt;span class="c"&gt;# Git 2.39+ core replaced Windows manager and it took its name : manager&lt;/span&gt;
credential.helper&lt;span class="o"&gt;=&lt;/span&gt;manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the tool you are using is not one of the above, then you can change it as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For Git versions up to 2.38.1 on Windows, the credential helper was called manager-core&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; credential.helper manager-core

&lt;span class="c"&gt;# Starting from Git 2.39+, the helper was renamed to 'manager'&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; credential.helper manager
credential.helper&lt;span class="o"&gt;=&lt;/span&gt;manager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By configuring Git Credential Manager Core, you ensure a smoother, more secure authentication experience, freeing up time to focus on what matters most: coding.&lt;/p&gt;

</description>
      <category>git</category>
      <category>devops</category>
    </item>
    <item>
      <title>Are you still using git checkout for everything? It is time to switch to git switch</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sat, 21 Sep 2024 23:23:08 +0000</pubDate>
      <link>https://dev.to/gkarwchan/are-you-still-using-git-checkout-for-everything-it-is-time-to-switch-to-git-switch-1ecn</link>
      <guid>https://dev.to/gkarwchan/are-you-still-using-git-checkout-for-everything-it-is-time-to-switch-to-git-switch-1ecn</guid>
      <description>&lt;p&gt;If you're like me and still rely on the trusty git checkout for a variety of tasks—like switching branches, restoring files, and checking out commits—then you're in for a treat. The Git community has made things easier by introducing two new commands to split the workload: git switch and git restore.&lt;/p&gt;

&lt;p&gt;These new commands were created to reduce the overload on git checkout and make Git a bit more intuitive, especially for developers who sometimes found it confusing. Let's break it down!&lt;/p&gt;

&lt;h2&gt;
  
  
  What git checkout used to do
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;git checkout&lt;/code&gt; command was a Swiss Army knife in Git. It handled several different jobs, which could sometimes be confusing. With git checkout, you could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switching branches:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a new branch and switch to it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;new-branch-name&amp;gt;
&lt;span class="c"&gt;## or create a branch from a specific commit&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; &amp;lt;new-branch-name&amp;gt; &amp;lt;commit-hash&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Restoring files from the stage area
Files that were modified and added to staging area can be brought back to last
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &amp;lt;file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Restoring files from specific commit
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &amp;lt;commit-hash&amp;gt; &lt;span class="nt"&gt;--file&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Checking out the code to a specific commit or tag:
It is as well called &lt;code&gt;detached HEAD&lt;/code&gt;, because the &lt;code&gt;HEAD&lt;/code&gt; pointer will point to a specific commit instead of the latst commit in the current branch:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git checkout &lt;span class="o"&gt;(&lt;/span&gt;&amp;lt;commit-hash&amp;gt; | &amp;lt;tag-name&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why &lt;code&gt;checkout&lt;/code&gt; was so overloaded
&lt;/h2&gt;

&lt;p&gt;In Git, the branches tags and commit SHAs, all are under the hood the same thing, which they are &lt;code&gt;refs&lt;/code&gt; (or references) in the log history, so having one command to manage all does make sense technically. &lt;br&gt;
But from a developer workflow viewpoint (where branch is different than tag), bundling them into one command could cause confusion, especially for newer users. You might ask, "Why does git checkout work in some situations and not others?" For instance, sometimes it works with staged files, sometimes with uncommitted changes, and other times it doesn't unless you commit first.&lt;/p&gt;

&lt;p&gt;Because git checkout had to handle so many different tasks, the Git community decided to split its functionality. The command still works for backward compatibility, but now we have two specialized commands that simplify common tasks: git switch and git restore.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to simplify your Git workflow
&lt;/h2&gt;

&lt;p&gt;With Git 2.23, two new commands were introduced to ease the confusion: git switch for handling branches and git restore for managing files. These commands break down checkout's responsibilities and make Git operations clearer.&lt;/p&gt;
&lt;h4&gt;
  
  
  git switch
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;git switch&lt;/code&gt; is a command for switching branches.&lt;br&gt;&lt;br&gt;
So you have a command to switch to another branch&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch &amp;lt;branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or create a new branch from existing status&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git switch &lt;span class="nt"&gt;-c&lt;/span&gt; &amp;lt;new-branch-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  git restore
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;git restore&lt;/code&gt; is focusing on restoing files from specific commit, or disregard the changes in staging, or working area.&lt;br&gt;&lt;br&gt;
&lt;code&gt;restore&lt;/code&gt; will restore the files from &lt;code&gt;HEAD&lt;/code&gt; content, but without touching the index/stage area, but you can override that as we will describe down:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git restore &amp;lt;file&amp;gt;
&lt;span class="c"&gt;# or restore all files from HEAD content without touching index/stage area&lt;/span&gt;
&lt;span class="c"&gt;# to compare to checkout, which revert both working tree and stage area&lt;/span&gt;
git restore &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;span class="c"&gt;# to revert the changes in index/stage area only use the following override argument&lt;/span&gt;
git restore &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--staged&lt;/span&gt; 
&lt;span class="c"&gt;# to revert both working tree and stage area use&lt;/span&gt;
git restore &lt;span class="nt"&gt;--source&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;--staged&lt;/span&gt; &lt;span class="nt"&gt;--worktree&lt;/span&gt; &lt;span class="c"&gt;# this similar to git checkout .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you can restore to a specific commit&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git restore &lt;span class="nt"&gt;--source&lt;/span&gt; &amp;lt;commit-hash&amp;gt; &amp;lt;file&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;git checkout&lt;/code&gt; still works, switching to the new commands can make you Git workflow more intutive and less confusion. Branches, files, and commits are all just pointers in your Git history, but by using these specialized commands, you’ll reduce the mental load and avoid mistakes.&lt;/p&gt;

&lt;p&gt;Take a few minutes to familiarize yourself with these new commands—you’ll be glad you did!&lt;/p&gt;

</description>
      <category>git</category>
      <category>devops</category>
    </item>
    <item>
      <title>How Single Page Application call a secure your API with OAuth2.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sat, 06 Jan 2024 04:43:07 +0000</pubDate>
      <link>https://dev.to/gkarwchan/how-single-page-application-call-a-secure-your-api-with-oauth2-1079</link>
      <guid>https://dev.to/gkarwchan/how-single-page-application-call-a-secure-your-api-with-oauth2-1079</guid>
      <description>&lt;p&gt;Public SPA challenge when it comes to use OAuth 2.0, is you cannot store any type of secrets of credentials in your code. This is why OAuth provided a special flow to be used by SPA: Authorization Code Grant &amp;amp; PKCE. We are going to describe this flow in details here.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Summary of the process:
&lt;/h2&gt;

&lt;p&gt;To describe the flow briefly, when the SPA requires to get a token it will direct the application to an Authorization Server (AS), which will use that server login page and UI, and the user will run the login process on the AS server website, then that server will return back to the original client website using a callback url passing the token to the SPA.&lt;br&gt;&lt;br&gt;
So the client SPA has no idea about the credentials and the client cannot intercept those credentials because the login run on Authorization Server website.  &lt;/p&gt;

&lt;p&gt;Let us imagine we have this setup and see how we will do that. I am going to use Auth0 service as an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ifhtmi0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgdd12gtmk4lnuegbxaj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ifhtmi0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wgdd12gtmk4lnuegbxaj.jpg" alt="The application we are going to implement" width="681" height="321"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  How to configure Auth0
&lt;/h2&gt;

&lt;p&gt;Before we start writing code, we should configure our API and our SPA application on Auth0.&lt;br&gt;&lt;br&gt;
I am not going to show the details on how to do it in Auth0, and assume you know how to do it.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create an API in Auth0, and configure its audience to be something like : &lt;code&gt;https://myapiserver.com"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Create an SPA application and get its &lt;code&gt;Client Id&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;From Auth0 we need two values:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the audience you used to create the API.&lt;/li&gt;
&lt;li&gt;the Client Id for the SPA application.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Details of the OAuth Authorization Code flow:
&lt;/h2&gt;

&lt;p&gt;Here are the steps to achieve getting token from Authorization Code flow.&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 1: call authorize endpoint
&lt;/h3&gt;

&lt;p&gt;The process start when the SPA application will find it needs a token to access the remote resource, so it start the process by navigating to the Authorize end point: &lt;code&gt;https://&amp;lt;your-tenant-id&amp;gt;.us.auth0.com/authorize&lt;/code&gt; passing the following information to this end point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /authorize?
response_type=code
&amp;amp; client_id=&amp;lt;client_id&amp;gt;
&amp;amp; state=&amp;lt;state&amp;gt;
&amp;amp; scope=&amp;lt;scope&amp;gt;
&amp;amp; redirect_uri=&amp;lt;callback uri&amp;gt;
&amp;amp; resource=&amp;lt;API identifier&amp;gt;
&amp;amp; code_challenge=&amp;lt;PKCE code_challenge&amp;gt;
&amp;amp; code_challenge_method=S256 HTTP/1.1
Host: authorizationserver.com
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The parameters are as follows:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;client_id: it is the application (SPA) you create on Auth0.&lt;/li&gt;
&lt;li&gt;audience: is the audience used in configuring API in Auth0. Other OAuth providers use the term &lt;code&gt;resource&lt;/code&gt; instead of audience, but it play the same function.&lt;/li&gt;
&lt;li&gt;redirect_uri: the callback URL to your application. This call back should be one of the allowed url registered in your SPA Auth0 application.&lt;/li&gt;
&lt;li&gt;scope: this setting could be use to define the scope or permissions requested by the client. In OpenID Connect it can be only the value &lt;code&gt;openid profile&lt;/code&gt;, and in OAuth 2.0 usually it is the list: &lt;code&gt;openid profile email offline_access&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;response_type: should be "code" because Authorization Code flow * response_mode: should be "query" which means the code will return as query parameter.&lt;/li&gt;
&lt;li&gt;code_challenge: a value generated by PKCE code verifier to protect the code.
code_challenge_method: S256, it is the recommended encryption to use.&lt;/li&gt;
&lt;li&gt;state: is an encrypted auto-generated string used to track calls during authorization process.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2:
&lt;/h3&gt;

&lt;p&gt;The Authorization Server find there is no valid token for this session, so it redirect it to its own login UI page:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /login?state=&amp;lt;state&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3:
&lt;/h3&gt;

&lt;p&gt;You provide your credentials in the login screen, and the Authorization server might take you to a consent page.&lt;br&gt;&lt;br&gt;
After &lt;code&gt;Submit&lt;/code&gt; login, the page will do a post call to login as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /login?state=&amp;lt;state&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the post there is a form of the credentials:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;username&lt;/li&gt;
&lt;li&gt;password&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 4:
&lt;/h3&gt;

&lt;p&gt;The Authorization server will call back your SPA with the callback url you provided with the code as query parameter&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;302&lt;/span&gt; &lt;span class="ne"&gt;Found&lt;/span&gt;
&lt;span class="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://clientapplication.com/callback?&lt;/span&gt;
&lt;span class="s"&gt;code=&amp;lt;authorization code&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;&amp;amp; state=&amp;lt;state&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Last Step Step 5: generate token
&lt;/h3&gt;

&lt;p&gt;Last step is you call the Authorization Server &lt;code&gt;token&lt;/code&gt; endpoint with &lt;code&gt;POST&lt;/code&gt; with the authorization code that generated from pervious step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;POST&lt;/span&gt; &lt;span class="nn"&gt;/token&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;&amp;lt;auth0 tenant authorization url&amp;gt;&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/x-www-form-urlencoded&lt;/span&gt;
&lt;span class="s"&gt;grant_type=authorization_code&lt;/span&gt;
&lt;span class="s"&gt;&amp;amp; code=&amp;lt;authorization_code&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;&amp;amp; client_id=&amp;lt;client id&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;&amp;amp; code_verifier=&amp;lt;code verifier&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;&amp;amp; redirect_uri=&amp;lt;callback URI&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server will response with json with the token and refresh token, and maybe id_token (in case of OpenID Connect):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"access_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;refresh token&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"token_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bearer"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"expires_in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;token&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;expiration&amp;gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"refresh_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;refresh_token&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"id_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;id token&amp;gt;"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="nl"&gt;"scope"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openid profile email"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>http</category>
      <category>oauth2</category>
      <category>security</category>
    </item>
    <item>
      <title>Calling HTTP API and the problem of Socket exhaustion and DNS rotation.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sat, 06 Jan 2024 00:00:46 +0000</pubDate>
      <link>https://dev.to/gkarwchan/calling-http-api-and-the-problem-of-socket-exhaustion-and-dns-rotation-555d</link>
      <guid>https://dev.to/gkarwchan/calling-http-api-and-the-problem-of-socket-exhaustion-and-dns-rotation-555d</guid>
      <description>&lt;p&gt;You definitely had to write code to communicate to an API service. Regardless of the language you use, or the framework you use, there is a two major problems when you want to do lots of calls. They are:   &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Socket Exhaustion&lt;/li&gt;
&lt;li&gt;DNS Rotation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I am going to use C# and ASP.NET as an example and show you what .NET world has a solution for that, but there are solutions in every language and framework.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Calling an API end point.
&lt;/h2&gt;

&lt;p&gt;Let us start from beginning, how to call an API service.  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HttpClient&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;baseAddress&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;api endpoint&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
     &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnsureSuccessStatusCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
     &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAsStringAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Let's explain what we are doing:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;wrap the HttpClient in &lt;code&gt;using&lt;/code&gt; statement, so it disposed at the end of the block.&lt;/li&gt;
&lt;li&gt;set the base address.&lt;/li&gt;
&lt;li&gt;make a call.&lt;/li&gt;
&lt;li&gt;Throw an exception of the request is not successful.&lt;/li&gt;
&lt;li&gt;extract the result.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How Http communication work?
&lt;/h2&gt;

&lt;p&gt;Let's explore the underlying protocol that implement the HTTP call.&lt;br&gt;&lt;br&gt;
When a computer needs to send a request to HTTP server, it creates a connection between the computer itself and the server.&lt;br&gt;&lt;br&gt;
To open a connection the computer needs to open a port with a random number between 0 and 65,535 and connects to the server's IP address and port. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjcrahe1bjf76ry4nrqx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjcrahe1bjf76ry4nrqx.jpg" alt="Image that show how sockets works"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The combination of the computer IP address and port is called &lt;strong&gt;&lt;code&gt;Socket&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The problem with above code is even you dispose the Http client, but the underlying connection won't be disposed immediately, and the port won't be release right away.&lt;br&gt;&lt;br&gt;
In Http protocol, when a connection disposed, it will stays in &lt;strong&gt;&lt;code&gt;TIME_WAIT&lt;/code&gt;&lt;/strong&gt; status for 240 seconds (4 minutes).  &lt;/p&gt;

&lt;p&gt;With lots of calls you might use all the ports on the client computer, which lead to the application will hang waiting for a port to be released.&lt;br&gt;&lt;br&gt;
That situation is called &lt;strong&gt;&lt;code&gt;Socket Exhaustion&lt;/code&gt;&lt;/strong&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Fixing Socket Exhaustion
&lt;/h2&gt;

&lt;p&gt;So what if we introduce one instance of Http Client (that is using only one random port), and keep it alive, and re-use it for all calls?&lt;br&gt;&lt;br&gt;
This will solve the problem of &lt;code&gt;Socket Exhaustion&lt;/code&gt;, but we introduce another problem.&lt;br&gt;&lt;br&gt;
When we call an API endpoint which has the address: &lt;code&gt;https://www.myapiservice.com/api/myendpint&lt;/code&gt;, the HttpClient will first call the &lt;code&gt;DNS&lt;/code&gt; servers to translate "myapiservice.com" to an IP address.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91ryv637vw4oqc38ooj0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F91ryv637vw4oqc38ooj0.jpg" alt="Image shows how DNS get called"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HttpClient will keep the connection open to that IP address.&lt;br&gt;&lt;br&gt;
But what the IP changed in the DNS server?&lt;br&gt;&lt;br&gt;
If that API was hosted in on-promise company computer then this might not happen a lot.&lt;br&gt;&lt;br&gt;
But on the cloud, IP address are not that stable (unless you specifically configure it to be like that).&lt;br&gt;&lt;br&gt;
By default cloud, and Kubernetes deals with the outside world with domain names, and they have their private DNS to resolve the IP resolving. Again the administrators could be using reserved IP address, but by default they are not. &lt;br&gt;
Any scale up on cloud PaaS, or even new deployment might change the IP.&lt;br&gt;&lt;br&gt;
Having one HttpClient, will keep the old IP address that was detected on the first call.  &lt;/p&gt;

&lt;h2&gt;
  
  
  How .NET core fixed the problem?
&lt;/h2&gt;

&lt;p&gt;.NET fixed the problem by introducing a feature called &lt;strong&gt;&lt;code&gt;IHttpClientFactory&lt;/code&gt;&lt;/strong&gt; in Core version 2.1. &lt;/p&gt;

&lt;h3&gt;
  
  
  How IHttpClientFactory solved the problem?
&lt;/h3&gt;

&lt;p&gt;HttpClient internally is creating a connection and doing the calls using a class in .NET called &lt;strong&gt;&lt;code&gt;SocketsHttpHandler&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The real work of establishing a connection is happening inside &lt;code&gt;SocketsHttpHandler&lt;/code&gt; , and the disposing of this handler that will take &lt;strong&gt;&lt;code&gt;Time_WAIT&lt;/code&gt;&lt;/strong&gt; for 4 minutes to be really released.  &lt;/p&gt;

&lt;p&gt;HttpClientFactory uses an internal class called &lt;code&gt;HttpClientHandler&lt;/code&gt;, and it is the same as &lt;code&gt;SocketsHttpHanlder&lt;/code&gt;, which might be confusing, so before we talk what HttpClientFactory is doing, let us explain the difference.  &lt;/p&gt;

&lt;h4&gt;
  
  
  HttpClientHandler vs. SocketsHttpHandler:
&lt;/h4&gt;

&lt;p&gt;HttpClientHandler was the old handler that HttpClient uses to do the real http communication. After version Core 2.1, the SocketsHttpHanlder was introduced, and HttpClient started using the new handler, but HttpClientFactory kept using the old handler HttpClientHandler.&lt;br&gt;&lt;br&gt;
But in Core 5.0, HttpClientHandler &lt;a href="https://github.com/dotnet/runtime/blob/f518b2e533ba9c5ed9c1dce3651a77e9a1807b8b/src/libraries/System.Net.Http/src/System/Net/Http/HttpClientHandler.cs#L16" rel="noopener noreferrer"&gt;was changed to use SocketsHttpHanlder internally&lt;/a&gt;. So in reality they are the same, and when you are talking about Core version 5.0 and later both are the same which is SocketsHttpHandler.  &lt;/p&gt;

&lt;p&gt;If you read about IHttpClientFactory you will read that it is using an internal class called HttpClientHandler, and that might create confusion.  &lt;/p&gt;

&lt;p&gt;So back to our question how HttpClientFactory fixed the problmes?&lt;br&gt;&lt;br&gt;
&lt;code&gt;IHttpClientFactory&lt;/code&gt; will create an internal pool of  &lt;code&gt;HttpClientHandler&lt;/code&gt; and keep them and passing them when create &lt;code&gt;HttpClient&lt;/code&gt;. So when create or dispose &lt;code&gt;HttpClient&lt;/code&gt;, &lt;code&gt;IHttpClientFactory&lt;/code&gt; is using &lt;code&gt;HttpClientHandler&lt;/code&gt; from its pool.&lt;br&gt;&lt;br&gt;
&lt;code&gt;IHttpClientFactory&lt;/code&gt; rotate between the &lt;code&gt;HttpClientHandler&lt;/code&gt; in the pool every 2 minutes (the half time of &lt;strong&gt;&lt;code&gt;WAIT_TIME&lt;/code&gt;&lt;/strong&gt;).&lt;br&gt;&lt;br&gt;
For 2 minutes &lt;code&gt;IHttpClientFactory&lt;/code&gt; uses one &lt;code&gt;HttpClientHandler&lt;/code&gt; to create all &lt;code&gt;HttpClient&lt;/code&gt; during that 2 minutes.&lt;br&gt;&lt;br&gt;
And after 2 minutes, it switch to another handler, and dispose the previous handler and recreate it and add it back to the pool.&lt;br&gt;&lt;br&gt;
A new &lt;code&gt;HttpClientHandler&lt;/code&gt; will create new connections, which means new &lt;code&gt;DNS&lt;/code&gt; calls, and getting it latest IP addresses.&lt;br&gt;&lt;br&gt;
This technique solves both the problems of &lt;code&gt;Socket Exhaustion&lt;/code&gt; and &lt;code&gt;DNS rotation&lt;/code&gt;.  &lt;/p&gt;

&lt;h2&gt;
  
  
  How to use IHttpClientFactory:
&lt;/h2&gt;

&lt;p&gt;In ASP.NET Core, you need to add &lt;code&gt;IHttpClientFactory&lt;/code&gt; as a singleton in configuring services:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHttpClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And then you can use it to create HttpClient:  &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IHttpClientFactory&lt;/span&gt; &lt;span class="n"&gt;_factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyController&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IHttpClientFactory&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_factory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"getdata"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.myapiservices.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;end point&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnsureSuccessStatusCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAsStringAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Dealing with different Http client configurations
&lt;/h2&gt;

&lt;p&gt;What if you want to use different Http Client configurations with different services, and to re-use those configurations?&lt;br&gt;&lt;br&gt;
ASP.NET gives two options to re-use the same configurations:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Named Http Client&lt;/li&gt;
&lt;li&gt;Typed Http Client&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Named HttpClient
&lt;/h3&gt;

&lt;p&gt;You to configure Named Http Client, where you can store custom configuration&lt;br&gt;
In ConfigureServices part:   &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddHttpClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mycustomClient"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; 
         &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://www.myapiservices.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultRequestHeaders&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;HeaderNames&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UserAgent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mycustomagent"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureHttpClient&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="n"&gt;custom&lt;/span&gt; &lt;span class="n"&gt;configuration&lt;/span&gt; &lt;span class="p"&gt;...})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ConfigureHttpClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
       &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceProvider&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;How to use that?&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;


&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IHttpClientFactory&lt;/span&gt; &lt;span class="n"&gt;_factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyController&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IHttpClientFactory&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_factory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"getdata"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mycustomClient"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;end point&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnsureSuccessStatusCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAsStringAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



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

&lt;/div&gt;
&lt;h4&gt;
  
  
  Typed Http Client
&lt;/h4&gt;

&lt;p&gt;Another way is to use Typed Http Client, which are classed that inject Http Client as follows:   &lt;/p&gt;

&lt;p&gt;First create a class that inject HttpClient and configure it&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyFinancialClient&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IMyFinancialClient&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyFinancialClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;HttpClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="n"&gt;_client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
       &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BaseAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://myapiservices.com"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetFinancialData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; 
   &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"financialEndPoint"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
       &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnsureSuccessStatusCode&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAsString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;And you register the class &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHttpClient&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyFinancialClient&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;



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

&lt;/div&gt;

&lt;p&gt;And then use it&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ApiController&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyController&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ControllerBase&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;MyFinancialClient&lt;/span&gt; &lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyController&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyFinancialClient&lt;/span&gt; &lt;span class="n"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;HttpGet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"getdata"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetFinancialData&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

</description>
      <category>httpclient</category>
      <category>aspnetcore</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>OAuth, OpenID Connect, SSO and Authentication Flows in plain English.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sat, 28 Oct 2023 04:31:31 +0000</pubDate>
      <link>https://dev.to/gkarwchan/oauth-openid-connect-sso-and-authentication-flows-in-plain-english-29nb</link>
      <guid>https://dev.to/gkarwchan/oauth-openid-connect-sso-and-authentication-flows-in-plain-english-29nb</guid>
      <description>&lt;p&gt;Gone are the days when you force your users to register into your application by creating username/password.&lt;br&gt;
Everyone wants to skip that process when they can identify themselves using other ways (google, facebook, twitter…), and they want to use their single sign on process to identify them across multiple applications and multiple websites.&lt;br&gt;
In this post I am trying to explain the process and its technologies in simple English.&lt;/p&gt;

&lt;h2&gt;
  
  
  An explanation by example:
&lt;/h2&gt;

&lt;p&gt;So you are a developer who is building an application and want to allow your users to use their Google credentials to authenticate themselves into your account.&lt;br&gt;
I am going to explain to you the concepts and the technologies.  &lt;/p&gt;

&lt;p&gt;To accomplish that, your application must make a request to some API service on the Google Account website in order to initiate the user authentication process and receive a response that identifies the user.&lt;br&gt;
The Google Account website is the only place where the authentication process should run, and where the user enter their credentials. And Google authentication service should ensures that the credentials are safe and hidden from our application.  &lt;/p&gt;

&lt;p&gt;The process of using an external server to sign-on and using its returning identity in different applications is called &lt;strong&gt;&lt;code&gt;Single Sign-On (SSO)&lt;/code&gt;&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Google Account website stores information about the user who did previously register into Google Account website. The digital information that uniquely identifies a user on Google Account website and shared on other websites and domains is known as &lt;strong&gt;&lt;code&gt;Federated Identity&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
The Google Account website has to provide API services that will achieve that process, and these services must use common protocols and policies that are understood by our application and Google Account. These protocols and policies are called &lt;strong&gt;&lt;code&gt;Federated Identity Management (FIdM)&lt;/code&gt;&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Google Account is the provider that provides Authentication service to identify users, and return their Federated Identities, and the technical terms for it is: &lt;strong&gt;&lt;code&gt;Federated Identity Provider&lt;/code&gt;&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Our application will be the consumer or the client for &lt;strong&gt;&lt;code&gt;FIdM&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;
There are many different Federated Identity Providers: Google, Microsoft, Twitter, Facebook…etc. They all provide these FIdM services for industry standard protocols.&lt;/p&gt;

&lt;h2&gt;
  
  
  What technologies and protocols are used?
&lt;/h2&gt;

&lt;p&gt;There are three technologies that provide FIdM services:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;SAML&lt;/strong&gt; (Security Assertion Markup Language):  It is the oldest technology, and although it is limited used now but still kicking around.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OAuth 2.0&lt;/strong&gt;: the most common one, because it is implemented by all providers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenID Connect&lt;/strong&gt;: is it built on top of OAuth but it cut lots of extra stuff and concentrate on authentication. &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How they are different?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  SAML , and WS-Federation:
&lt;/h4&gt;

&lt;p&gt;SAML was the oldest one, and is used mainly for web applications and mostly internal web applications. It uses XML to communicate to the Identity providers. SAML was developed when calling external services was done using SOAP (an old protocol from web services). &lt;br&gt;
Interesting to note that an approach to make better SAML was initiated and was called &lt;strong&gt;&lt;code&gt;WS-Federation&lt;/code&gt;&lt;/strong&gt; but then later REST and HTTP replaced SOAP, and JSON replaced XML, and SAML/WS-Federation became less and less used.&lt;br&gt;&lt;br&gt;
SAML only returns a digital identity called &lt;strong&gt;&lt;code&gt;SAML Assertion&lt;/code&gt;&lt;/strong&gt; to identify the user. The &lt;code&gt;SAML Assertion&lt;/code&gt; is very simple and it is the simplest representation of the user.  &lt;/p&gt;

&lt;h4&gt;
  
  
  OAuth 2.0:
&lt;/h4&gt;

&lt;p&gt;Although OAuth is used as one of FIdM technologies, but it wasn't mainly built for that purpose.&lt;br&gt;
With the rising of social media and the wealth of its data, social media companies wanted to provide its data and share user data across the applications.&lt;br&gt;
They provided more sophisticated protocols to share user information and allow users to choose what information they want to share, and this is how OAuth 2.0 was built.&lt;/p&gt;

&lt;p&gt;Because OAuth 2.0 needed to identify the users on their own social media servers, so it has the SSO features of FIdM, beside it added more features to allow users to chose what information they want to share.&lt;br&gt;&lt;br&gt;
For example on google we all saw this when using google login.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CeXyHqbm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngm47aure1o2jr0ta3ac.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CeXyHqbm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngm47aure1o2jr0ta3ac.png" alt="Image description" width="443" height="527"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you see that OAuth has more that SSO and FIdM, but it built very good technologies and protocols, and this is why OpenID came up to life.&lt;/p&gt;

&lt;h4&gt;
  
  
  OpenID Connect:
&lt;/h4&gt;

&lt;p&gt;Because OAuth had good technologies and standards to achieve SSO and FIdM, but has way more of Authorization and sharing information, the industry built a new standard that use OAuth technologies but concentrate only on the Authentication process and cut out the authorization, and it only share the basic data that uniquely identify the user. This new standard is OpenID Connect 1.0.&lt;br&gt;
OpenID Connect uses lots of common technologies with OAuth, that is sometimes it get confused.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the process works?
&lt;/h2&gt;

&lt;p&gt;OAuth created many workflows each work better for a specific type of applications. OAuth called these workflows: &lt;strong&gt;&lt;code&gt;Flows&lt;/code&gt;&lt;/strong&gt; &lt;br&gt;
OpenID still using these flows but slightly modified them. So understand them with OAuth is the same as OpenID.&lt;br&gt;
We can define these types of applications:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Website application that serve its own UI.&lt;/li&gt;
&lt;li&gt;Single Page Application (SPA), where the client is a thick JavaScript application that can be hosted on any place, and it called different API application.&lt;/li&gt;
&lt;li&gt;Mobile native APP.&lt;/li&gt;
&lt;li&gt;Local desktop App.
Each type has its matching OAuth &lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Application Type&lt;/th&gt;
&lt;th&gt;OAuth Flow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Web application&lt;/td&gt;
&lt;td&gt;Authorization Flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SPA&lt;/td&gt;
&lt;td&gt;the Authorization Code Flow with Proof Key for Code Exchange (PKCE) &lt;br&gt; Implicit Flow used to be the one but not any more&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local Desktop App&lt;/td&gt;
&lt;td&gt;Client Credential Flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Native mobile APP&lt;/td&gt;
&lt;td&gt;the Authorization Code Flow with Proof Key for Code Exchange (PKCE)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;Hopefully I was able to explain these technical terms and technologies in simple plain Engligh.&lt;/p&gt;

</description>
      <category>security</category>
      <category>sso</category>
      <category>oauth</category>
      <category>openid</category>
    </item>
    <item>
      <title>Best way to run background services in ASP.NET.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Thu, 13 Jul 2023 01:27:21 +0000</pubDate>
      <link>https://dev.to/gkarwchan/best-way-to-run-background-services-in-aspnet-1h6n</link>
      <guid>https://dev.to/gkarwchan/best-way-to-run-background-services-in-aspnet-1h6n</guid>
      <description>&lt;p&gt;Asp.Net provides many ways to run background processes. They are:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IHostedService interface&lt;/li&gt;
&lt;li&gt;BackgroundService abstract class&lt;/li&gt;
&lt;li&gt;Worker Service using Microsoft.NET.SDK.Worker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Actually they are just layers on top of each others, each layer provides extra functionality on the one below.&lt;br&gt;&lt;br&gt;
This post is going to describe each layer and what it provides.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Running background tasks using &lt;code&gt;IHostedService&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Asp.NET provides support for running background tasks in the same process that host Asp.net application.&lt;br&gt;&lt;br&gt;
By implementing &lt;code&gt;IHostedService&lt;/code&gt; interface, your background task will start a little bit after Asp.Net application start, and end when Asp.Net application shutdown.  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;P.S.: Asp.NET core server, Kestrel itself is a hosted service.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;IHostedService has two methods:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IHostedService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StartAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StopAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After you implement the interface, you need to register the task, and register it with the DI container. Asp.NET provides &lt;code&gt;AddHostedService&lt;/code&gt; extension method on &lt;code&gt;IServiceCollection&lt;/code&gt; for that purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ConfigureServices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceCollection&lt;/span&gt; &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddHostedService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;MyExampleService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Using &lt;strong&gt;scoped&lt;/strong&gt; services in the background task:
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;AddHostedService&lt;/code&gt; is doing registering the service as Singleton in the DI container.&lt;br&gt;&lt;br&gt;
That leads to a problem if you need to use services registered as scoped-lifetime services.&lt;br&gt;&lt;br&gt;
To fix this problem, create a new container scope anywhere you need access to scoped service, as the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyExampleService&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IHostedService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IServiceProvider&lt;/span&gt; &lt;span class="n"&gt;_provider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyExampleService&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceProvider&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_provider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt; &lt;span class="nf"&gt;StartAsync&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CancellationToken&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IServiceScope&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateScope&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
     &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;scopedProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
         &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scopeProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ExampleScopedService&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
         &lt;span class="p"&gt;...&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Guidelines on IHostedService
&lt;/h4&gt;

&lt;p&gt;There are subtleties to implementing the interface correctly. In particular, the &lt;code&gt;StartAsync&lt;/code&gt; method, although asynchronous, runs inline as part of your application startup. Background tasks that are expected to run for the lifetime of your application must return a Task immediately and schedule background work on a different thread. Calling await in the &lt;code&gt;IHostedService.StartAsync&lt;/code&gt; method will block your application from starting until the method completes. This can be useful in some cases, but it’s often not the desired behavior for background tasks.  &lt;/p&gt;

&lt;h2&gt;
  
  
  BackgroundService
&lt;/h2&gt;

&lt;p&gt;To make it easier to create background services using best-practice patterns, ASP.NET Core provides the abstract base class &lt;code&gt;BackgroundService&lt;/code&gt;, which implements &lt;code&gt;IHostedService&lt;/code&gt; and is designed to be used for long-running tasks. To create a background task you must override a single method of this class, &lt;code&gt;ExecuteAsync&lt;/code&gt;. You’re free to use async-await inside this method, and you can keep running the method for the lifetime of your app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Worker Service
&lt;/h2&gt;

&lt;p&gt;.NET provides a special kind of application called &lt;code&gt;Worker Service&lt;/code&gt;, which runs IHostedService in a host that is lighter than Asp.NET host.&lt;br&gt;&lt;br&gt;
That lighter host is &lt;code&gt;Microsoft.Extensions.Hosting.Host&lt;/code&gt;, which is a general host that is hosting the Asp.Net WebApplication itself.&lt;br&gt;&lt;br&gt;
&lt;a href="https://www.ghassan.page/posts/2022_12_19_aspnet_minimal_api/" rel="noopener noreferrer"&gt;I wrote before&lt;/a&gt; about the relation between Host and WebApplication.&lt;br&gt;&lt;br&gt;
The worker service's &lt;code&gt;Host&lt;/code&gt; will run background service, but doesn't handle HTTP request. It has the following:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;configuration features.&lt;/li&gt;
&lt;li&gt;logging features.&lt;/li&gt;
&lt;li&gt;dependency injection features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To use Worker Service, run the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new worker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a &lt;strong&gt;&lt;code&gt;BackgroundService&lt;/code&gt;&lt;/strong&gt; class, that is hosted in &lt;strong&gt;&lt;code&gt;Microsoft.Extensions.Hosting.Host&lt;/code&gt;&lt;/strong&gt;, which is an implementation of &lt;strong&gt;&lt;code&gt;IHost&lt;/code&gt;&lt;/strong&gt; which what we described as a lightweight host.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Running Worker Service in production
&lt;/h2&gt;

&lt;p&gt;You can run Worker Service as a Windows Service, or Linux's Systemd service.  &lt;/p&gt;

</description>
      <category>aspnet</category>
    </item>
    <item>
      <title>build resilient applications accessing Azure services with no code.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sun, 12 Mar 2023 02:08:54 +0000</pubDate>
      <link>https://dev.to/gkarwchan/build-resilient-applications-accessing-azure-services-with-no-code-48hn</link>
      <guid>https://dev.to/gkarwchan/build-resilient-applications-accessing-azure-services-with-no-code-48hn</guid>
      <description>&lt;p&gt;When working on distributed system like systems that are running on the cloud, and microservices, then you should anticipate transient faults like temporary loss of network connection, or temporary unavailability of a service, or a service is busy.&lt;br&gt;&lt;br&gt;
This is why in cloud application, the term &lt;strong&gt;Building for resiliency&lt;/strong&gt; become a pattern in building application, and it means properly handling these transient faults in the code.  &lt;/p&gt;

&lt;p&gt;There are two common used patterns that we can use in our code, that can help build resilience application.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retry pattern.&lt;/li&gt;
&lt;li&gt;Circuit-breaker Pattern.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The good news is there are libraries that will help you doing that, and even the SDKs for some Azure services have these two patterns built-in, and by just configure the connection properly you will get this benefits without writing your own code for those.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Retry Pattern
&lt;/h2&gt;

&lt;p&gt;The retry pattern means if calling a service failed, you wait for a short time, and then retry again because you expect the problem will be resolved shortly. You try not only one time, but maybe for 3 times, and leave a short waiting time between the retries.  &lt;/p&gt;
&lt;h4&gt;
  
  
  Services that support retry.
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Azure SQL Server, and Entity Framework:
Entity Framework has a built-in retry technique when it comes to communicate with Azure SQL Server.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddDbContextPool&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ConcertDataContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UseSqlServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sqlDatabaseConnectionString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;sqlServerOptionsAction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;sqlOptions&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;sqlOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EnableRetryOnFailure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="n"&gt;maxRetryCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="n"&gt;maxRetryDelay&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;errorNumbersToAdd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Azure Cache for Redis
If you are using the most famous Redis .NET library which is &lt;strong&gt;&lt;code&gt;StackExchange.Redis&lt;/code&gt;&lt;/strong&gt;, then the library has the mechanism for retry as follows:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ConfigurationOptions&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;EndPoints&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"localhost"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;ConnectRetry&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ReconnectRetryPolicy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ExponentialRetry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;TotalMilliseconds&lt;/span&gt;
&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;TotalMilliseconds&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;ConnectTimeout&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2000&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;ConnectionMultiplexer&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConnectionMultiplexer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Azure Service Bus
The .NET package for the service bus &lt;strong&gt;&lt;code&gt;Azure.Messaging.ServiceBus&lt;/code&gt;&lt;/strong&gt; has built-in support for retry using the configuration of its client.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ServiceBusClientOptions&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RetryOptions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;ServiceBusRetryOptions&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Delay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;MaxDelay&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Mode&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ServiceBusRetryMode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exponential&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;MaxRetries&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ServiceBusClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  More Azure service support retry
&lt;/h4&gt;

&lt;p&gt;I am not going to list the code for all services, but just check the SDK for each service, and you will find how to enable the retry features. But these services will support the feature: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Azure Cosmos DB&lt;/li&gt;
&lt;li&gt;Azure Active Directory&lt;/li&gt;
&lt;li&gt;Azure Search&lt;/li&gt;
&lt;li&gt;Event Hub&lt;/li&gt;
&lt;li&gt;IoT Hub&lt;/li&gt;
&lt;li&gt;Azure Storage&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Retry using Polly
&lt;/h4&gt;

&lt;p&gt;If you need to connect to other API services, or you need to connect to Azure SQL but without Entity Framework, then you need to implement the code yourself.&lt;br&gt;&lt;br&gt;
But there is a .NET package that is already doing that: &lt;a href="https://github.com/App-vNext/Polly"&gt;&lt;strong&gt;&lt;code&gt;Polly&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Let us see for example how to connect to SQL using ADO.NET and Polly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SqlDataReader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;ExecuteReaderWithRetryAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="n"&gt;SqlCommand&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;GuardConnectionIsNotNull&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;().&lt;/span&gt;&lt;span class="nf"&gt;WaitAndRetryAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;retryCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Retry 3 times&lt;/span&gt;
        &lt;span class="n"&gt;sleepDurationProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromMilliseconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="c1"&gt;// Exponential backoff based on an initial 200 ms delay.&lt;/span&gt;
        &lt;span class="n"&gt;onRetry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Capture some information for logging/telemetry.&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogWarn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"ExecuteReaderWithRetryAsync: Retry &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; due to &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// Retry the following call according to the policy.&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExecuteAsync&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;SqlDataReader&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// This code is executed within the Policy&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;State&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConnectionState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OpenAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ExecuteReaderAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CommandBehavior&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;cancellationToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Circuit-breaker Pattern
&lt;/h2&gt;

&lt;p&gt;There is a problem with the retry pattern. What if a service was down and stayed down for long time?&lt;br&gt;&lt;br&gt;
Then every time we call this service, we are going to call it three times and wait for a second between these calls.&lt;br&gt;&lt;br&gt;
This will add delay for our application.&lt;br&gt;&lt;br&gt;
The Circuit-breaker pattern will fix this, by assuming the service is down after many failed calls.&lt;br&gt;&lt;br&gt;
If the service marked as down, then code will immediately fail the call without even calling the service.&lt;br&gt;&lt;br&gt;
This state is called &lt;code&gt;Open Circuit&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Then the code will wait for a while before it try again to call the service, and if it is still failing, then the state will still be &lt;code&gt;Open&lt;/code&gt;, otherwise it is marked as healthy, and the state will be &lt;code&gt;Closed Circuit&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
Circuit breaker should be used in conjunction with the retry pattern.  &lt;/p&gt;
&lt;h4&gt;
  
  
  Using Cicruit-breaker with Polly.
&lt;/h4&gt;

&lt;p&gt;There is built-in implementation of circuit-breaker in SDKs of Azure services, but we can achieve it using Polly package, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;IAsyncPolicy&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;HttpResponseMessage&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;GetCircuitBreakerPolicy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;HttpPolicyExtensions&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HandleTransientHttpError&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CircuitBreakerAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TimeSpan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromSeconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;30&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>aspnet</category>
      <category>azure</category>
    </item>
    <item>
      <title>Buy custom domains with Azure for your App Service.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sun, 05 Mar 2023 04:36:14 +0000</pubDate>
      <link>https://dev.to/gkarwchan/buy-custom-domains-with-azure-for-your-app-service-40f7</link>
      <guid>https://dev.to/gkarwchan/buy-custom-domains-with-azure-for-your-app-service-40f7</guid>
      <description>&lt;p&gt;If you googled how to buy a domain name on Azure, you might get answers saying that Azure doesn't provide domain name registrar, like &lt;a href="https://learn.microsoft.com/en-us/answers/questions/10805/use-azure-as-a-domain-registrar-for-a-domain-curre?orderby=helpful" rel="noopener noreferrer"&gt;the following answer&lt;/a&gt;, or &lt;a href="https://feedback.azure.com/d365community/idea/9e9f97ea-8526-ec11-b6e6-000d3a4f0789" rel="noopener noreferrer"&gt;the following discussion&lt;/a&gt;.&lt;br&gt;&lt;br&gt;
Not even those answers, even the book &lt;a href="https://www.microsoftpressstore.com/store/exam-ref-az-900-microsoft-azure-fundamentals-9780137955145" rel="noopener noreferrer"&gt;Exam Ref AZ-900&lt;/a&gt; which is a Microsoft book says the following about &lt;code&gt;Azure DNS Zone&lt;/code&gt;:  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you want to purchase your own domain name, you go to a domain registrar, and they register the domain to you. ....  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The book didn't mention a way to buy your domain from Azure itself.&lt;br&gt;&lt;br&gt;
I struggled with that myself, and bought my domain with a third party provider. But it turned out Azure provide this service already.&lt;br&gt;&lt;br&gt;
This is why I hope you will come to my post and find the answer you are looking for.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Custom domains with App Service Domain Service:
&lt;/h2&gt;

&lt;p&gt;To buy a custom domain through Azure, you need to create an &lt;strong&gt;&lt;code&gt;App Service Domain&lt;/code&gt;&lt;/strong&gt; resource in Azure.&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqcugjwb9nkq930i7aje.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqcugjwb9nkq930i7aje.jpg" alt=" " width="237" height="393"&gt;&lt;/a&gt;&lt;br&gt;
When you create the resource, you will enter the domain name you want, and Azure will find out if you can use it or not.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2xxabp5t04qiy6kthyy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2xxabp5t04qiy6kthyy.jpg" alt=" " width="760" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Right now, as I am writing this post, only these &lt;code&gt;Top Level Domain&lt;/code&gt; (TLD) are available through Azure:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.com&lt;/li&gt;
&lt;li&gt;.net&lt;/li&gt;
&lt;li&gt;.co.uk&lt;/li&gt;
&lt;li&gt;.org&lt;/li&gt;
&lt;li&gt;.nl&lt;/li&gt;
&lt;li&gt;.in&lt;/li&gt;
&lt;li&gt;.biz&lt;/li&gt;
&lt;li&gt;.org.uk&lt;/li&gt;
&lt;li&gt;col.in&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why you need to buy from Azure?
&lt;/h2&gt;

&lt;p&gt;The obvious answer to this question, is you have one place to manage your site content, and its domain name and its SSL certificate.&lt;br&gt;&lt;br&gt;
But beside that, Azure is &lt;strong&gt;cheeeeeap&lt;/strong&gt;. The pricing right now is only $11 US dollar for the whole year.&lt;br&gt;&lt;br&gt;
I don't know what you are using for as your domain provider, but I am using GoDaddy, and I am paying for the domain and SSL certificate $10/month.&lt;br&gt;&lt;br&gt;
And on top of that the SSL certificate is free (if you are using standard domain like &lt;a href="http://www.somesite.com" rel="noopener noreferrer"&gt;www.somesite.com&lt;/a&gt;). You have to pay for wildcard certificates.  &lt;/p&gt;

</description>
      <category>azure</category>
      <category>networking</category>
    </item>
    <item>
      <title>Everything you need to know about telemetry for your Asp.NET application on Azure.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sat, 25 Feb 2023 05:10:04 +0000</pubDate>
      <link>https://dev.to/gkarwchan/everything-you-need-to-know-about-telemetry-and-instrumentation-your-aspnet-application-on-azure-49jn</link>
      <guid>https://dev.to/gkarwchan/everything-you-need-to-know-about-telemetry-and-instrumentation-your-aspnet-application-on-azure-49jn</guid>
      <description>&lt;p&gt;All of the services that Azure offers for the instrumentation and observability (monitoring) of applications are grouped under Azure Monitor.  &lt;/p&gt;

&lt;p&gt;Three services fall under the banner of Azure Monitor:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Azure Monitor itself, which offers the observability component to track your apps.&lt;/li&gt;
&lt;li&gt;Application Insights, or its substitute OpenTelemetry, which offers the instrumentation and telemetry components&lt;/li&gt;
&lt;li&gt;The analytics component is provided by Log Analytics.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will emphasise the instrumentation component in this post.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Telemetry and instrumentation in Azure.
&lt;/h2&gt;

&lt;p&gt;Telemetry, the data collected to observe your application, can be broken into three types or "pillars":  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Distributed Tracing&lt;/li&gt;
&lt;li&gt;Metrics&lt;/li&gt;
&lt;li&gt;Logs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Azure provides two services that cover this area:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Insights&lt;/li&gt;
&lt;li&gt;OpenTelemtry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Application Insights is the service we will discuss in this post because it offers thorough and rich capabilities for gathering information about your application. Yet &lt;code&gt;OpenTelemetry&lt;/code&gt; deserves a quick mention.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenTelemetry on Azure:
&lt;/h3&gt;

&lt;p&gt;Resuming with Application Insights&lt;br&gt;
OpenTelemetry is the new kid in the hood and it is the future of telemetry. This initiative aims to standardize telemetry APIs and SDKs, and establish vendor-neutral SDKs for telemetry.&lt;br&gt;&lt;br&gt;
It is still in early phase of development, and it only cover the &lt;strong&gt;Distributed Tracing&lt;/strong&gt; part of the telemetry.&lt;br&gt;&lt;br&gt;
The technology is widely utilised in the world of Docker and Kubernetes.&lt;br&gt;&lt;br&gt;
Recently, Azure Monitor began implementing OpenTelmetry by reading its data. Nonetheless, in general, we should choose Application Insights because it has far more functionality till this technology advances further, especially if we are working on App Service and Azure functionalities.  &lt;/p&gt;

&lt;p&gt;Now back to Application Insights.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Application Insights and Auto-Instrumentation:
&lt;/h2&gt;

&lt;p&gt;You can enable Application Insights on an App Service or Azure Function without writing any line of code.&lt;br&gt;
This feature is called Auto-instrumentation or “Run-time instrumentation”&lt;br&gt;
This feature is available because the App Service base image has a built-in agent that will collect the instrumentation and communicate with the Application Insights server.&lt;/p&gt;

&lt;p&gt;Asp.net core (on both linux and windows) supports Auto-instrumentation.&lt;/p&gt;

&lt;p&gt;To enable Auto-instrumentation on an App Service, on Azure Portal check the App Service, and on the left side there is &lt;strong&gt;&lt;code&gt;Application Insigths&lt;/code&gt;&lt;/strong&gt; blade.&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feflexlh7m9gd41lkpwv1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feflexlh7m9gd41lkpwv1.png" alt=" " width="568" height="624"&gt;&lt;/a&gt;&lt;br&gt;
Then you enable it on the App Service.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopsn6eio4ylbu2w9pxfd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopsn6eio4ylbu2w9pxfd.png" alt=" " width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Auto-instrumentation on client side:
&lt;/h4&gt;

&lt;p&gt;If you are using Asp.NET MVC application on Windows hosted App Service, or using Azure Static Web App, you can auto-instrument your JavaScript code, by just doing the following:&lt;br&gt;&lt;br&gt;
Add a new application setting &lt;strong&gt;&lt;code&gt;APPINSIGHTS_JAVASCRIPT_ENABLED&lt;/code&gt;&lt;/strong&gt; and set its value to &lt;strong&gt;&lt;code&gt;true&lt;/code&gt;&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
That will inject JavaScript SDK for Application Insights in your JavaScript code.  &lt;/p&gt;

&lt;p&gt;Client-side instrumentation captures information about the user experience of the app, including page load times, details of browser exceptions, and performance data about AJAX calls. &lt;/p&gt;
&lt;h2&gt;
  
  
  Application Insights and Manual-Instrumentation:
&lt;/h2&gt;

&lt;p&gt;Although Auto-instremenation will provide good coverage, it is not enough.&lt;br&gt;
We need to track our application manually from inside the code.&lt;br&gt;
The more we track from inside the code the more coverage we will have on the performance and operational issues we encounter in production, which translates to better support.&lt;/p&gt;
&lt;h4&gt;
  
  
  Manual instrumentation on the Asp.NET server code:
&lt;/h4&gt;

&lt;p&gt;To collect telemetry from the code, we need to include NuGet package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Microsoft.ApplicationInsights.AspNetCore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then initialize the service from the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;builder&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;WebApplication&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// The following line enables Application Insights telemetry collection.&lt;/span&gt;
&lt;span class="n"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddApplicationInsightsTelemetry&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can pass the connection string in the code, but better to provide it from the &lt;code&gt;appsettings.json&lt;/code&gt; file as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;appsettings.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"ApplicationInsights"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ConnectionString"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Copy connection string from Application Insights Resource Overview"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By just adding these few lines, our SDK will collect lots of metrics from the running application. It will collect:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application Dependencies: for example communication with databases including sql statements, or with blob storage.&lt;/li&gt;
&lt;li&gt;Performance Counters: for example memory and CPU usage.&lt;/li&gt;
&lt;li&gt;Events Counter: There are built-in events that the SDK will collect, and you can create your own custom event. For a list of built-in events &lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/app/eventcounters" rel="noopener noreferrer"&gt;check this link&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  What to capture with the SDK
&lt;/h4&gt;

&lt;p&gt;Many metrics can be collected, and each one has a corresponding config name which we can turned off&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Http request calls&lt;/li&gt;
&lt;li&gt;Performance counters (memory, CPU usage)&lt;/li&gt;
&lt;li&gt;Dependencies: &lt;a href="https://learn.microsoft.com/en-us/azure/azure-monitor/app/asp-net-dependencies#dependency-auto-collection" rel="noopener noreferrer"&gt;check this for a list of trackable dependencies&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Heart Beat feature&lt;/li&gt;
&lt;li&gt;Events: this deserve another post&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Frequency of metric sampling
&lt;/h4&gt;

&lt;p&gt;How often the SDK will send sampling to Azure service?&lt;br&gt;&lt;br&gt;
We can configure that using sampling configuration. There are two options to define sampling frequency:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adaptive: which is the default&lt;/li&gt;
&lt;li&gt;Fixed-rate: which you can use to reduce the traffic to the server.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Logging to Application Insights
&lt;/h2&gt;

&lt;p&gt;Finally, we need to do our logging in Application Insights.&lt;br&gt;&lt;br&gt;
First add this package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Microsoft.Extensions.Logging.ApplicationInsights
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then we add this to our &lt;code&gt;appsettings.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"ApplicationInsights"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"InstrumentationKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[The instrumentation key]"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"Logging"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PathFormat"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[The path and file format used in file logging, e.g.: c:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;log-{Date}.txt]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"LogLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Information"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"ApplicationInsightsLoggerProvider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"LogLevel"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Default"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Warning"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and add this when you configure the service collection&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// as we discussed before&lt;/span&gt;
&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddApplicationInsightsTelemetry&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddLogging&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logBuilder&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
             &lt;span class="p"&gt;{&lt;/span&gt;
                 &lt;span class="n"&gt;logBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddApplicationInsights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;YourInstrumentationKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="c1"&gt;// adding custom filter for specific use case. &lt;/span&gt;
                     &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddFilter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Orleans"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;LogLevel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>aspnet</category>
      <category>azure</category>
    </item>
    <item>
      <title>Check performance bottleneck with Azure Application Insights.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Thu, 23 Feb 2023 04:43:16 +0000</pubDate>
      <link>https://dev.to/gkarwchan/check-performance-bottleneck-with-azure-application-insight-em4</link>
      <guid>https://dev.to/gkarwchan/check-performance-bottleneck-with-azure-application-insight-em4</guid>
      <description>&lt;p&gt;If you have Application Insights enabled for your azure app service, then it is a piece of cake to get the performance bottleneck in your app, and even it check external dependencies like database queries or any other external dependencies.  &lt;/p&gt;

&lt;p&gt;I have a Web API application, that is accessing Azure Sql Server, and Azure blob storage.  &lt;/p&gt;

&lt;p&gt;By going into the performance blade under &lt;code&gt;Investigate&lt;/code&gt;:&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mr3srn55zc4vebhm1ik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mr3srn55zc4vebhm1ik.png" alt=" " width="518" height="598"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You will see the average time for each API call, sorted descending by time:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fir4wnbet13t5m4875maz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fir4wnbet13t5m4875maz.png" alt=" " width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By clicking on any one, you can drill down to where the time consume even by its external dependencies:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs693bun98iqxz1y459q8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs693bun98iqxz1y459q8.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see it shows the time it takes to connect to its external resources, and in our case they are:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sql Server&lt;/li&gt;
&lt;li&gt;Blob Storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can even drill down to its collected samples:&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vujzbb9n233osykkvkg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vujzbb9n233osykkvkg.png" alt=" " width="398" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And you can get a very granular look at the time consume in the whole workflow of that API call:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomzo4cgmwcncj9shn6q1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomzo4cgmwcncj9shn6q1.png" alt=" " width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait, there is more
&lt;/h2&gt;

&lt;p&gt;If the app administrator had concerns about the performance, and want to inform the developer team, then they can report the issue from Application Insights.&lt;br&gt;&lt;br&gt;
On the right side, you can create a &lt;strong&gt;&lt;code&gt;Work Item&lt;/code&gt;&lt;/strong&gt; to report this issue to the dev team.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyg5duvxy0h3korp97yn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkyg5duvxy0h3korp97yn.png" alt=" " width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You need to have a &lt;code&gt;Work Item Template&lt;/code&gt;, which define where you report those issues. There are two venues where you report the issues:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Azure DevOps.&lt;/li&gt;
&lt;li&gt;GitHub Repository, where it report it to the &lt;code&gt;Issues&lt;/code&gt; tab in the repository.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Creating a template is easy, but I am not going to cover it here, and I am already created a template the report in my github repo.  &lt;/p&gt;

&lt;p&gt;After you create a &lt;code&gt;Work Item&lt;/code&gt;, (in my case I had already template, it will create an issue with the name of the API call&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8wcdmrm07p6c7jjfx1bx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8wcdmrm07p6c7jjfx1bx.png" alt=" " width="800" height="130"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and inside the issue will have a link to the details captured in Application Insights.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkejv8yf70spkg4j2ntag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkejv8yf70spkg4j2ntag.png" alt=" " width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>performance</category>
    </item>
    <item>
      <title>Use Azure Key Vault to retrieve secured parameters during Azure deployment.</title>
      <dc:creator>Ghassan Karwchan</dc:creator>
      <pubDate>Sat, 04 Feb 2023 00:38:20 +0000</pubDate>
      <link>https://dev.to/gkarwchan/use-azure-key-vault-to-retrieve-secured-parameters-during-azure-deployment-5alb</link>
      <guid>https://dev.to/gkarwchan/use-azure-key-vault-to-retrieve-secured-parameters-during-azure-deployment-5alb</guid>
      <description>&lt;p&gt;You have an ARM template to deploy, and you need to pass secure parameters. Instead of storing secure values in the parameter file, you can just retrieve these values from Key Vault.&lt;/p&gt;

&lt;p&gt;To be able to access the key vault by the resource manager you need to change access policy to allow "Azure Resource Manager for template deployment", as shown here.&lt;/p&gt;

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

&lt;p&gt;Or you can do it from Powershell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;an&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;existing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-AzKeyVaultAccessPolicy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-VaultName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MyVaultName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-EnabledForTemplateDeployment&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;vault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-AzKeyVault&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-VaultName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MyVaultName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-resourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;myresourcegroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-Location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;centralus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-EnabledForTemplateDeployment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to use it?
&lt;/h2&gt;

&lt;p&gt;in the deployment parameter file specify the location of the secured string to be the &lt;code&gt;keyvault&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"contentVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"parameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"location"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"eastus"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;

        &lt;/span&gt;&lt;span class="nl"&gt;"adminUsername"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"companyAdmin"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"adminPassword"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"reference"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"keyVault"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/&amp;lt;subscription-id&amp;gt;/resourceGroups/&amp;lt;rg-name&amp;gt;/providers/Microsoft.KeyVault/vaults/MyVaultName"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"secretName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;secret&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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

&lt;/div&gt;



&lt;p&gt;Permissions to run deployments:&lt;/p&gt;

&lt;p&gt;The beauty of this feature is the user who is doing deployment doesn't need to have access to the secrets, even read access. Just need a special permission called deploy permission, or more specifically this permission&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Microsoft.keyVault/Vaults/deploy/action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To assign this permission to the user, it is easier if we create a custom role with this permission and then assign this role to any user want to deploy.&lt;br&gt;&lt;br&gt;
First we create a json to represent the definition of the custom role:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TemplateDeploymentForResourceManagerRole"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"IsCustom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Lets you deploy a resource manager template with the access to the secrets in the Key Vault."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.KeyVault/vaults/deploy/action"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"DataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotDataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AssignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/&amp;lt;your subscription id&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then create the role and assign it to the user.&lt;br&gt;&lt;br&gt;
This powershell script does this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;New-AzRoleDefinition&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-InputFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;path-to-role-file&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-AzRoleAssignment&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ExampleGroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-RoleDefinitionName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TemplateDeploymentForResourceManagerRole"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-SignInName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;user-principal-name&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
  </channel>
</rss>
