异常 de-serializing SOAP XML 到对象

Exception de-serializing SOAP XML into Object

我正在开发可以接受和 return SOAP 1.1 消息的 WCF 服务。但是,我在将 SOAP 主体反序列化为我的对象时遇到问题。目前我有;

namespace MyAPI
{    
    [ServiceContract]
    public interface IMyService
    {
        [OperationContract(IsOneWay = false, Action = "*", ReplyAction = "*")]     
        [WebInvoke(Method = "POST",           
           BodyStyle = WebMessageBodyStyle.Bare, RequestFormat=WebMessageFormat.Xml)]
        Message ProcessMessgae(Message message);       
    }
}

public class MyService : IMyService
{  
    public Message ProcessMessgae(Message message)
    {
        MessageBuffer buffer = message.CreateBufferedCopy(8192);

        // Get a copy of the original message.
        Message msgCopy = buffer.CreateMessage();

        // Take another copy of the same message. 
        Message returnMsg = buffer.CreateMessage();

        // Use the msgCopy to get an XML and extract the body contents. Once this message has been read and consumed,

        System.Xml.XmlDictionaryReader xrdr = msgCopy.GetReaderAtBodyContents();

        string bodyData = xrdr.ReadOuterXml();

        var reader = new StringReader(bodyData);
        var serializer = new XmlSerializer(typeof(OTA_HotelAvailRQ));
        var instance = (OTA_HotelAvailRQ)serializer.Deserialize(reader);

        return returnMsg; 
    }
}

这是我的auto-generated对象

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.7.2046.0")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.opentravel.org/OTA/2003/05")]
public partial class OTA_HotelAvailRQ : object, System.ComponentModel.INotifyPropertyChanged
{

    private string echoTokenField;

    private System.DateTime timeStampField;

    private bool timeStampFieldSpecified;

    private bool targetFieldSpecified;

    private decimal versionField;

    private bool availRatesOnlyField;

    private bool availRatesOnlyFieldSpecified;

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public string EchoToken
    {
        get
        {
            return this.echoTokenField;
        }
        set
        {
            this.echoTokenField = value;
            this.RaisePropertyChanged("EchoToken");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public System.DateTime TimeStamp
    {
        get
        {
            return this.timeStampField;
        }
        set
        {
            this.timeStampField = value;
            this.RaisePropertyChanged("TimeStamp");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool TimeStampSpecified
    {
        get
        {
            return this.timeStampFieldSpecified;
        }
        set
        {
            this.timeStampFieldSpecified = value;
            this.RaisePropertyChanged("TimeStampSpecified");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public decimal Version
    {
        get
        {
            return this.versionField;
        }
        set
        {
            this.versionField = value;
            this.RaisePropertyChanged("Version");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public bool AvailRatesOnly
    {
        get
        {
            return this.availRatesOnlyField;
        }
        set
        {
            this.availRatesOnlyField = value;
            this.RaisePropertyChanged("AvailRatesOnly");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool AvailRatesOnlySpecified
    {
        get
        {
            return this.availRatesOnlyFieldSpecified;
        }
        set
        {
            this.availRatesOnlyFieldSpecified = value;
            this.RaisePropertyChanged("AvailRatesOnlySpecified");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName)
    {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null))
        {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

但是,当我 运行 代码时,我在以下行中遇到异常 var instance = (OTA_HotelAvailRQ)serializer.Deserialize(reader);

我发布的 SOAP XML 是;

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <SOAP-ENV:Header xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <wsse:Security soap:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <wsse:UsernameToken> <wsse:Username>test</wsse:Username> <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">thebest</wsse:Password> </wsse:UsernameToken> </wsse:Security> </SOAP-ENV:Header> <SOAP-ENV:Body xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> <OTA_HotelAvailRQ xmlns="http://www.opentravel.org/OTA/2003/05" Version="1.0" TimeStamp="2005-08-01T09:30:47+02:00" EchoToken="fb57388d" AvailRatesOnly="true"> </OTA_HotelAvailRQ> </SOAP-ENV:Body> </SOAP-ENV:Envelope>

实际异常是;

如果将命名空间添加到 xmlserializer 会发生什么情况?

var instance = (OTA_HotelAvailRQ)serializer.Deserialize(reader, "http://www.opentravel.org/OTA/2003/05");

另一种选择是执行类似下面的操作,您可能必须使用 ReadOuterXml() 而不是 ReadInnerXml,命名空间也可以从此方法中删除:

System.Xml.Linq.XElement body = System.Xml.Linq.XElement.Parse(msgCopy.GetReaderAtBodyContents().ReadInnerXml());
var instance = Deserialize<OTA_HotelAvailRQ>(body, "http://www.opentravel.org/OTA/2003/05");

public static T Deserialize<T>(XElement xElement, string nameSpace)
{
    using (MemoryStream memoryStream = new MemoryStream(Encoding.ASCII.GetBytes(xElement.ToString())))
    {
        XmlSerializer xmlSerializer = new XmlSerializer(typeof(T), nameSpace);
        return (T)xmlSerializer.Deserialize(memoryStream);
    }
}

如果您仍然遇到问题,还有一种使用 DataContractSerializerSoapreflectionImporter 的方法,但您没有非常复杂的对象,这些方法可能有点矫枉过正。