我只是更深入地研究它并发现了新的细节。
通常不是“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¶2=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"];
}
//...
}