Search code examples
asp.netwcfsoapxmlserializermessagecontract

WCF MessageContract not binding to classes - MessageContract is Null in endpoint


I am trying to receive a request in WCF. I need to respond with a MessageContract, therefore I need to take a MessageContract as input. I cannot alter the input SOAP request and must accept it as is.

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <wsa:To>http://localhost/SomeService.svc</wsa:To>
    <wsa:MessageID soapenv:mustUnderstand="true">urn:uuid:72A256A3317AF1411C1719318536115</wsa:MessageID>
    <wsa:Action soapenv:mustUnderstand="true">urn:ihe:iti:2007:CrossGatewayQuery</wsa:Action>
</soapenv:Header>
<soapenv:Body>
    <query:AdhocQueryRequest
        xmlns:query="urn:oasis:names:tc:ebxml-regrep:xsd:query:3.0"
        xmlns:rs="urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0">
        <query:ResponseOption returnComposedObjects="true" returnType="ObjectRef" />
        <AdhocQuery id="urn:uuid:14d4debf-8f97-4251-9a74-a90016b0af0d" home="2.16.840.1.113883.3.9075">
            <Slot name="$XDSDocumentEntryPatientId">
                <ValueList>
                    <Value>'111111111^^^&amp;2.16.840.1.113883.4.1&amp;ISO'</Value>
                </ValueList>
            </Slot>
            <Slot name="$XDSDocumentEntryStatus">
                <ValueList>
                    <Value>('urn:oasis:names:tc:ebxml-regrep:StatusType:Approved', 'urn:oasis:names:tc:ebxml-regrep:StatusType:Deprecated')</Value>
                </ValueList>
            </Slot>
        </AdhocQuery>
    </query:AdhocQueryRequest>
</soapenv:Body>

</soapenv:Envelope>

I have tried to manually build the MessageContract. I have tried using paste special XML as classes in Visual Studio. I have tried creating classes from XML with online tool https://xmltocsharp.azurewebsites.net/. I even tried the approach defined here: https://stackoverflow.com/a/64321991/3298156 .

This is what I have and "think" should work:

[MessageContract(IsWrapped = false)]
public class DQ_RequestMessage
{
    [MessageBodyMember(Name = "AdhocQueryRequest", Namespace = "urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0")]
    public DQ_RequestBody Body { get; set; }

    public DQ_RequestMessage() { }

    public DQ_RequestMessage(DQ_RequestBody body)
    {
        Body = body;
    }
}

And, the body:

[XmlType(AnonymousType = true)]
public class DQ_RequestBody
{
    [XmlAttribute(AttributeName = "query", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string query { get; set; }


    [XmlAttribute(AttributeName = "rs", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string rs { get; set; }


    [XmlAttribute(AttributeName = "xsi", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public string xsi { get; set; }


    [XmlElement(ElementName = "ResponseOption", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public ResponseOption responseOption { get; set; }

    public class ResponseOption
    {
        [XmlAttribute(AttributeName = "returnComposedObjects")]
        public string returnComposedObjects { get; set; }

        [XmlAttribute(AttributeName = "returnType")]
        public string returnType { get; set; }
    }

    [XmlElement(ElementName = "AdhocQuery", Namespace = "")]
    public AdhocQuery adhocQuery { get; set; }

    public class AdhocQuery
    {
        [XmlAttribute(AttributeName = "id")]
        public string id { get; set; }

        [XmlAttribute(AttributeName = "home")]
        public string home { get; set; }

        [XmlElement(ElementName = "Slot")]
        public List<Slot> slot { get; set; }

        public class Slot
        {
            [XmlAttribute(AttributeName = "name")]
            public string name { get; set; }

            [XmlElement(ElementName = "ValueList")]
            public ValueList valueList { get; set; }

            public class ValueList
            {
                [XmlElement(ElementName = "Value")]
                public List<string> value { get; set; }

                public ValueList()
                {
                    value = new List<string>();
                }
            }
        } // Slot
    } // AdhocQuery
} // DQ_RequestBody

However, I am getting null in the code.

Any help would be appreciated.


Solution

  • Try this code:

    namespace WcfService10
    {
        [ServiceContract]
        public interface IService1
        {
    
            [OperationContract]
            XmlMessage SomeOperation(XmlMessage request);
        }
    
    
        [MessageContract]
        public class XmlMessage
        {
            [MessageHeader(Name = "To", Namespace = "http://www.w3.org/2005/08/addressing", MustUnderstand = true)]
            public string To;
    
            [MessageHeader(Name = "MessageID", Namespace = "http://www.w3.org/2005/08/addressing", MustUnderstand = true)]
            public string MessageID;
    
            [MessageHeader(Name = "Action", Namespace = "http://www.w3.org/2005/08/addressing", MustUnderstand = true)]
            public string Action;
    
            [MessageBodyMember(Name = "AdhocQueryRequest", Namespace = "urn:oasis:names:tc:ebxml-regrep:xsd:query:3.0")]
            public AdhocQueryRequestBody Body;
        }
    
        public class AdhocQueryRequestBody
        {
            [XmlElement(Namespace = "urn:oasis:names:tc:ebxml-regrep:xsd:rs:3.0")]
            public ResponseOption ResponseOption;
    
            [XmlElement(Namespace = "urn:oasis:names:tc:ebxml-regrep:xsd:rim:3.0")]
            public AdhocQuery AdhocQuery;
        }
    
        public class ResponseOption
        {
            [XmlAttribute]
            public bool returnComposedObjects;
    
            [XmlAttribute]
            public string returnType;
        }
    
        public class AdhocQuery
        {
            [XmlAttribute]
            public string id;
    
            [XmlAttribute]
            public string home;
    
            [XmlElement("Slot")]
            public Slot[] Slots;
        }
    
        public class Slot
        {
            [XmlAttribute]
            public string name;
    
            public ValueList ValueList;
        }
    
        public class ValueList
        {
            [XmlElement("Value")]
            public string[] Values;
        }
    }
    

    Service1.svc

        public class Service1 : IService1
        {
            public XmlMessage SomeOperation(XmlMessage request)
            {
                
                var response = new XmlMessage
                {
                    To = "http://localhost/SomeService.svc",
                    MessageID = "urn:uuid:response-message-id",
                    Action = "urn:ihe:iti:2007:CrossGatewayResponse",
                    Body = new AdhocQueryRequestBody
                    {
                        ResponseOption = new ResponseOption
                        {
                            returnComposedObjects = true,
                            returnType = "ObjectRef"
                        },
                        AdhocQuery = new AdhocQuery
                        {
                            id = "urn:uuid:response-adhoc-query-id",
                            home = "2.16.840.1.113883.3.9075",
                            Slots = new[]
                            {
                            new Slot
                            {
                                name = "$XDSDocumentEntryPatientId",
                                ValueList = new ValueList
                                {
                                    Values = new[] { "response-patient-id" }
                                }
                            },
                            new Slot
                            {
                                name = "$XDSDocumentEntryStatus",
                                ValueList = new ValueList
                                {
                                    Values = new[] { "response-status" }
                                }
                            }
                        }
                        }
                    }
                };
                return response;
            }
        }
    }
    

    Output:

    enter image description here

    More details you can work on further.