Categories
ASP.Net Core

Handle API Idempotency in ASP.NET Core

What is API Idempotency?

Idempotency is a crucial concept in API design where making the same request multiple times produces the same result as making it once. This is especially important for operations that modify data (POST, PUT, PATCH, DELETE) where accidental duplicate requests could cause problems like double charges or duplicate records.

Why Implement Idempotency?

Before we dive into code, let’s understand why idempotency matters:

  1. Network reliability: Clients might retry requests if they don’t receive a response
  2. User experience: Users might double-click buttons
  3. Distributed systems: Microservices might need to retry failed calls

Basic Implementation Approach

Here’s a simple way to implement idempotency in ASP.NET Core:

1. Create an Idempotency Filter

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Concurrent;

public class IdempotencyFilter : IActionFilter
{
    private static readonly ConcurrentDictionary<string, bool> _processedRequests = new();

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Check for Idempotency-Key header
        if (!context.HttpContext.Request.Headers.TryGetValue("Idempotency-Key", out var idempotencyKey))
        {
            context.Result = new BadRequestObjectResult("Idempotency-Key header is required");
            return;
        }

        var key = idempotencyKey.ToString();

        // If we've already processed this key, return conflict
        if (_processedRequests.ContainsKey(key))
        {
            context.Result = new ConflictObjectResult("This request has already been processed");
            return;
        }

        // Mark this key as being processed
        _processedRequests.TryAdd(key, true);
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Cleanup if needed
    }
}

2. Register the Filter

In your Program.cs:

builder.Services.AddControllers(options =>
{
    options.Filters.Add<IdempotencyFilter>();
});

3. Using the Idempotent API

POST /api/orders
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json

{
    "productId": 123,
    "quantity": 2
}

Best Practices

  1. Key generation: Clients should generate unique keys (GUIDs work well)
  2. Key length: Keep it reasonable (128-256 characters max)
  3. Expiration: Set appropriate expiration times (hours/days depending on use case)
  4. HTTP methods: Typically only needed for POST, PUT, PATCH, DELETE
  5. Response caching: Cache successful responses to return identical responses for duplicate requests

Implementing idempotency in your ASP.NET Core APIs helps make them more reliable and resilient to duplicate requests.

Remember that the exact implementation might vary based on your specific requirements, but this gives you a solid foundation to build upon.

Happy Coding 🙂

Categories
ASP.Net Core

Getting logged in user ID in non-controller class in ASP.Net Core

It’s easy to retrieve the current logged-in user’s information, such as user ID, username, or email, in an ASP.Net Core controller class. However, it can be tricky to access this information in other classes, like the IdentityDbContext class. Here’s an example of how to extract the current user in a non-controller class, specifically in the IdentityDbContext class:

var httpContextAccessor = this.GetService<IHttpContextAccessor>();
var userId = httpContextAccessor.HttpContext?.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;

This example demonstrates how to retrieve the user ID. Hopefully, you find it helpful.

Happy coding 🙂

Categories
Azure NextJs

Fixing Azure Static App Error while Deploying Next.js

If you encounter the following error while deploying your Next.js app to Azure Static App via a GitHub CD/CI pipeline:

You are using Node.js 16.20.2. For Next.js, Node.js version >= v18.17.0 is required.


---End of Oryx build logs---
Oryx has failed to build the solution.

Don’t worry, it’s a quick fix! You just need to add one line to your package.json file:

"engines": {
    "node": ">=18.0.0"
}

After adding this line, your package.json file should look something like this:

{
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "latest",
    "react": "18.2.0",
    "react-dom": "18.2.0",
  },
  "engines": {
    "node": ">=18.0.0"
  }
}

Happy coding 🙂

Categories
PowerShell

Setting Environment Variables in Developer PowerShell in Visual Studio

While writing UI automated test scenarios using Gherkin SpecFlow framework and C# Steps, I needed to set an environment variable to run a single test case from the command line. In the Windows Command Prompt, I would set the environment variable like this:

Set ENV=envName

For example:

Set ENV=autotests-rc

Then, I would run the test scenario using:

dotnet test --filter FullyQualifiedName=project_api_testing.Features.Admin.Structure.VerifyAdminPayItemsFunctionalityFeature.VerifyUserCanGetPayItemOptions

However, setting the environment variable like this doesn’t work in the Developer PowerShell in Visual Studio. Instead, you need to use the following syntax:

$env:ENV = "autotest-rc"

To run all the test cases from the Developer PowerShell in Visual Studio, I use the following command:

To run the all the test case from the developer power shell in visual studio.

dotnet test ; py .\SanitizeJsonReport.py ; livingdoc test-assembly ./bin/Debug/net6.0/project_api_testing.dll -t ./TestExecution.json

Happy Coding 🙂

Categories
Git

Revert a check-in file in Git

To revert a file to a previous version in Git, follow these steps:

  1. View the commit history for the file: Use git log followed by the file name to see the commit history for that specific file:
git log --oneline <filename>

This will display a concise list of commits that have modified the file.

2. Checkout the previous version of the file: Use the git checkout command followed by the commit hash and the file name:

git checkout <commit_hash> -- <filename>

Replace <commit_hash> with the hash of the commit that contains the version of the file you want to revert to.

3. Commit the change: To save the reverted file, commit the change:

git add <filename>
git commit -m "Reverted changes to <filename>"

4. Push the changes: Finally, push the updated branch to the remote repository:

