如何在ASP.NET MVC中中止操作
本文关键字:操作 MVC NET ASP | 更新日期: 2023-09-27 18:24:03
我想停止服务器端jQuery.ajax
方法调用的操作。我可以在客户端使用$.ajax.abort()
方法停止Ajax请求,但在服务器端不能。
更新:
我使用异步操作而不是同步操作,但我没有得到我想要的!正如您所知,服务器不能同时处理多个请求,这导致即使$.Ajax.Artrt()方法取消了上一个请求,每个请求都必须等待上一个完成。我知道如果我使用[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)],它几乎是我想要的,但它不能满足我。
最重要的是,我想由用户中止服务器端的处理方法。就是这样:)
您可能需要考虑使用以下类型的控制器在ASP.NET MVC 中使用异步控制器
同时看看这篇文章是否也能帮助你取消异步web服务调用,很抱歉这次我不能给出任何代码示例。
我创建了一个示例作为概念验证,以表明您可以取消服务器端请求。我的github异步取消示例
如果你通过代码调用其他网站,你有两个选择,这取决于你的目标框架和你想使用的方法。我在这里包括参考资料供您审查:
用于.Net 4.0的WebRequest.BeginGetResponse在.Net 4.5中使用的HttpClient,这个类有一个方法来取消所有挂起的请求。
希望这能给你足够的信息来达到你的目标。
下面是一个例子后端:
[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)
希望我不会迟到。
我发现这篇文章:在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。
我们在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
}
}
}
一个简单的解决方案是使用以下内容。我用它来取消长时间运行的任务(特别是生成数千个通知)。我也使用相同的方法通过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";
}
}