Stitch10925
Stitch10925

Reputation: 182

Adding a Namespace to a MessageContract (WCF)

I am trying to create a SOAP message to send to an SAP endpoint, however, I am having trouble setting the namespace correctly. I have been trying for days and tried many suggestions I found online, but none seem to work. I am hoping some of you can help me.

This is an example of the C# code that I have:

[ServiceContract]
[XmlSerializerFormat]
public interface IWcfClient
{
    [OperationContract(IsOneWay = true)]
    void SendUpdates(UpdateRequest request);
}

[MessageContract(IsWrapped = true, WrapperName = "MyRoot", WrapperNamespace = "myNamespace")]
public class UpdateRequest
{
    [MessageBodyMember]
    [XmlElement(ElementName = "updateType")]
    public byte UpdateType { get; internal set; }

    [MessageBodyMember]
    [XmlElement(ElementName = "updateEntry")]
    public UpdateEntry[] UpdateEntries { get; set; }
}

public class UpdateEntry
{
    [XmlElement]
    public string DeviceId { get; set; }

    [XmlElement]
    public DateTime LastSeen { get; set; }
}

This results in the SOAP body looking something like this:

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <MyRoot xmlns="myNamespace">
        <updateEntry>
            <DeviceId>12345</DeviceId>
            <LastSeen>2017-04-24T14:44:30.8030649Z</LastSeen>
        </updateEntry>
        <updateEntry>
            <DeviceId>56789</DeviceId>
            <LastSeen>2017-05-03T01:33:02.084Z</LastSeen>
        </updateEntry>
        <updateType>2</updateType>
    </MyRoot>
</s:Body>

What I am trying to achieve, is to add another namespace to the root and have the sub-elements use that namespace. In end effect I am looking for a result similar to this (mySecondNamespace):

<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <MyRoot xmlns="myNamespace" xmlns:a="mySecondNamespace">
        <a:updateEntry>
            <a:DeviceId>12345</a:DeviceId>
            <a:LastSeen>2017-04-24T14:44:30.8030649Z</a:LastSeen>
        </a:updateEntry>
        <a:updateEntry>
            <a:DeviceId>56789</a:DeviceId>
            <a:LastSeen>2017-05-03T01:33:02.084Z</a:LastSeen>
        </a:updateEntry>
        <a:updateType>2</a:updateType>
    </MyRoot>
</s:Body>

I have tried:

But nothing seems to work. Adding the namespace to the XmlElement seems to have effect, but in that case the namespace is not on the root element and is not propagated to the underlying elements. Any ideas?

Upvotes: 0

Views: 2050

Answers (1)

Stitch10925
Stitch10925

Reputation: 182

After a long search I finally found the solution to my problem. What I had to do was to switch to the XmlSerializerFormat on the OperationContract instead of on the Interface itself and update the contracts accordingly:

[ServiceContract]
public interface IWcfClient
{
    [XmlSerializerFormat]
    [OperationContract(IsOneWay = true)]
    void SendUpdates(UpdateRequest request);
}

[MessageContract(IsWrapped = false)]
public class UpdateRequest
{
    [MessageBodyMember(Name="UpdateEntry")]
    public UpdateEntry[] UpdateEntries { get; set; }
}

[Serializable]
[XmlType(Namespace = "myNamespace")]
public class UpdateEntry
{
    [XmlElement(ElementName = "UpdateEntry", Order = 0)]
    public Device[] DeviceInfo { get; set; }

    [XmlElement(ElementName = "UpdateType", Order = 1)]
    public byte UpdateType { get; set; }
}

[Serializable]
[XmlType(Namespace = "myNamespace")]
public class Device
{
    [XmlElement(ElementName = "DeviceId", Order = 0)]
    public string DeviceId { get; set; }

    [XmlElement(ElementName = "LastSeen", Order = 1)]
    public DateTime LastSeen { get; set; }
}

Upvotes: 1

Related Questions