git push origin <branch_name>

Happy Coding 🙂

Categories
Git

Git Rebase Interactive: A Step-by-Step Guide

Git Rebase Interactive is a powerful tool for rewriting commit history. Here’s how to use it:

Step 1: Rebase the Branch

git rebase -i "origin/remote-branch"

Step 2: Edit the Commit History

  • pick: Keep the commit as is
  • squash: Squash the commit into the previous commit
  • edit: Edit the commit message
  • drop: Remove the commit

Step 3: Save and Close

Save and close the interactive shell. Git will rebase the branch according to your changes.

Step 4: Push the Updated Branch

git push --force-with-lease origin local-branch

Example Output

$ git rebase "origin/remote-branch" -Xtheirs
$ git rebase -i "origin/remote-branch"
$ git push --force-with-lease origin local-branch

Conclusion

Git Rebase Interactive makes it easy to squash commits, reorder commits, and push the updated branch to the remote repository. Just remember to use git push --force-with-lease to update the remote branch with the new commit history.

Happy Coding 🙂

Categories
PowerShell

Code sign using PowerShell

Code signing is important before releasing our software to the client. In the previous post, we use a PowerShell script to publish our code. After publishing the code, we need to sign the code before release. We must have code cert for signing. Install the code sign in your machine. Certificate installs process is simple using certificate import wizard.

Windows Certificate installation wizard.

Once the certificate is install, we can procced to code signing process.

cd src
$paths = Get-ChildItem -include *.csproj -Recurse
foreach($pathobject in $paths)
{
     cd $pathobject.directory.fullName
     dotnet publish -o ..\..\__DEPLOY__\Program
}
cd ..\..

This part of the code from previous post this script publish all the project in the solution.

$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert

Get-ChildItem -recurse -path '__DEPLOY__\' -Include *.exe, *.dll | ForEach-Object {	
	$signingParameters = @{
		FilePath      =  $_.FullName
		Certificate   = $cert
		HashAlgorithm = 'SHA256'
		TimestampServer = 'http://timestamp.digicert.com'
	}
	Set-AuthenticodeSignature @signingParameters
	
}

The first line gets the signing cert path.

Next line, navigate to the code that needed to sign, in this example path is ‘__DEPLOY__’, sign will only the files with exe and dll extension. Subsequent lines shows different params for signing. You can find more about the code signing params from PowerShell documentation.

If you want to exclude any folder and files from signing, you can define like this

[string[]]$Exclude = @('ExcudeFolderName')

Get-ChildItem -recurse -path '__DEPLOY__\Program\' -Include *.exe, *.dll | Where-Object  { $_.DirectoryName -notmatch $Exclude } | ForEach-Object
cd src
$paths = Get-ChildItem -include *.csproj -Recurse
foreach($pathobject in $paths)
{
     cd $pathobject.directory.fullName
     dotnet publish -o ..\..\__DEPLOY__\Program
}
cd ..\..

[string[]]$Exclude = @('ExcudeFolderName')

$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert

Get-ChildItem -recurse -path '__DEPLOY__\Program\' -Include *.exe, *.dll | Where-Object  { $_.DirectoryName -notmatch $Exclude } | ForEach-Object {	
	$signingParameters = @{
		FilePath      =  $_.FullName
		Certificate   = $cert
		HashAlgorithm = 'SHA256'
		TimestampServer = 'http://timestamp.digicert.com'
	}
	Set-AuthenticodeSignature @signingParameters
	
}

Above snippet is the entire script.

Happy coding 🙂

Categories
PowerShell

.Net Publish Using PowerShell

Sometimes we want to publish project using PowerShell rather then using Visual Studio Publish feature. I wanted to published all projects of the solutions in one folder. Below PowerShell command will published our projects in __DEPLOY__ folder as an example.

cd src
$paths = Get-ChildItem -include *.csproj -Recurse
foreach($pathobject in $paths)
{
     cd $pathobject.directory.fullName
     dotnet publish -o ..\..\__DEPLOY__\Program
}
cd ..\..

Save this code as PowerShell script with extension of ps1. Run this script from VS, we need to open VS in elevated permission, open “Developer PowerShell” navigate to the script folder and run the script.
You may face an error with error message
“FullyQualifiedErrorId : UnauthorizedAccess”

To resolve this error run this command to by pass security exception

Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass

Run the PowerShell Script again, it should run it without any issue. And all you published files and folder should be in “__DEPLOY__” folder.

Happy Hacking 🙂

Categories
Git Quick Note To Me

Git clone repo with specific branch

Git clone command clones the default or master repository from git remote source. If need to clone a specific branch, we need to specify the branch name in the git clone command. Here is the command to do so

git clone --branch <branch-name> <git-url-to-clone>

Or we can write the same command as follows

git clone -b <branch-name> <git-url-to-clone>

Hope this helps.

Happy Coding 🙂

Categories
Git KeepRemaindingMe

Folder rename in Git

Git can’t detect directory name change. For example rename an existing folder to “Dashboard” from “DashBoard”. Even if we rename the folder name from the directory but git will still not detect the change. Here is the git command to make it work for rename

git mv oldname newname 

For the above example it will not work since it’s case sensitive, to rename a case sensitive name, follow the below commands

git mv DashBoard temp
git mv temp Dashboard

We need to rename to a temporary folder and then rename to intendent folder name.

Happy Coding 🙂