8

我想停止jQuery.ajax服务器端方法调用的操作。我可以在客户端使用方法停止 Ajax 请求$.ajax.abort(),但不能在服务器端。

更新:

我使用异步操作而不是同步操作,但我没有得到我想要的!如您所知,服务器不能同时处理多个请求,这导致每个请求都必须等到前一个请求完成,即使前一个请求被 $.Ajax.Abort() 方法取消也是如此。我知道我是否使用 [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] 属性它几乎是我想要的,但它并不满足我。

最重要的是,我想由用户中止服务器端的处理方法。而已 :)

4

5 回答 5

4

您可能想查看使用以下类型的控制器Using an Asynchronous Controller in ASP.NET MVC

并看看这篇文章是否也能帮助你取消异步网络服务调用,很抱歉这次我不能给出任何代码示例。

我创建了一个示例作为概念证明,以表明您可以取消服务器端请求。我的 github 异步取消示例

如果您通过代码调用其他站点,则有两种选择,具体取决于您的目标框架和您要使用的方法。我在这里包括参考供您查看:

用于 .Net 4.0 的WebRequest.BeginGetResponse用于 .Net 4.5 的HttpClient,该类具有取消所有挂起请求的方法。

希望这可以为您提供足够的信息来实现您的目标。

于 2013-07-20T03:15:11.117 回答
3

这是一个示例后端:

[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)

希望我不会迟到。

于 2015-04-08T10:41:44.860 回答
2

我发现这篇文章:在 ASP.NET MVC 和 Web API 中取消长时间运行的查询非常有用。我将在这里总结这篇文章。

开始之前的快速说明:

  • 我正在运行 MVC5,而不是 ASP.NET Core MVC。
  • 当我离开页面或使用 jQuery 取消操作时,我希望能够取消操作abort

我最终得到了这样的结果:

// Just add the CancellationToken parameter to the end of your parameter list
public async Task<ActionResult> GetQueryDataAsync(
    int id,
    CancellationToken cancellationToken)
{
    CancellationToken dcToken = Response.ClientDisconnectedToken;
    var linkTokenSrc = CancellationTokenSource
        .CreateLinkedTokenSource(
            cancellationToken, 
            dcToken
        );

    using (var dbContext = new Entities())
    {
        var data = await dbContext.ComplicatedView
            /* A bunch of linq statements */
            .ToListAsync(linkTokenSrc.Token)
            .ConfigureAwait(true);

        // Do stuff and return data unless cancelled
        // ...
    }
}

由于我使用的是 MVC5,因此我不得不使用文章中规定的解决方法,即读取Response.ClientDisconnectedToken并链接令牌源。

如果您改用 ASP.NET Core MVC,您应该可以CancellationToken直接使用该参数,而不必根据文章链接它。

在此之后,我所要做的就是确保abort在我离开页面时在 JavaScript 中编辑了 XHR。

于 2021-03-25T19:31:32.033 回答
0

我们已经在 IE 中看到了这个问题,其中一个中止的请求仍然被转发到控制器操作 - 但是,在我们的日志和用户活动条目中报告的参数被剥离,这会导致不同的错误。

我已经使用如下过滤器解决了这个问题

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
        }
    }
}
于 2014-03-25T11:54:42.250 回答
-2

一个简单的解决方案是使用类似下面的东西。我用它来取消长时间运行的任务(特别是生成数千条通知)。我也使用相同的方法通过 AJAX 轮询进度和更新进度条。此外,这实际上适用于任何版本的 MVC,并且不依赖于 .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";
}
}
于 2013-10-21T09:06:27.033 回答