Optional parameter in UriTemplate makes calls to AfterReceiveRequest twice - WCF - IDispatchMessageInspector
I just dived into it a bit and discovered new details.
Not "UriTemplate" at all calls the 2nd call to "AfterReceiveRequest", but an optional parameter inside!
If I call the method
http: // myserver / result / val1
AfterReceiveRequest will be called twice.
If I pass in all possible parameters like
http: // myserver / result / val1 / val2 / val3
there will be no useless call. Is this behavior as intended?
UriTemplate = "result/{para1=null}/{para2=null}/{para3=null}"
--- after the initial message, for information only ---
While implementing WCF REST service system, I ran into problem with http headers.
In mine ServiceContract
there is a method with a definition UriTemplate
in the attribute WebGet
, so it can be called through
http://server/resource/val1/val2 ...
instead
http://server/resource?para1=val1¶2=val2 ...
(I need this for compatibility reasons.)
There is also significant value in the http-headers collection that I need to read. So I am implementing IDispatchMessageInspector
and adding this inspector to the collection EndpointDispatchers
MessageInspectors
. This AfterReceiveRequest
will call WCF and I can access WebOperationContext.Current.IncomingRequest.Headers
to read the value I want.
Problem:
WCF solves the transformationUriTemplate
by generating a second request to the destination method, but does not pass header records from the original call to the generated second call. This way
AfterReceiveRequest
(and of course
BeforeSendReply
also) will be called twice, but the header values from the real client call are only included in the first call.
Also I have not found a way to match the first and second calls AfterReceiveRequest
to implement a "special way" for passing the header value from the first to the second call.
Can WCF be told to route headers to the second call UriTemplate
?
Here are some code snippets to get them to understand:
[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"];
}
//...
}
source to share
No one has answered this question yet
Check out similar questions: