How can I abort an action in ASP.NET MVC

后端 未结 4 1840
野趣味
野趣味 2020-12-31 22:31

I want to stop the actions that are called by the jQuery.ajax method on the server side. I can stop the Ajax request using $.ajax.abort() method on

相关标签:
4条回答
  • 2020-12-31 22:46

    You may want to look at using the following type of controller Using an Asynchronous Controller in ASP.NET MVC

    and also see if this article helps you out as well Cancel async web service calls, sorry I couldn't give any code examples this time.

    I've created an example as a proof of concept to show that you can cancel server side requests. My github async cancel example

    If you're calling other sites through your code you have two options, depending on your target framework and which method you want to use. I'm including the references here for your review:

    WebRequest.BeginGetResponse for use in .Net 4.0 HttpClient for use in .Net 4.5, this class has a method to cancel all pending requests.

    Hope this gives you enough information to reach your goal.

    0 讨论(0)
  • 2020-12-31 22:46

    A simple solution is to use something like below. I use it for cancelling long running tasks (specifically generating thousands of notifications). I also use the same approach to poll progress and update progress bar via AJAX. Also, this works practically on any version of MVC and does not depends on new features of .NET

    public class MyController : Controller
    {
    
    private static m_CancelAction = false;
    
    public string CancelAction()
    {
        m_CancelAction = true;
        return "ok";
    }
    
    public string LongRunningAction()
    {
        while(...)
        {
            Dosomething (i.e. Send email, notification, write to file, etc)
    
            if(m_CancelAction)
            {
                m_CancelAction = false;
                break;
                return "aborted";
            }
        }
    
        return "ok";
    }
    }
    
    0 讨论(0)
  • 2020-12-31 23:01

    We have seen the problem in IE, where an aborted request still got forwarded to the controller action - however, with the arguments stripped, which lead to different error, reported in our logs and user activity entries.

    I have solved this using a filter like the following

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using TWV.Infrastructure;
    using TWV.Models;
    
    namespace TWV.Controllers
    {
        public class TerminateOnAbortAttribute : FilterAttribute, IActionFilter
        {
            public void OnActionExecuting(ActionExecutingContext filterContext)
            {
                // IE does not always terminate when ajax request has been aborted - however, the input stream gets wiped
                // The content length - stays the same, and thus we can determine if the request has been aborted
                long contentLength = filterContext.HttpContext.Request.ContentLength;
                long inputLength = filterContext.HttpContext.Request.InputStream.Length;
                bool isAborted = contentLength > 0 && inputLength == 0;
                if (isAborted)
                {
                    filterContext.Result = new EmptyResult();
                }
            }
    
            public void OnActionExecuted(ActionExecutedContext filterContext)
            {
                // Do nothing
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-31 23:02

    Here is an example Backend:

    [HttpGet]
    public List<SomeEntity> Get(){
            var gotResult = false;
            var result = new List<SomeEntity>();
            var tokenSource2 = new CancellationTokenSource();
            CancellationToken ct = tokenSource2.Token;
            Task.Factory.StartNew(() =>
            {
                // Do something with cancelation token to break current operation
                result = SomeWhere.GetSomethingReallySlow();
                gotResult = true;
            }, ct);
            while (!gotResult)
            {
                // When you call abort Response.IsClientConnected will = false
                if (!Response.IsClientConnected)
                {
                    tokenSource2.Cancel();
                    return result;
                }
                Thread.Sleep(100);
            }
            return result;
    }
    

    Javascript:

    var promise = $.post("/Somewhere")
    setTimeout(function(){promise.abort()}, 1000)
    

    Hope I'm not to late.

    0 讨论(0)
提交回复
热议问题