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&para2=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 transformation UriTemplate

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

      

+3


source to share





All Articles