Optional parameter of at UriTemplate causes twice invoces of AfterReceiveRequest - WCF - IDispatchMessageInspector RRS feed

  • Question

  • 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://server/result/val1" AfterReceiveRequest will be invoked twice.

    If I pass all possible parameters like "http://server/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/result/val1/val2 ...
    instead of

        http://server/MyMethod?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:  

        public interface IMyService
            [WebGet(UriTemplate = "result/{para1=null}/{para2=null}/{para3=null}")]
            bool MyMethod(string para1, string para2, string para3);
        [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
        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 = 
                string xForwardedIp = webOpContext["X-FORWARDED-IP"];
                return OperationContext.Current.IncomingMessageProperties["ActivityId"];

    • Edited by Heiko Wrede Thursday, September 25, 2014 3:31 PM new facts
    Thursday, September 25, 2014 9:16 AM

All replies

  • I think the principals of REST are violated when you pass parameters on the query string, and especially so when you pass multiple query string parameters. http://en.wikipedia.org/wiki/Clean_URL

    If you need to pass more than one parameter into the service you can use a comma separated list. For example, a service which draws a rectangle could receive two integers representing the length of the sides as input, separated by a comma.

    Friday, September 26, 2014 8:44 AM