2012-10-12 5 views
4

저는 Windows Store 응용 프로그램을 작성 중입니다. SOAP 메시지의 세부 사항 비 직렬화

나는 다음과 같은 수동으로 만든 오류 클래스가 있습니다

<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Body><env:Fault><faultcode>env:Server</faultcode><faultstring>internal error</faultstring><detail><ns2:InnerException xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://ns1.my.namespace.com" xmlns:ns2="http://my.namespace.com" xmlns:ns3="http://ns3.my.namespace.com"><message>internal error</message></ns2:InnerException ></detail></env:Fault></env:Body></env:Envelope> 

내가 그것을 같다 읽으려고 오전 방법 :

[XmlRoot(Namespace = "http://schemas.xmlsoap.org/soap/envelope/", ElementName = "Fault")] 
public partial class SoapFault 
{ 
    [XmlElement(Form = XmlSchemaForm.Unqualified, ElementName = "faultcode")] 
    public String FaultCode { get; set; } 

    [XmlElement(Form = XmlSchemaForm.Unqualified, ElementName = "faultstring")] 
    public String FaultDescription { get; set; } 

    [XmlElement(Form = XmlSchemaForm.Unqualified, ElementName = "detail")] 
    public InnerException[] Detail { get; set; } 
} 

    [XmlType(Namespace = "http://my.namespace.com", TypeName = "InnerException")] 
    public partial class InnerException 
    { 
     [XmlElement(Form = XmlSchemaForm.Unqualified, ElementName = "message")] 
     public String Message { get; set; } 
    } 

이 내가 읽으려고하고있는 서버의 응답입니다 다음과 같습니다 :

using (XmlReader reader = XmlReader.Create(await response.Content.ReadAsStreamAsync())) 
{ 
    string SoapNamespace = "http://schemas.xmlsoap.org/soap/envelope/"; 
    try 
    { 
     var serializer = new XmlSerializer(typeof(SoapFault)); 

     reader.ReadStartElement("Envelope", SoapNamespace); 
     reader.ReadStartElement("Body", SoapNamespace); 

     var fault = serializer.Deserialize(reader) as SoapFault; 

     reader.ReadEndElement(); 
     reader.ReadEndElement(); 
    } 
    catch(Exception ex) 
    { 
     throw new Exception("Exception was thrown:" + ex.Message); 
    } 
} 

XmlElement 특성을 변경하면 네임 스페이스를 추가하려했지만 항상 끝납니다. SoapFault의 Detail 속성이 NULL로 설정됩니다. 개체를 형식을 변경할 때 적어도 데이터가 들어있는 XmlNode 집합을 가져옵니다.

직렬화에서 올바른 클래스를 구현하려면이 코드에서 무엇을 변경해야합니까?

참고 : 저는 불행히도 전화를 수동으로 만들어야하며 자동 생성 코드를 사용할 수 없습니다.

답변

6

무겁게 How to Deserialize XML document에 의해 영감을 받아, 나는 이것이 트릭을해야한다고 생각합니다. 다음과 같이

