這是一個常見的問題 - 你想從WCF服務中返回一個對象作爲XML,但是你希望或者需要將一些或者所有的屬性值作爲XML屬性而不是XML元素來傳遞;但你不能這樣做,因爲DataContractSerializer不支持屬性(如果你已經完成了網絡搜索,你很可能會看到這個StackOverflow QA)。很可能您已經將所有WCF服務代碼遷移到了使用XmlSerializer(具有所有XmlElement/XmlAttribute/XmlType屬性等) - 並且您大聲詛咒。
嗯,我在這裏是爲了拯救你,因爲這是可能的 - 而且問題的答案實際上是從MSDN文章「數據合約序列化器支持的類型」中推斷出來的。
我要給出的例子純粹僅用於說明目的。我沒有太多時間,所以和我一起工作! •創建一個新的Asp.Net WCF服務應用程序,您可以使用Cassini作爲您的Web服務器(可能更容易 - 否則您可能必須啓用Asp.Net兼容模式)。 •打開web.config並刪除爲新服務創建的元素。 •這個例子的接口和實現模型是矯枉過正的。將[ServiceContract]和[OperationContract]聲明從爲新服務創建的接口移動到也創建的類。刪除界面。 •打開.svc標記文件並在最後添加以下內容:Factory =「System.ServiceModel.Activation.WebServiceHostFactory」 - 這將爲此服務啓用零配置WCF模型(我們將創建一個RESTful服務) 。 •以下類聲明粘貼到您的代碼隱藏SVC:
public interface IExampleData
{
string Description { get; set; }
string Name { get; set; }
int ID { get; set; }
}
public class ExampleData : IExampleData
{
public string Description { get; set; }
public string Name { get; set; }
public int ID { get; set; }
}
public class ExampleDataAttributed : ExampleData, IXmlSerializable
{
#region IXmlSerializable Members
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(System.Xml.XmlReader reader)
{
//implement if remote callers are going to pass your object in
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteAttributeString("id", ID.ToString());
writer.WriteAttributeString("name", Name);
//we'll keep the description as an element as it could be long.
writer.WriteElementString("description", Description);
}
#endregion
}
Just to demonstrate the point, the class that will be part-serialized to attributes simply derives from one that will be serialized as normal.
•Now add the following two methods to your service class:
[OperationContract]
[WebGet(UriTemplate = "/test1")]
public ExampleData Test1()
{
return new ExampleData() { ID = 1,
Name = "Element-centric",
Description =
"The contents of this item are entirely serialized to elements - as normal" };
}
[OperationContract]
[WebGet(UriTemplate = "/test2")]
public ExampleDataAttributed Test2()
{
return new ExampleData_Attributed() { ID = 2,
Name = "Mixed",
Description =
"Everything except this description will be serialized to attributes" };
}
封面,烤40分鐘(即 - 建立它)。
如果你離開服務爲Service1.svc,然後運行它,並打開IE瀏覽器並瀏覽到http://本地主機:卡西尼港]/test1的
結果應該是這個樣子:
<JSLabs.ExampleData
xmlns="http://schemas.datacontract.org/2004/07/ExampleNamespace"
xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<Description>
The contents of this item are entirely serialized to elements - as normal
</Description>
<ID>
1
</ID>
<Name>
Element-centric
</Name>
</JSLabs.ExampleData>
現在瀏覽到http://本地主機:[卡西尼的端口]/TEST2
<JSLabs.ExampleDataAttributed id="2" name="Mixed"
xmlns="http://schemas.datacontract.org/2004/07/JobServe.Labs.Web">
<description>Everything except this description will be
serialized to attributes</description>
</JSLabs.ExampleDataAttributed>
它由一個小稍欠由討厭「orrible‘的xmlns =’屬性,該屬性的WCF數據c ontract序列化程序會自動穿上類型 - 但是,正如您所看到的,「ID」和「名稱」屬性確實已被推出爲屬性!
我們可以讓這兩個方法返回IExampleData,然後在該接口上使用KnownType屬性,以使其支持(根據返回的方法的代碼)。
爲了支持反序列化從屬性的對象,所有你需要做的是落實IXmlSerializable.ReadXml方法。
最後,正如前面提到的有關支持的類型的MSDN文章所述 - 您還應該能夠使用XmlElement/XmlNode類型作爲直接表示XML的方式 - DataContractSerializer就像在這種情況下一樣,採用簡短的路線並簡單獲取Xml。
,如果你的XML或JSON的客戶端的雙輸出對象這應該也不會影響到JSON格式。
Check the source of this article
感謝很多基斯德維特:) – Santosh