3

我只是更深入地研究它并发现了新的细节。

通常不是“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集合中。这样AfterReceiveRequest,WCF 将调用 WCF,我可以访问WebOperationContext.Current.IncomingRequest.Headers以读取所需的值。

问题:

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

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

有没有办法告诉 WCF 将标头路由到UriTemplate-redirected 第二个调用?

这里有一些代码片段可以清楚地说明:

[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"];
    }
    //...
}
4

0 回答 0