【问题标题】:Modeling Client Context in WCF Web API with MEF使用 MEF 在 WCF Web API 中建模客户端上下文
【发布时间】:2011-12-27 02:57:25
【问题描述】:

我需要在每个请求的开头提取几个标头值,并将它们放入一个 ClientContext 对象中,MEF 可以将该对象注入我的应用程序代码中。我正在使用 WCF Web API 的预览版 5,但没有办法做到这一点。

在“标准”WCF 中,我将创建一个实现 IExtension 的类,并具有以下属性将它们连接在一起:

[Export(typeof(IClientContext)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public static ClientContextExtension Current
{
    get
    {
        var operationContext = OperationContext.Current;

        if (operationContext == null)
            return null;

        var extension = operationContext.Extensions.Find<ClientContextExtension>();

        if (extension == null)
        {
            extension = new ClientContextExtension();

            operationContext.Extensions.Add(extension);
        }

        return extension;
    }
}

自定义 DelegatingHandler 调用 ClientContextExtension.Current 并根据标头值设置属性。不幸的是,使用 WCF Web API,OperationContext.Current 始终为空!

我想不出一种方法来使用 Web API 进行这项工作。任何帮助表示赞赏!!!

【问题讨论】:

    标签: wcf-web-api


    【解决方案1】:

    我想出了一个可行的解决方案,但对其他选择持开放态度。首先,原始方法背后的一些基本原理......

    因为 WCF 使用线程池,所以基于每线程模型的任何内容都可能(并且将会)具有超出单个请求的生命周期。我需要一种方法来存储从每个请求的 HTTP 标头中提取的客户端上下文信息,因为每次信息都会不同。这意味着我不能为每个线程保留上下文信息,因为线程将被重复使用。

    或者我可以吗?

    我的逻辑缺陷是线程重用是问题所在。实际上,每个线程一次只服务一个请求,从而使该线程中的任何信息都与该请求隔离。因此,我需要做的就是确保信息与该请求相关并且我的问题得到解决。

    我的解决方案是重构 Current 属性以引用标有 [ThreadStatic()] 属性的私有静态字段,确保每个实例都特定于线程。然后,在为每个请求执行的 DelegatingHandler 中,我为该请求重置对象的属性。在该请求期间对 Current 的后续调用会返回特定于请求的信息,并且线程处理的下一个请求会在 DelegatingHandler 中更新,因此就我的其他代码而言,上下文是每个请求的。

    不完美,但它至少让我暂时启动并运行。正如我所说,我对其他解决方案持开放态度。

    更新

    仔细检查后,该解决方案不起作用,因为 DelegatingHandler 和使用上下文对象的服务代码之间没有线程关联。结果,有时我检索 ThreadStatic 对象的调用按预期工作,但在其他情况下,我得到一个新实例,因为代码在与处理程序不同的线程上运行。

    因此,请忽略此解决方案。回到绘图板。

    更新我的更新

    在与 Glenn Block 讨论了我的问题后,事实证明这只是确保在请求处理程序(服务)正在执行的同一线程上设置上下文的问题。解决方案是使用 HttpOperationHandler 而不是 MessageHandler。

    根据 Glenn 的说法,消息处理程序是异步操作的,这意味着它们可以在与请求处理程序(服务)不同的线程上执行,因此我们不应该在消息处理程序中做任何需要线程关联的事情。另一方面,操作处理程序与请求处理程序在同一线程上同步运行,因此我们可以依赖线程亲和性。

    所以,我只是将我的代码从 MessageHandler 移动到 HttpOperationHandler 并获得了想要的结果。

    您可以在此处阅读完整说明:http://sonofpirate.blogspot.com/2011/11/modeling-client-context-in-wcf-web-api.html

    【讨论】:

      【解决方案2】:

      你可以尝试使用一个

      HttpOperationHandler<HttpRequestMessage, HttpRequestMessage>
      

      在那里你应该能够访问标题。

      【讨论】:

      • 我的问题不是访问标头值本身,而是以每个请求的方式持久化 ClientContext 对象。使用标准 WCF,可以使用 OperationContext。但是对于 Web API,OperationContext.Current 始终为 null。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-28
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 2021-01-11
      相关资源
      最近更新 更多