2009-09-30 58 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