如何自定义WCF XML序列化

时间:2009-03-16 10:44:13

标签: c# xml wcf serialization xml-serialization

我们有一个现有的SOAP Web服务接口,我们希望使用WCF为新应用程序实现。除了一个小细节外,这似乎工作得很好。函数返回类型的XML命名空间必须与Web服务本身的XML命名空间不同。而对于我的生活,我无法让它发挥作用。

我用一个小样本项目重新创建了同样的问题。 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; }
}

Web服务实现:

    public class Service1 : IService1
{
    public MyClass DoStuff(int value)
    {
        return new MyClass { MyString = "Wooh!" };
    }
}

然后将此Web服务的响应序列化为: (省略SOAP的东西)

  <DoStuffResponse xmlns="urn:outer-namespace">
     <DoStuffResult>
        <DataString>Wooh!</DataString>
     </DoStuffResult>
  </DoStuffResponse>

但我们想要&lt; DoStuffResult&gt;是xmlns =“urn:inner-namespace”。

我尝试在接口函数或Web服务函数上添加[return:XmlElement(...)],但这不需要。此外,MyClass类定义中的[XmlType]或[XmlRoot]不起作用。

有没有人知道如何更改作为WCF Web服务函数返回值的对象的序列化XML名称空间(或元素名称)?

2 个答案:

答案 0 :(得分:3)

使用XML序列化(或更好)数据协定定义属性定义名称空间。

e.g。使用XML序列化:

[Serializable, XmlRoot(namespace="http://example.com/eg1")]
public class MyClass {
  [XmlElement(ElementName = "DataString")]
  public string MyString { get; set; }
}

e.g。数据合同序列化:

[DataContract(Namespace="http://example.com/eg2")]
public class MyClass {
  [DataMember]
  public string MyString { get; set; }
}

修改

根据第一条评论,上述内容不起作用,因为希望在SOAP包装器上围绕消息设置名称空间,而不是在消息本身上。

OperationContractAttribute无法控制名称空间,我在方法级别看不到任何其他WCF属性。

两种可能性:(1)您可以通过删除抽象级别和使用消息合同来获得足够的控制权。 (2)获取服务的当前WSDL(使用svcutil.exe),手动调整它以获取所需的命名空间,然后再次使用svcutil.exe生成代码,并查看生成的代码。

答案 1 :(得分:1)

经过几天的搜索并尝试了几十种推荐的解决方案;我终于能够让WCF停止强制包装容器名称将some_code附加到Web服务方法的名称。诀窍是将以下装饰器属性添加到Web服务接口:

some_code

此属性应直接放在/位于界面中Result属性之后(并且位于实际方法存根之前)。

(我还需要为所有[return:MessageParameter(Name = "whatIWantItNamed")] [OperationContract]属性添加XmlSerializerFormat属性。)