An external (java) app sends messages to our web service. This message contains multiple namespaces:
<StUF:Fo01Bericht xmlns:StUF="http://www.egem.nl/StUF/StUF0300">
<LVO:stuurgegevens xmlns:LVO="http://www.vrom.nl/StUF/sector/lvo/0305">
<StUF:versieStUF>0300</StUF:versieStUF>
<StUF:berichtcode>Fo01</StUF:berichtcode>
</LVO:stuurgegevens>
<StUF:body>
<StUF:code>200</StUF:code>
<StUF:plek>LVO</StUF:plek>
<StUF:omschrijving>test</StUF:omschrijving>
</StUF:body>
</StUF:Fo01Bericht>
The WCF service cannot deserialize this message because of the LVO prefix on the second line (it should have been StUF according to the WSDL).
I want to get our web service to accept these messages. Is there a way to do this - preferably using attributes?
I had this issue when accepting soap message from a third party.
Here is the soapHeader i was being sent(Note the different namespaces within UsernameToken):
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wssu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>userName</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">password</wsse:Password>
<wsse:Nonce>nonce</wsse:Nonce>
<wssu:Created>2015-02-19T16:24:32Z</wssu:Created>
</wsse:UsernameToken>
</wsse:Security>
To deserialize properly i needed to implement IxmlSerializable, in my DataContract, as below:
[DataContract(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", Name = "Security")]
public partial class SecurityHeaderType
{
[XmlElementAttribute(Namespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")]
[DataMember]
public UsernameToken UsernameToken { get; set; }
}
public class UsernameToken : IXmlSerializable
{
public string Username { get; set; }
public string Password { get; set; }
public string Nonce { get; set; }
public string Created { get; set; }
public XmlSchema GetSchema()
{
throw new NotImplementedException();
}
public void ReadXml(XmlReader reader)
{
Dictionary<string, string> secDictionary;
string xml = reader.ReadOuterXml();
using (var s = GenerateStreamFromString(xml))
{
secDictionary =
XElement.Load(s).Elements()
.ToDictionary(e => e.Name.LocalName, e => e.Value);
}
Username = secDictionary["Username"];
Password = secDictionary["Password"];
Nonce = secDictionary["Nonce"];
Created = secDictionary["Created"];
}
I was then able to deserialize my header as below:
if (OperationContext.Current.IncomingMessageHeaders.FindHeader("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd") != -1)
{
var securityHeader = OperationContext.Current.IncomingMessageHeaders.GetHeader<SecurityHeaderType>("Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
}
I don't believe you can accomplish that through modifying the DataContract namespaces. The reason is the DataMember attribute reasonably assumes the class properties are in the same XML namespace as the class itself. However, you may be able to do this with a combination of MessageContract and MessageBodyMember attributes. Another possibly simpler alternative is to implement a message inspector to reformat the soap message to comply with the expected XML schema.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With