为什么 XmlRoot 属性在 WCF 中被忽略以及如何解决这个问题 [英] Why does the XmlRoot attribute gets ignored in WCF and how to overcome this

查看:25
本文介绍了为什么 XmlRoot 属性在 WCF 中被忽略以及如何解决这个问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们观察到,当我们公开使用用各种 xml 序列化属性修饰的类的 WCF 服务时,尽管我们在接口上使用 XmlSerializerFormat 属性,但任何操作参数上的任何 XmlRoot 属性都被完全忽略.参数的命名空间始终是服务的命名空间,而不是我们指定的命名空间.

We've observed that when we expose a WCF service which uses classes decorated with various xml serialisation attributes, despite the fact that we use the XmlSerializerFormat attribute on the interface any XmlRoot attribute on any of the operation's parameters gets completely ignored. The namespace of the parameters is always that of the service and not what we specify.

这给我们带来了问题,因为它似乎与 ASMX 不向后兼容,还因为我们使用的是 BizTalk,并且需要更严格地控​​制所交换的 XML 的形状.

This is causing us problems as it does not seem to be backwards compatible with ASMX and also because we're using BizTalk, and need to have tighter control over the shape of the XML's exchanged.

那么几个问题 -

  1. 任何人都知道这是什么原理这一决定背后的原因是什么?
  2. 谁知道这是怎么回事?我在WCF 的印象,与XmlSerializerFormat 属性,使用用于序列化的 XmlSerialiser类型,这会建议 XmlRoot应该考虑,如何难道不是这样吗?(是吗只是因为,采取考虑到 SOAP 信封,参数不是root?)
  3. 大多数重要的是 - 任何人都知道有一种方法可以强制解决问题"-即获取参数是我们选择的命名空间?

我看过这篇帖子,但我认为这与我的问题无关 -

I've seen this post, but I don't believe it is relevant to my question -

根据 Wagner Silveira 的要求 - 我用来测试的合同是 -

As per Wagner Silveira's request - the contracts I used to test this are -

[ServiceContract(Namespace = "http://servicecontract"),
 XmlSerializerFormat(Style = OperationFormatStyle.Document)]
public interface ITestService
{
    [OperationContract]
    MyOtherType MyTestMethod(MyType obj);
}

// Composite class for DCS and XMLS
[Serializable, XmlType, XmlRoot(Namespace = "http://datacontract")] 
public class MyType
{
    [XmlAttribute]
    public string StringValue { get; set; }
}

// Composite class for DCS and XMLS
[Serializable, XmlType, XmlRoot(Namespace = "http://datacontract")]
public class MyOtherType
{
    [XmlAttribute]
    public string OtherStringValue { get; set; }
}

推荐答案

我假设您使用 SOAP 作为消息格式.在这种情况下,您要序列化的对象不是 XML 的根,soap 信封才是.所以 XmlRoot 将被忽略是有道理的.默认情况下,WCF 将为您创建一个消息协定并命名响应,它具有服务的命名空间.您可以做的是创建您自己的消息合同以完全控制通过 SOAP.

I assume you're using SOAP as the message format. In this case, the object you're serializing is not the root of the XML, the soap envelope is. So it makes sense that the XmlRoot would be ignored. By default WCF will create a message contract for you and name the response and it has the namespace of the service. What you can do is create your own message contract to have full control over SOAP.

创建以下两个类:

[MessageContract]
public class MyTestMethodRequest
{
    [MessageBodyMember( Namespace = "http://datacontract" )]
    public MyType MyType;
}

[MessageContract]
public class MyTestMethodResponse
{
    [MessageBodyMember( Namespace = "http://datacontract" )]
    public MyOtherType MyOtherType;
}

然后将您的服务操作的签名更改为以下内容.

Then change the signature of your service operation to the following.

[OperationContract]
public MyTestMethodResponse MyTestMethod( MyTestMethodRequest request )
{
    return new MyTestMethodResponse {
        MyOtherType = new MyOtherType {
            OtherStringValue = "bar"
        }
    };
}

现在,如果您以 SOAP 消息为例,您应该看到以下内容:

Now if you example the SOAP messages you should see the following:

请求

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <Action xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none"
            s:mustUnderstand="1">http://servicecontract/TestService/MyTestMethod</Action>
  </s:Header>
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <MyTestMethodRequest xmlns="http://servicecontract">
      <MyType StringValue="foo" xmlns="http://datacontract" />
    </MyTestMethodRequest>
  </s:Body>
</s:Envelope>

回复

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header />
  <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <MyTestMethodResponse xmlns="http://servicecontract">
      <MyOtherType OtherStringValue="bar" xmlns="http://datacontract" />
    </MyTestMethodResponse>
  </s:Body>
</s:Envelope>

这篇关于为什么 XmlRoot 属性在 WCF 中被忽略以及如何解决这个问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