异常将SOAP XML反序列化为Object

时间:2017-06-14 16:53:00

标签: c# xml wcf soap xml-deserialization

我正在开发一个可以接受和返回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; 
    }
}

这是我自动生成的对象

/// <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 I&m; m发布是;

<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>

实际例外是:enter image description here

1 个答案:

答案 0 :(得分:1)

如果将命名空间添加到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,但您不会有一个非常复杂的对象,那些可能有点过分。