【问题标题】:Asp.net WebAPI: Aborted (cancelled) requestsAsp.net WebAPI:中止(取消)请求
【发布时间】:2015-10-23 01:58:24
【问题描述】:

首先,如果你们中的任何人在 WebAPI 控制器中执行请求取消之类的操作(可能也适用于 MVC),这是一个讨论。

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

  • 制作一个(繁重的)数据库查询
  • 对另一个服务进行(大量)服务调用

最终一切都是徒劳的(至少当它是一个无副作用的读取操作时)。

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

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

【问题讨论】:

  • 这可能无法完全回答您的问题,但请查看stackoverflow.com/questions/19010856/…
  • 听起来确实很有趣。似乎可以设法使用 CancellationToken 作为参数(我知道),尤其是让它被框架取消。

标签: c# asp.net asp.net-mvc asp.net-web-api


【解决方案1】:

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

使用通过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);
    }
}

要使用它,您可以使用 HttpConfigurationParameterBindingRules 集合注册绑定:

config.ParameterBindingRules.Add(p
    => p.ParameterType == typeof(CancellationToken)
    ? new OwinCancellationTokenBinding (p)
    : null);

此规则匹配CancellationToken 类型的任何参数。您可以在此处创建与您希望为其提供此值的参数匹配的任何规则。

【讨论】:

  • 谢谢!但这不是开箱即用的吗?当 CancellationToken 用作最后一个参数时,它由 webapi 管道设置。参考:books.google.at/…(希望这个链接一直有效)
  • 那看来我一直在处理旧信息。
  • 嗯,你的想法实现了!微软有真正聪明的人在思考这些话题,感到自豪!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 2011-01-28
  • 2013-02-15
  • 1970-01-01
  • 2011-05-31
相关资源
最近更新 更多