簡體   English   中英

使用REST和WCF序列化為XML

[英]Serialization to XML using REST and WCF

我在使用REST並將響應作為XML返回時遇到問題。 我已經從模板創建了基本服務,一切看起來都不錯但是當我想序列化我的類並將其作為響應返回時,服務返回其他內容。

看一看:

[WebHelp(Comment = "Sample description for DoWork")]
[WebInvoke(UriTemplate = "DoWork")]
[OperationContract]
public SampleResponseBody DoWork(SampleRequestBody request)
{
    //TODO: Change the sample implementation here
    return new SampleResponseBody()
    {
        Value = String.Format("Sample DoWork response: '{0}'", request.Data)

    };
}

[WebHelp(Comment = "Returns order state based on client and order number")]
[WebInvoke(UriTemplate = "OrderStatus")]
[OperationContract]
public order_status OrderStatus(q_order_status request)
{   
    return new order_status() 
    {
        error_id = 0,
        client_acr = "client", 
        order_acr = "order"
    };
}

第一種方法來自模板,第二種方法是我的。 返回結構如下所示:

public class SampleResponseBody
{
    [DataMember]
    public string Value { get; set; }
}

public class q_order_status
{
    public string client_acr;
    public string order_acr;
}

[DataContract]
[XmlSerializerFormat]
public class order_status
{
    [XmlAttribute]
    public int error_id;
    [XmlElement]
    public string error_desc;
    [XmlElement]
    public string order_acr;
    [XmlElement]
    public string client_acr;
}

編輯:

當我在REST工具包的幫助頁面上時,我得到這個作為兩個方法的示例響應是錯誤的(我不應該為第二個方法得到這個):

<SampleResponseBody>
<Value>String content</Value>
</SampleResponseBody>

當我像這樣調用第一種方法:

User-Agent: Fiddler
Host: ipv4.fiddler:4617
Content-Type: text/xml
Content-Length: 63

<SampleRequestBody>
<Data>bla bla</Data>
</SampleRequestBody>

我收到:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/9.0.0.0
Date: Wed, 30 Sep 2009 09:41:20 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: application/xml; charset=utf-8
Content-Length: 141
Connection: Close

<SampleResponseBody xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Value>Sample DoWork response: 'bla bla'</Value></SampleResponseBody>

這沒關系。

我打電話給第二種方法是這樣的:

User-Agent: Fiddler
Host: ipv4.fiddler:4617
Content-Type: text/xml
Content-Length: 115

<q_order_status>
<client_acr>String content</client_acr>
<order_acr>String content</order_acr>
</q_order_status>

我得到這個:

HTTP/1.1 200 OK
Server: ASP.NET Development Server/9.0.0.0
Date: Wed, 30 Sep 2009 09:44:18 GMT
X-AspNet-Version: 2.0.50727
Cache-Control: private
Content-Type: application/xml; charset=utf-8
Content-Length: 67
Connection: Close

<order_status xmlns:i="http://www.w3.org/2001/XMLSchema-instance"/>

它應該返回一個序列化為類order_status XML實例有什么問題?

提前致謝。

編輯后:好的,問題是[OperationContract]沒有觸發XmlSerializer 必須在[OperationContract]之后插入[XmlSerializerFormat]以覆蓋默認的DataContractSerializer

使用WCF REST入門工具包,您應該能夠創建一個返回XElement作為其返回值的方法:

[WebHelp(Comment = "Returns order state based on client and order number")]
[WebInvoke(UriTemplate = "OrderStatus")]
[OperationContract]
public XElement OrderStatus(q_order_status request)
{   
  .....
}

在這種情況下,您的方法實現可能如下所示:

public XElement OrderStatus(q_order_status request)
{   
    return new XElement("q_order_status",
                 new XAttribute("error_id", 0),
                 new XElement("client_acr", "client acr value"),
                 new XElement("order_acr", "order acr value")
           );
}

這將返回一個這樣的XML片段:

<q_order_status error_id="0">
  <client_acr>client acr value</client_acr>
  <order_acr>order acr value</order_acr>
</q_order_status>

這樣,任何事情都是可能的 - 完全取決於你如何以及如何在XML結構方面創建。

我會說q_order_status應該用[DataContract]屬性進行修飾,並且他的所有成員(以及order_status的成員)都應該用[DataMember]屬性進行修飾。 或者你是故意忽略這些?

你可以試試這個order_status代碼:

[DataContract]
public class order_status
{
    [DataMember]
    public int error_id;
    [DataMember]
    public string error_desc;
    [DataMember]
    public string order_acr;
    [DataMember]
    public string client_acr;
}

旁注:我還建議您遵循類和成員的.NET命名約定,PascalCase和沒有下划線。 如果限制為給定的xml名稱,則可以使用DataContract / DataMember屬性的Name成員來定義xml名稱。 (例如:[DataContract(Name =“order_status”)]公共類OrderStatus)。 ;)

這個問題(和最后的編輯)幫助我們解決了類似的問題。 我們發現,如果我們的WCF服務改為使用XmlSerializerFormat,我們可以輕松地反序列化我們的對象,而不是使用DataContract / DataMember屬性和使用(默認)DataContractSerializer來裝飾數千個數據元素。

對於那些需要一個例子的人:

[System.ServiceModel.ServiceContract]
public interface IRestService
{
    [System.ServiceModel.OperationContract]
    // Added this attribute to use XmlSerializer instead of DataContractSerializer
    [System.ServiceModel.XmlSerializerFormat(
        Style=System.ServiceModel.OperationFormatStyle.Document)]
    [System.ServiceModel.Web.WebGet(
        ResponseFormat = System.ServiceModel.Web.WebMessageFormat.Xml,
        UriTemplate = "xml/objects/{myObjectIdentifier}")]
    MyObject GetMyObject(int myObjectIdentifier);
}

這就是我們反序列化對象的方式:

public static T DeserializeTypedObjectFromXmlString<T>(string input)
{
    T result;

    try
    {
        System.Xml.Serialization.XmlSerializer xs = new System.Xml.Serialization.XmlSerializer(typeof(T));
        using (System.IO.TextReader textReader = new System.IO.StringReader(input))
        {
            result = (T)xs.Deserialize(textReader);
        }
    }
    catch
    {
        throw;
    }

    return result;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM