如何自定义WCF XML序列化

Jer*_*len 8 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; }
}
Run Code Online (Sandbox Code Playgroud)

Web服务实现:

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

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

  <DoStuffResponse xmlns="urn:outer-namespace">
     <DoStuffResult>
        <DataString>Wooh!</DataString>
     </DoStuffResult>
  </DoStuffResponse>
Run Code Online (Sandbox Code Playgroud)

但是我们希望<DoStuffResult>是xmlns ="urn:inner-namespace".

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

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

Ric*_*ess 5

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

[return:MessageParameter(Name = "whatIWantItNamed")]
Run Code Online (Sandbox Code Playgroud)

该属性应该直接放置/定位在接口中的[OperationContract]属性之后(并且就在实际方法存根之前)。

(我还需要为XmlSerializerFormat所有ServiceContractOperationContract属性添加一个属性。)


Ric*_*ard 3

使用 XML 序列化(或更好的)数据契约定义属性定义命名空间。

例如,使用 XML 序列化:

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

例如,使用数据合同序列化:

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

编辑

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

OperationContractAttribute不提供对命名空间的控制,并且我在方法级别看不到任何其他 WCF 属性。

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