Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/256.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Asp.net WebAPI:中止(取消)请求_C#_Asp.net_Asp.net Mvc_Asp.net Web Api - Fatal编程技术网

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

C# Asp.net WebAPI:中止(取消)请求,c#,asp.net,asp.net-mvc,asp.net-web-api,C#,Asp.net,Asp.net Mvc,Asp.net Web Api,首先,如果你们中有人在WebAPI控制器中执行请求取消之类的操作(可能也适用于MVC),那么这是一个讨论 我特别想说的是这样一个场景: 客户端(通常是浏览器)启动请求,导航到别处或更一般的位置,出于任何原因中止请求。现在,请求在客户端被中止,不再被考虑。但在服务器端,请求仍在执行,通常可能会做两件特别有趣的事情: 进行(繁重的)数据库查询 给另一个服务打一个(沉重的)服务电话 最终一切都是徒劳的(至少当它是一个无副作用的读取操作时) 在这种情况下,是否有人负责取消正在进行的查询/服务呼叫 我

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

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

  • 进行(繁重的)数据库查询
  • 给另一个服务打一个(沉重的)服务电话
最终一切都是徒劳的(至少当它是一个无副作用的读取操作时)

在这种情况下,是否有人负责取消正在进行的查询/服务呼叫

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

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

使用通过
OwinRequest
属性公开的
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);
    }
}

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

这可能无法完全回答您的问题,但看看它确实听起来很有趣。似乎可以使用CancellationToken作为参数(我知道这一点),特别是框架取消了它。谢谢!但这不是开箱即用的支持吗?当CancellationToken用作最后一个参数时,它由webapi管道设置。参考:(我希望这个链接继续工作)那么看起来我一直在处理旧信息。好吧,你的想法已经实现了!微软有很多聪明的家伙在思考这些话题,请骄傲!
config.ParameterBindingRules.Add(p
    => p.ParameterType == typeof(CancellationToken)
    ? new OwinCancellationTokenBinding (p)
    : null);