C# 如何自定义 WCF XML 序列化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/649913/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to customize WCF XML serialization
提问by Jeroen-bart Engelen
We have an existing SOAP web service interface that we want to implement using WCF for a new application. This seems to work fine except for one small detail. The XML namespace of the return type of a function must be different than the XML namespace of the web service itself. And for the life of me, I can't get it to work.
我们有一个现有的 SOAP Web 服务接口,我们希望使用 WCF 为新应用程序实现该接口。除了一个小细节外,这似乎工作正常。函数返回类型的 XML 命名空间必须不同于 Web 服务本身的 XML 命名空间。对于我的生活,我无法让它发挥作用。
I've recreated the same problem with a small sample project. The WCF interface:
我用一个小示例项目重新创建了同样的问题。WCF接口:
[XmlSerializerFormat]
[ServiceContract(Namespace = "urn:outer-namespace")]
public interface IService1
{
[OperationContract]
MyClass DoStuff(int value);
}
[Serializable]
public class MyClass
{
[XmlElement(ElementName = "DataString")]
public string MyString { get; set; }
}
The web service implementation:
网络服务实现:
public class Service1 : IService1
{
public MyClass DoStuff(int value)
{
return new MyClass { MyString = "Wooh!" };
}
}
A response from this webservice is then serialized as: (Omitting SOAP stuff)
来自该网络服务的响应随后被序列化为:(省略 SOAP 内容)
<DoStuffResponse xmlns="urn:outer-namespace">
<DoStuffResult>
<DataString>Wooh!</DataString>
</DoStuffResult>
</DoStuffResponse>
But we want the <DoStuffResult> to be of xmlns="urn:inner-namespace".
但是我们希望 <DoStuffResult> 是 xmlns="urn:inner-namespace"。
I've tried adding a [return: XmlElement(...)] on the interface function or the web service function, but that doesn't take. Also an [XmlType] or [XmlRoot] on the MyClass class definition doesn't work.
我试过在接口函数或 web 服务函数上添加一个 [return: XmlElement(...)] ,但这并不需要。MyClass 类定义上的 [XmlType] 或 [XmlRoot] 也不起作用。
Does anyone have an idea how to change the serialized XML namespace (or element name) of the object that is the return value of a WCF web service function?
有没有人知道如何更改作为 WCF Web 服务函数返回值的对象的序列化 XML 命名空间(或元素名称)?
采纳答案by Richard
Define namespaces with the XML Serialisation (or, better) Data Contract definition attributes.
使用 XML 序列化(或更好的)数据协定定义属性定义命名空间。
e.g. with XML Serialisation:
例如使用 XML 序列化:
[Serializable, XmlRoot(namespace="http://example.com/eg1")]
public class MyClass {
[XmlElement(ElementName = "DataString")]
public string MyString { get; set; }
}
e.g. with Data Contract serialisation:
例如使用数据合同序列化:
[DataContract(Namespace="http://example.com/eg2")]
public class MyClass {
[DataMember]
public string MyString { get; set; }
}
EDIT
编辑
Based on the first comment, the above won't work, because the desire is to set the namespace on the SOAP wrapper around the message, not on the message itself.
根据第一条评论,以上将不起作用,因为希望在消息周围的 SOAP 包装器上设置命名空间,而不是在消息本身上。
OperationContractAttribute
offers no control of namespaces, and I can't see any other WCF attributes at a method level.
OperationContractAttribute
不提供对命名空间的控制,并且我在方法级别看不到任何其他 WCF 属性。
Two possibilities: (1) You may have enough control by dropping a level of abstraction and using a Message Contract. (2) Get the current WSDL for the service (using svcutil.exe
), manually adjusting it to get the namespaces you want, and then using svcutil.exe
again to generate the code, and look at the resulting code.
两种可能性:(1)您可以通过降低抽象级别并使用消息契约来获得足够的控制权。(2)获取服务当前的WSDL(使用svcutil.exe
),手动调整得到你想要的命名空间,然后svcutil.exe
再次使用生成代码,查看生成的代码。
回答by Rich Bayless
After days of searching and trying dozens of recommended solutions; I was finally able to get WCF to stop forcing a wrapper container name of appending Result
to the name of the web service method. The trick was to add the following decorator attribute to the web service interface:
经过数天的搜索和尝试数十种推荐的解决方案;我终于能够让 WCF 停止强制将包装容器名称附加Result
到 Web 服务方法的名称。诀窍是将以下装饰器属性添加到 Web 服务接口:
[return:MessageParameter(Name = "whatIWantItNamed")]
This attribute should be placed/located directly after the [OperationContract]
attribute (and just before the actual method stub) in the interface.
该属性应该直接放置/定位在接口中的[OperationContract]
属性之后(并且就在实际方法存根之前)。
(I also needed to add an XmlSerializerFormat
attribute to all of the ServiceContract
and OperationContract
attributes.)
(我还需要为XmlSerializerFormat
所有ServiceContract
和OperationContract
属性添加一个属性。)