Asp.net WebAPI:中止(取消)请求
本文关键字:取消 请求 中止 net WebAPI Asp | 更新日期: 2023-09-27 18:05:47
首先,如果你们中有人在WebAPI控制器中做这样的事情(可能也适用于MVC),这是一个讨论。
我指的是这样一个场景:客户端(通常是浏览器)启动请求,导航离开,或者更一般,由于任何原因终止请求。现在,请求在客户端被中止,不再被考虑。但在服务器端,请求仍在执行,通常可能会做两件特别有趣的事情:
- 进行(重)DB-Query
- 呼叫其他业务
而这一切最终都是徒劳的(至少当它是一个副作用的自由读操作时)。
在这种情况下,是否有人处理正在进行的查询/服务调用的取消?我所知道的是,CancellationToken
可以在api控制器中传递(即使我无法使其工作,因此在从客户端中止时真正请求取消)。理论上,这个CancellationToken
需要向下传递到所有较低的层,以处理可能取消的数据库和服务调用。
虽然在编写WebAPI时不直接支持取消,但OWIN API绝对支持取消。如果你正在使用WebAPI 2.0,你将运行在OWIN之上,并且将能够使用GetOwinContext()
扩展方法通过微软包装器访问上下文。
方便地使用通过OwinRequest
的CallCancelled
属性暴露的CancellationToken
值传播消去。您可以将所有这些放在一起,以在控制器方法中获取令牌:
public async Task Get()
{
var cancellation = Request.GetOwinContext().Request.CallCancelled;
await database.FooAsync(cancellation);
}
这是相当丑陋的。你必须在每个需要处理取消的方法中进行这个调用,并且它不能很好地工作,因为WebAPI将给你这个CancellationToken
。相反,如果我们把它变成一个参数不是更好吗?
public async Task Get(CancellationToken cancellation)
{
await database.FooAsync(cancellation);
}
为此,您可以创建一个自定义参数绑定,从OWIN上下文中获取CancellationToken
:
public class OwinCancellationTokenBinding : HttpParameterBinding
{
public OwinCancellationTokenBinding(HttpParameterDescriptor parameter)
: base(parameter)
{
}
public override Task ExecuteBindingAsync(
ModelMetadataProvider metadataProvider,
HttpActionContext actionContext,
CancellationToken cancellationToken)
{
actionContext.ActionArguments[Descriptor.ParameterName]
= actionContext.Request.GetOwinContext().Request.CallCancelled;
return Task.FromResult<object>(null);
}
}
要使用它,您可以使用ParameterBindingRules
集合向HttpConfiguration
注册绑定:
config.ParameterBindingRules.Add(p
=> p.ParameterType == typeof(CancellationToken)
? new OwinCancellationTokenBinding (p)
: null);
该规则匹配任何类型为CancellationToken
的参数。您可以在这里创建任何规则,以匹配您希望提供此值的参数。