2009-09-30 59 views
1

我遇到了使用REST並將響應作爲XML返回的問題。我從模板創建了基本的服務,一切看起來都很好,但是當我想序列化我的類並將其作爲響應返回時,該服務返回其他內容。使用REST和WCF序列化爲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> 

WHIS是確定的。

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

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

它應該返回一個序列化類的XML實例order_status 什麼是錯的?

在此先感謝。

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

回答

4

隨着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結構。

馬克

+0

marc_s:謝謝,這是實現這一目標的方法之一。但是如果我想序列化一些包含其他對象的大對象呢?在這個解決方案中,我沒有串行器功能..或者我錯了嗎? – Wodzu 2009-09-30 13:25:45

+0

當然!你可以有你的'q_order_status'類,只需手動實例化一個XmlSerializer,並將該類型的對象序列化爲一個字符串並將其作爲XElement返回。這應該工作得很好。 – 2009-09-30 13:46:06

+0

感謝您的提示。我將不得不閱讀更多關於LINQ的信息。 – Wodzu 2009-09-30 16:02:43

0

我會說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; 
} 

附註:我也建議你遵循類和成員,PascalCase沒有下劃線.NET命名約定。如果限制爲給定的xml名稱,則可以使用DataContract/DataMember屬性的Name成員來定義xml名稱。 (例如:[DataContract(Name =「order_status」)] public class OrderStatus)。;)

+0

@Philippe:* q_order_status *作爲參數傳遞,它工作正常。我需要在反序列化的XML中返回* order_status *。我通過HTTP正確地調用服務,但我會告訴你如何。 NET約定:問題是我需要將它反序列化爲確切的XML結構,而這個XML結構並不是由我定義的。 – Wodzu 2009-09-30 09:35:37

+0

您可以嘗試將[DataMember]屬性添加到order_status類的所有成員嗎? – Philippe 2009-09-30 09:50:11

+0

再次提醒您:您可以遵循.NET命名約定,並使用DataContract/DataMember屬性的Name成員定義該元素的xml名稱:http://msdn.microsoft.com/zh-cn/library/system.runtime .serialization.datacontractattribute.name.aspx – Philippe 2009-09-30 09:51:50

0

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

對於那些誰需要一個例子:

[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; 
} 
+0

我很高興它幫助你! – Wodzu 2011-12-01 06:43:58