我们有一个现有的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名称空间(或元素名称)?
答案 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
属性。)