Avoid duplicate POSTs with .NET Core

prevent duplicate request mvc
avoiding duplicate form submission in asp net mvc by clicking submit twice
web api prevent multiple requests
asp net mvc stop double submit
asp net mvc double post
validateantiforgerytoken asp net core
.net antiforgerytoken
ignoreantiforgerytoken attribute

I'm using POST in a .NET Core REST API to insert data on database.

In my client application, when the user clicks a button, I disable this button. But sometimes, because some reason, the click of the button may be faster than the function of the disable button. This way, the user can double click on the button and the POST will be sent twice, inserting the data twice.

To do POST I'm using axios on the client side. But how can I avoid this on the server side?

Handling concurrency with inserts is hard, frankly. Things like updates and deletes are relatively trivial as you can use concurrency tokens. When doing an update for instance, a WHERE clause is added to check the row that is about to be updated concurrency token value. If it doesn't match, that means it was updated since the data was last queried, and you can then implement some sort of recovery stategy.

Inserts don't work the same way because there's obviously nothing there yet to compare to. Your best bet is a somewhat convoluted strategy of assigning some id to a particular insertion. This will have to be persisted on a column in your table, and that column will need to be unique. When you display the form, you set a hidden input with a unique-ish value, such as Guid.NewGuid(). This will then be posted back when the user submits. This then gets added to your entity, and when you save it will be set on the row that's created.

Now let's say the user double-click the submit button firing off two nearly simultaneous requests. Because the same form data is being submit for both requests, the same id is present in both submissions. The one that makes it first ends up saving the record to the database, while the next will end up throwing an exception. Since the column the id is being saved to is unique, and the same id was sent for both requests, the second one will fail to save. At this point, you can catch the exception and recover some how.

My personal recommendation is to make it seamless to the user. When you hit the catch, you query the row that was actually inserted with that id, and return that id/data instead. For example, let's say this was for a checkout page and you were creating orders. You're likely going to redirect the user to an order confirmation page after completion. So, on the request that fails, you look up the order that was actually created, and then you just redirect to the order confirmation page immediately with that order number/id. As far as the user is concerned, they just went to directly to the confirmation page, and your app ended up only inserting one order. Seamless.

Define Unique ID in API, Last post Dec 07, 2019 12:32 PM by PatriceSc � ‹ Previous Thread|Next NET Core you may want also to have a look at However, how do I make sure multiple requests don't tap into this variable at the same time resulting in duplicates? Part 5 - Detecting duplicate routes in ASP.NET Core (this post) In this series , I have shown how to view all the routes in your application using an endpoint graph. In this post I show how to do something more useful—detecting duplicate routes that would throw an exception at runtime.

I have had this scenario some time ago. I created an Action Filter for it, which is using an Anti Fogery Token:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class PreventDoublePostAttribute : ActionFilterAttribute
{
    private const string TokenSessionName = "LastProcessedToken";

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var antiforgeryOptions = context.HttpContext.RequestServices.GetOption<AntiforgeryOptions>();
        var tokenFormName = antiforgeryOptions.FormFieldName;

        if (!context.HttpContext.Request.Form.ContainsKey(tokenFormName))
        {
            return;
        }

        var currentToken = context.HttpContext.Request.Form[tokenFormName].ToString();
        var lastToken = context.HttpContext.Session.GetString(TokenSessionName);

        if (lastToken == currentToken)
        {
            context.ModelState.AddModelError(string.Empty, "Looks like you accidentally submitted the same form twice.");
            return;
        }

        context.HttpContext.Session.SetString(TokenSessionName, currentToken);
    }
}

Simple use it on your method:

[HttpPost]
[PreventDoublePost]
public async Task<IActionResult> Edit(EditViewModel model)
{
    if (!ModelState.IsValid)
    {
        //PreventDoublePost Attribute makes ModelState invalid
    }
    throw new NotImplementedException();
}

Make sure, you generate the Anti Fogery Token, see the documentation on how it works for Javascript or Angular.

How to Prevent Double Posting form in mvc?, Please find below link for the same. https://stackoverflow.com/questions/ 55286021/avoid-duplicate-posts-with-net-core . You can use the same� I don't think this is quite a duplicate of the answer referenced in the comment, since the link is for spring MVC, and this question is for .NET MVC. I actually spent a few hours on this a while back, and came up with the following.

