3

I just dived a little deeper into it and discovered new details.

Not the 'UriTemplate' in general causes the 2nd invocation of 'AfterReceiveRequest' but the optional parameter within!

If I call the method by

http:/ /myserver/result/val1

AfterReceiveRequest will be invoked twice.

If I pass all possible parameters like

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

there will be no useless invocation. Is that behavior as intended?

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

--- following the initial post, just for information ---

While implementing a WCF REST Service System I stuck on a problem with the http-headers.

In my ServiceContract there is a method with an UriTemplate definition at the WebGet attribute, so it can be called via

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

instead of

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

(I need this because of compatibility reasons.)

Also there is a significant value in the http-headers collection, that I need to read. Therefore I implement IDispatchMessageInspector and add this inspector to the EndpointDispatchers MessageInspectors collection. By that the AfterReceiveRequest will be invoked by WCF and I can access WebOperationContext.Current.IncomingRequest.Headers to read the desired Value.

The Problem:

WCF solves the UriTemplate-mapping by generating a second request to the destination method, but does not pass the header entries from the original call to the generated second call. So AfterReceiveRequest (and of course BeforeSendReply, too) will be invoked twice, but the header-values from the real client call are only included in the first call.

Also I found no way to correlate the first and the second AfterReceiveRequest call, to implement a "special way" for passing the header-value from the first to the second call.

Is there a way to tell WCF to route the headers to the UriTemplate-redirected second call?

Here are some code fragments to make it clear:

[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"];
    }
    //...
}
Heiko
  • 67
  • 6

0 Answers0