나는 클래스를 생성 :

  1. 디스크에 저장하기 위해 XML 서버 응답 (C : \ 임시 \의 reply.xml)
  2. XSD에 c : \ 임시 \ reply.xml/O를 : " c : \ temp "
  3. xsd c : \ temp \ reply.xsd reply_app1.xsd/classes/o :"c : \ temp "
  4. reply_app1.cs를 프로젝트에 추가하십시오.

    //------------------------------------------------------------------------------ 
    // <auto-generated> 
    //  This code was generated by a tool. 
    //  Runtime Version:4.0.30319.269 
    // 
    //  Changes to this file may cause incorrect behavior and will be lost if 
    //  the code is regenerated. 
    // </auto-generated> 
    //------------------------------------------------------------------------------ 
    
    using System.Xml.Serialization; 
    
    // 
    // This source code was auto-generated by xsd, Version=4.0.30319.1. 
    // 
    
    /// <remarks/> 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 
    [System.SerializableAttribute()] 
    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.ComponentModel.DesignerCategoryAttribute("code")] 
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")] 
    [System.Xml.Serialization.XmlRootAttribute(Namespace="http://schemas.xmlsoap.org/soap/envelope/", IsNullable=false)] 
    public partial class Envelope { 
    
        private EnvelopeBody[] itemsField; 
    
        /// <remarks/> 
        [System.Xml.Serialization.XmlElementAttribute("Body")] 
        public EnvelopeBody[] Items { 
         get { 
          return this.itemsField; 
         } 
         set { 
          this.itemsField = value; 
         } 
        } 
    } 
    
    /// <remarks/> 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 
    [System.SerializableAttribute()] 
    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.ComponentModel.DesignerCategoryAttribute("code")] 
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")] 
    public partial class EnvelopeBody { 
    
        private EnvelopeBodyFault[] faultField; 
    
        /// <remarks/> 
        [System.Xml.Serialization.XmlElementAttribute("Fault")] 
        public EnvelopeBodyFault[] Fault { 
         get { 
          return this.faultField; 
         } 
         set { 
          this.faultField = value; 
         } 
        } 
    } 
    
    /// <remarks/> 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 
    [System.SerializableAttribute()] 
    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.ComponentModel.DesignerCategoryAttribute("code")] 
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")] 
    public partial class EnvelopeBodyFault { 
    
        private string faultcodeField; 
    
        private string faultstringField; 
    
        private EnvelopeBodyFaultDetail detailField; 
    
        /// <remarks/> 
        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
        public string faultcode { 
         get { 
          return this.faultcodeField; 
         } 
         set { 
          this.faultcodeField = value; 
         } 
        } 
    
        /// <remarks/> 
        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
        public string faultstring { 
         get { 
          return this.faultstringField; 
         } 
         set { 
          this.faultstringField = value; 
         } 
        } 
    
        /// <remarks/> 
        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
        public EnvelopeBodyFaultDetail detail { 
         get { 
          return this.detailField; 
         } 
         set { 
          this.detailField = value; 
         } 
        } 
    } 
    
    /// <remarks/> 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 
    [System.SerializableAttribute()] 
    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.ComponentModel.DesignerCategoryAttribute("code")] 
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://schemas.xmlsoap.org/soap/envelope/")] 
    public partial class EnvelopeBodyFaultDetail { 
    
        private InnerException innerExceptionField; 
    
        /// <remarks/> 
        [System.Xml.Serialization.XmlElementAttribute(Namespace="http://my.namespace.com")] 
        public InnerException InnerException { 
         get { 
          return this.innerExceptionField; 
         } 
         set { 
          this.innerExceptionField = value; 
         } 
        } 
    } 
    
    /// <remarks/> 
    [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.0.30319.1")] 
    [System.SerializableAttribute()] 
    [System.Diagnostics.DebuggerStepThroughAttribute()] 
    [System.ComponentModel.DesignerCategoryAttribute("code")] 
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://my.namespace.com")] 
    [System.Xml.Serialization.XmlRootAttribute(Namespace="http://my.namespace.com", IsNullable=false)] 
    public partial class InnerException { 
    
        private string messageField; 
    
        /// <remarks/> 
        [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)] 
        public string message { 
         get { 
          return this.messageField; 
         } 
         set { 
          this.messageField = value; 
         } 
        } 
    } 
    

    예,이 자동 생성됩니다,하지만 난 그게 당신이 역 직렬화 할 수있을 것입니다 클래스를 생성 할 수있는 가장 쉬운 방법이 될 것이라고 생각 :

는이 결과. 다음과 같이 할 수 있습니다 :

정확하게 Detail 속성을 선택했습니다. 귀하의 경우에는 new StringReader(document.OuterXml) 대신 이전에했던 것처럼 XmlReader을 사용해야하며이를 사용하는 블록 등으로 포장해야합니다.

역 직렬화 된 객체의 속성 이름 중 일부는 SoapFault 클래스 (예 : Envelope)에있는 것과 정확히 일치하고 속성 중 일부는 단일 객체보다는 배열로 표현되지만 필요에 따라 Xsd를 조정할 수 있습니다. 위의 3 단계에서

+1

, 2 단계 이상에서 2 파일이 생성 된 경우 모두 xsd에 인수로 나열해야 할 수 있습니다. ** xsd ** * reply.xsd * * reply_app1.xsd * * reply_app2.xsd * ... etc – mungflesh

+0

당신은 생명을 구하는 사람입니다 – Yiping