C# 如何在ASP.NET MVC中中止操作

C# 如何在ASP.NET MVC中中止操作,c#,javascript,jquery,ajax,asp.net-mvc,C#,Javascript,Jquery,Ajax,Asp.net Mvc,我想停止服务器端的jQuery.ajax方法调用的操作。 我可以在客户端使用$.Ajax.abort()方法停止Ajax请求,但在服务器端则不能 更新: 我使用了异步操作而不是同步操作,但是我没有得到我想要的!正如您所知,服务器不能同时处理多个请求,这导致每个请求都必须等待上一个请求完成,即使上一个请求被$.Ajax.Abort()方法取消。 我知道如果我使用[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]

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

更新:

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


首先,我希望用户中止服务器端的处理方法。就是这样:)

您可能想看看如何使用以下类型的控制器

还要看看这篇文章是否也能帮助您,很抱歉,这次我不能给出任何代码示例

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

如果您通过代码调用其他站点,则有两个选项,具体取决于您的目标框架和要使用的方法。我在这里提供参考资料供您审阅:

用于.NET4.0 为了在.NET4.5中使用,此类有一个方法来取消所有挂起的请求


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

一个简单的解决方案是使用以下内容。我使用它来取消长时间运行的任务(特别是生成数千个通知)。我还使用相同的方法通过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";
}
}

我们已经在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
        }
    }
}
这里有一个例子 后端:

希望我没有迟到。

我发现这篇文章:非常有用。我将在这里总结这篇文章

开始之前的简短说明:

  • 我运行的是MVC5,而不是ASP.NET核心MVC
  • 我希望能够在导航离开页面时取消操作,或者使用jQuery
    abort
    取消操作
我的结局是这样的:

//只需将CancellationToken参数添加到参数列表的末尾即可
公共异步任务GetQueryDataAsync(
int id,
取消令牌(取消令牌)
{
CancellationToken dcToken=Response.ClientDisconnectedToken;
var linkTokenSrc=CancellationTokenSource
.CreateLinkedTokenSource(
取消令牌,
德托克
);
使用(var dbContext=new Entities())
{
var data=await dbContext.complementdview
/*一堆linq语句*/
.ToListAsync(linkTokenSrc.Token)
.配置等待(true);
//除非取消,否则执行填充并返回数据
// ...
}
}
因为我使用的是MVC5,所以我必须使用文章中规定的解决方法,即读取
Response.ClientDisconnectedToken
并链接令牌源

如果您使用的是ASP.NET Core MVC,那么您应该能够直接使用
CancellationToken
参数,而不必根据文章将其链接起来


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

如果我理解正确,您不希望任何XHR击中您的服务器?:)。。。也许这句话会对我有所帮助或感谢,但这不是我想要的!!我调用一个动作,例如,需要1分钟。如果用户愿意,我想让他们取消请求,我正在使用$.ajax.abort(),它可以正常工作,并取消请求,但我知道服务器正在处理以前的请求。如果我在服务器上用该会话发送另一个请求,它必须等到最后一个操作结束。@user2349133只要它在客户端,您就可以根据该请求用户检查它的状态。。。一旦它进入服务器。。。我看不到取消特定XHR请求的方法长时间运行的操作在做什么?你能在那里使用分页吗,即每次调用处理100个“东西”?谢谢,我相信你已经正确地理解了我的意思,你能给我一个清晰的代码示例吗?再做一点研究,这可能取决于你使用的mvc版本。我的理解是,您希望开始一个异步请求,因为这是一个长时间运行的过程,用户可以取消。当用户取消请求时,服务器将获取该异步线程并基本上中止该操作。是吗?是的,没错!我使用的是ASP.NET MVC 4,我还没有在c#中使用异步,如果您有一个示例代码,它将帮助我!不过,谢谢:)很抱歉,我自己没有任何实际的示例,但是我的答案中的第一个链接使用了一个示例zip,您可以使用它,名为Async.zip,它位于此处:从示例来看,控制器似乎有一个用于异步工作的服务,该服务上有一个中止方法。至少它应该让您了解如何实现执行实际异步工作的服务。@SaeedHamed您对长时间运行的服务有多大的控制权?是否存在其他客户端可能取消第一个客户端的长时间运行请求的操作的安全风险。是否可以使用“Task.IsCompleted”而不是“gotResult”标志?不起作用。我使用的是.NETFramework4.8。
[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;
}
var promise = $.post("/Somewhere")
setTimeout(function(){promise.abort()}, 1000)