Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The message with Action cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher

Tags:

c#

wcf

Thanks for stopping by. I thought I'd share a face-palm moment I experienced when building out a WCF service. And while I had eventually came to find the answer. It was so infuriatingly simple, but the I had lost hours over one misplaced character. So I figured, I'd 'pay-it-forward' and share how I had figured out the solution.

The full error message: The message with Action 'http://Foo.bar.car/IPolicyService/GetPolicyData/' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None)

My client requirement was for sending SOAP messages w/out using a proxy class so that the payload always stayed in XML.

[ServiceContract(Namespace = "http://Foo.bar.car")]
public interface IPolicyService
{
    [OperationContract]
    PolicyResponse GetPolicyData(PolicyRequest request);
}

public class PolicyData : IPolicyService
{
   public PolicyResponse GetPolicyData(PolicyRequest request)
   {
            var polNbr = request.REQ_POL_NBR;
            return GetFakePolicyData(polNbr);
    }
}

This WebClient method worked:

using System.Net; 
using System.Xml.Linq;

public static class ClientHelper
{
    public static string Post(string targetUrl, string action, string method, string key, string value)
    {
        var request = BuildEnvelope(method, key, value);
    using (var webClient = new WebClient())
    {
        webClient.Headers.Add("Accept-Header", "application/xml+");
        webClient.Headers.Add("Content-Type", "text/xml; charset=utf-8");
        webClient.Headers.Add("SOAPAction", action);
        var result = webClient.UploadString(targetUrl, "POST", request);

        return result;
    }
}

public static string BuildEnvelope(string method, string key, string value)
{
    XNamespace s = "http://schemas.xmlsoap.org/soap/envelope/";
    XNamespace d = "d4p1";
    XNamespace tempUri = "http://tempuri.org/";
    XNamespace ns = "http://Foo.bar.car";
    XNamespace requestUri = "http://schemas.datacontract.org/2004/07/Foo.bar.car.Model.Policy";
    var xDoc = new XDocument(
                        new XElement(
                            s + "Envelope",
                            new XAttribute(XNamespace.Xmlns + "s", s),
                            new XElement(
                                s + "Body",
                                new XElement(
                                    ns + method,
                                    new XElement(requestUri + "request", 
                                        new XElement(tempUri + key, value))
                                )
                            )
                        )
                    );
    // hack - finish XDoc construction later
    return xDoc.ToString().Replace("request xmlns=", "request xmlns:d4p1=").Replace(key, "d4p1:" + key);
}

}

when called with:

return ClientHelper.Post("http://localhost:5050/PolicyService.svc", "http://Foo.bar.car/IPolicyService/GetPolicyData", "GetPolicyData", "REQ_POL_NBR", id);

But making the same call via a WCF message failed, giving me a frowny face...

    private static Message SendMessage(string id)
    {
        var body = new GetPolicyData {request =  new request{ REQ_POL_NBR = id }}; 
        var message = Message.CreateMessage(MessageVersion.Soap11, "http://Foo.bar.car/IPolicyService/GetPolicyData/", body);

        message.Headers.Add(MessageHeader.CreateHeader("Accept-Header", string.Empty, "application/xml+"));
        message.Headers.Add(MessageHeader.CreateHeader("Content-Type", string.Empty, "text/xml"));
        message.Headers.Add(MessageHeader.CreateHeader("FromSender", string.Empty, "DispatchMessage"));
        message.Headers.To = new System.Uri(@"http://localhost:5050/PolicyService.svc");

        var binding = new BasicHttpBinding(BasicHttpSecurityMode.None)
        {
             MessageEncoding = WSMessageEncoding.Text,
            MaxReceivedMessageSize = int.MaxValue,
            SendTimeout = new TimeSpan(1, 0, 0),
            ReaderQuotas = { MaxStringContentLength = int.MaxValue, MaxArrayLength = int.MaxValue, MaxDepth = int.MaxValue }
        };
        message.Properties.Add("Content-Type", "text/xml; charset=utf-8");
        message.Properties.Remove("Accept-Encoding");
        message.Properties.Add("Accept-Header", "application/xml+");

        var cf = new ChannelFactory<IRequestChannel>(binding, new EndpointAddress(new Uri("http://localhost:5050/PolicyService.svc")));

        cf.Open();
        var channel = cf.CreateChannel();
        channel.Open();

        var result = channel.Request(message);

        channel.Close();
        cf.Close();
        return result;
    }


[DataContract(Namespace = "http://Foo.bar.car")]
public class GetPolicyData
{
    [DataMember]
    public request request { get; set; }
}

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/Foo.bar.car.Model.Policy")]
public class request
{
    ///<summary>
    /// Define request parameter for SOAP API to retrieve selective Policy level data
    /// </summary>
    [DataMember]
    public string REQ_POL_NBR { get; set; }
}

Checking the web_messages.log only provided a red herring that sent me down the wrong rabbit hole. The version of the call that worked stored the action as [HttpRequest] SOAPAction http://Foo.bar.car/IPolicyService/GetPolicyData

whereas the failing call recorded that action in quotes as [HttpRequest] SOAPAction "http://Foo.bar.car/IPolicyService/GetPolicyData/"

Finding the solution required two things.

Recreating the client call using fiddler and getting that to work...

Post action:    http://localhost:5050/PolicyService.svc
Header:
User-Agent: Fiddler
SOAPAction: http://Foo.bar.car/IPolicyService/GetPolicyData
Content-type: text/xml
Host: localhost:5050
Content-Length: 381

Body:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Body>
    <GetPolicyData xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://Foo.bar.car">
    <request xmlns:d4p1="http://schemas.datacontract.org/2004/07/Foo.bar.car.Model.Policy">
    <d4p1:REQ_POL_NBR>1</d4p1:REQ_POL_NBR>
    </request>
    </GetPolicyData>
      </s:Body>
    </s:Envelope>

And probably more importantly Stepping away for an while to clear my head and eat something and look at the problem with a fresh pair of eyes.

I'll post the answer on Monday, but happily credit the person who finds that one character that had stumped me for longer than I'd care to admit...

like image 208
James Fleming Avatar asked May 10 '14 12:05

James Fleming


1 Answers

Remove the forward slash (/) at the end of the second parameter in the following method when you create the soap message: Message.CreateMessage(MessageVersion.Soap11, "http://Foo.bar.car/IPolicyService/GetPolicyData/", body);

like image 115
Kevin Hennessy Avatar answered Sep 30 '22 07:09

Kevin Hennessy