If you use a relational database the simplest way is to add unique constraint to the table(s) where data is populated. If it's impossible or database isn't relational and you have single server instance you can use synchronization inside the application code, that is keep single instance of an entity to be populated into db and modify this instance quintessentially by using synchronization primitives like lock, etc. But this approach has significant drawback - it doesn't work if there multiple instance of your web application (on different servers for example). Another approach you can apply is using versioning approach - that is you can keep version of modification along with your data and do read before write into a database (in order to increment version) with turned on optimistic locking on the db side (most of dbs support this).

Prevent Repeated Requests using ActionFilters in ASP.NET MVC , Wherever there is a form or page that allows a user to post up those that aren't very tech-savy) from bombarding you with duplicate items. Select the ASP.NET Core Web Application template and click Next. Name the project TodoApi and click Create. In the Create a new ASP.NET Core Web Application dialog, confirm that .NET Core and ASP.NET Core 3.1 are selected. Select the API template and click Create. Open the integrated terminal.

This answer inspired by @Christian Gollhardt answer First you need to enable session in your stratup.cs add

    services.Configure<CookiePolicyOptions>(options =>
                    {
                        // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                        options.CheckConsentNeeded = Context => false;
                        options.MinimumSameSitePolicy = SameSiteMode.None;
                    });

services.AddMemoryCache();
                    services.AddSession(options => {
                        // Set a short timeout for easy testing.
                        options.IdleTimeout = TimeSpan.FromMinutes(10);
                        options.Cookie.HttpOnly = true;
                        // Make the session cookie essential
                        options.Cookie.IsEssential = true;
                    });

and then

   app.UseSession();

then your class

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class PreventDoublePostAttribute : ActionFilterAttribute
{
    private const string UniqFormuId = "LastProcessedToken";
    public override async void OnActionExecuting(ActionExecutingContext context)
    {

        IAntiforgery antiforgery = (IAntiforgery)context.HttpContext.RequestServices.GetService(typeof(IAntiforgery));
        AntiforgeryTokenSet tokens = antiforgery.GetAndStoreTokens(context.HttpContext);

        if (!context.HttpContext.Request.Form.ContainsKey(tokens.FormFieldName))
        {
            return;
        }

        var currentFormId = context.HttpContext.Request.Form[tokens.FormFieldName].ToString();
        var lastToken = "" + context.HttpContext.Session.GetString(UniqFormuId);

        if (lastToken.Equals(currentFormId))
        {
            context.ModelState.AddModelError(string.Empty, "Looks like you accidentally submitted the same form twice.");
            return;
        }
        context.HttpContext.Session.Remove(UniqFormuId);
        context.HttpContext.Session.SetString(UniqFormuId, currentFormId);
        await context.HttpContext.Session.CommitAsync();

    }

}

usage

[HttpPost]
[PreventDoublePost]
public async Task<IActionResult> Edit(EditViewModel model)
{
    if (!ModelState.IsValid)
    {
        //PreventDoublePost Attribute makes ModelState invalid
    }
    throw new NotImplementedException();
}

dupFinder Command-Line Tool - Help, By default, it considers code fragments as duplicates not only if they are identical, NET framework to load the application in partial trust, which means it won't load or run correctly. a balance between avoiding false positives and missing real duplicates. Can I use DupFinder against a .net core project? If you want to prevent double clicks from double posting, you could: 1. Disable the button after click 2. Maintain a unique index on 'Issues' and look for duplicates 3. Maintain something in session that gives you an indication of a double post.

Work with data in ASP.NET Core Apps, NET Core and Azure | Working with data in ASP. it belongs, and can avoid duplicate logic between multiple entities that use the same concept. The full code listing to return a collection of posts with their Owner property� The controller takes the result of the model's processing (if any) and returns either the proper view and its associated view data or the result of the API call. Learn more at Overview of ASP.NET Core MVC and Get started with ASP.NET Core MVC and Visual Studio. The controller is a UI-level abstraction. Its responsibilities are to ensure request

Azure Service Bus duplicate message detection , This article explains how you can detect duplicates in Azure Service Bus NET and AMQP libraries automatically generate a message ID for the message. This blog post about idempotence describes various techniques for� Avoid insert duplicate data into database by MVC5 C# [Answered] RSS 1 reply Last post May 11, 2014 10:32 PM by Starain chen - MSFT

How to avoid duplicate records in SQL view using Entity Framework , duplicate rows in entity framework view returning, duplicate rows in entity framework view, Net Core | MVC | HTML Agility Pack | SQL | Technology Crowds�

Comments
  • You could send a unique token from the client side, and in your controller, you can check if it's been added to the MemoryCache earlier. If it has, then just exit the from the POST method, otherwise continue with the intended logic.
  • the method need to be async otherwise it will not work as expected
  • also there is no GetOption in .net core 2.2