UriTemplate的可选参数导致两次AfterReceiveRequest调用 - WCF - IDispatchMessageInspector

时间:2014-09-11 14:39:17

标签: c# wcf http-headers url-redirection uritemplate

我只是深入了解它并发现了新的细节。

不是'UriTemplate'一般会导致第二次调用'AfterReceiveRequest',而是在!

中的可选参数

如果我通过

调用方法
  

http:/ / myserver / result / val1

AfterReceiveRequest将被调用两次。

如果我传递了所有可能的参数,例如

  

http:/ / myserver / result / val1 / val2 / val3

没有无用的调用。这种行为是否符合预期?

UriTemplate = "result/{para1=null}/{para2=null}/{para3=null}"

---在首发后,仅供参考---

在实施WCF REST服务系统时,我遇到了http-headers的问题。

ServiceContract我的UriTemplate属性中有一个WebGet定义的方法,因此可以通过

调用
http://server/resource/val1/val2 ...

而不是

http://server/resource?para1=val1&para2=val2 ...

(由于兼容性原因,我需要这个。)

http-headers 集合中还有一个重要的值,我需要阅读。因此,我实施IDispatchMessageInspector并将此检查器添加到EndpointDispatchers MessageInspectors集合中。由此,WCF将调用AfterReceiveRequest,我可以访问WebOperationContext.Current.IncomingRequest.Headers以读取所需的值。

问题:

WCF通过生成对目标方法的第二个请求来解决UriTemplate - 映射,但是没有将头条目从原始调用传递给生成第二个电话。因此,AfterReceiveRequest(当然还有BeforeSendReply)将被调用两次,但来自真实客户端调用的标头值仅包含在第一次调用中。

此外,我发现没有办法关联第一个和第二个AfterReceiveRequest调用,以实现一个“特殊方式”,用于将标头值从第一个调用传递到第二个调用。

有没有办法告诉WCF将标题路由到UriTemplate - 重定向的第二个电话?

以下是一些明确的代码片段:

[ServiceContract]
public interface IMyService
{
    [WebGet(UriTemplate = "result/{para1=null}/{para2=null}/{para3=null}")]
    bool MyMethod(string para1, string para2, string para3);
}

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
[MyServiceInspectorBeavior]
public class MyService : IMyService
{
    public bool MyMethod(string para1, string para2, string para3)
    {
        return DoTheWork();
    }
    //...
}

public class MyServiceInspectorBeavior : Attribute, IServiceBehavior
{

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (EndpointDispatcher epDispatcher in serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>().SelectMany(cDispatcher => cDispatcher.Endpoints))
        {
            epDispatcher.DispatchRuntime.MessageInspectors.Add(new MyInspector());
        }
    }

    //...
}

public class MyInspector : IDispatchMessageInspector
{
    //this is invoked twice for each client request, 
    //but only at the first call the header is present...
    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        WebHeaderCollection webOpContext = 
                      WebOperationContext.Current.IncomingRequest.Headers;
        string xForwardedIp = webOpContext["X-FORWARDED-IP"];
        WriteLog(xForwardedIp);

        return OperationContext.Current.IncomingMessageProperties["ActivityId"];
    }
    //...
}

0 个答案:

没有答案