Asp.net WebAPI:中止(取消)请求

本文关键字:取消 请求 中止 net WebAPI Asp | 更新日期: 2023-09-27 18:05:47

首先,如果你们中有人在WebAPI控制器中做这样的事情(可能也适用于MVC),这是一个讨论。

我指的是这样一个场景:客户端(通常是浏览器)启动请求,导航离开,或者更一般,由于任何原因终止请求。现在,请求在客户端被中止,不再被考虑。但在服务器端,请求仍在执行,通常可能会做两件特别有趣的事情:

  • 进行(重)DB-Query
  • 呼叫其他业务

而这一切最终都是徒劳的(至少当它是一个副作用的自由读操作时)。

在这种情况下,是否有人处理正在进行的查询/服务调用的取消?

我所知道的是,CancellationToken可以在api控制器中传递(即使我无法使其工作,因此在从客户端中止时真正请求取消)。理论上,这个CancellationToken需要向下传递到所有较低的层,以处理可能取消的数据库和服务调用。

Asp.net WebAPI:中止(取消)请求

虽然在编写WebAPI时不直接支持取消,但OWIN API绝对支持取消。如果你正在使用WebAPI 2.0,你将运行在OWIN之上,并且将能够使用GetOwinContext()扩展方法通过微软包装器访问上下文。

方便地使用通过OwinRequestCallCancelled属性暴露的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的参数。您可以在这里创建任何规则,以匹配您希望提供此值的参数。