【问题标题】:WCF DataContractSerializer doesn't pick up contract attributes... why not?WCF DataContractSerializer 不获取合同属性......为什么不呢?
【发布时间】:2009-07-16 03:55:30
【问题描述】:

我有以下类型,我在 WCF 中用作消息协定:

[MessageContract(IsWrapped = true, 
                 WrapperNamespace = "http://example.com/services", 
                 WrapperName = "EchoRequest")]
public class EchoRequest
{
    public EchoRequest() { }
    public EchoRequest(String value)
    {
        Value = value;
    }

    [MessageBodyMember(Name = "Value", 
                       Namespace = "http://example.com/services", 
                       Order = 0)]
    public String Value { get; set; }
}

当我使用 svcutil.exe 生成此类型的代理时,我得到了一个客户端,该客户端能够与托管它的服务进行通信,元素上的 XML 命名空间根据消息契约属性。

当我在它的一个实例上使用Message.CreateMessage(...) 时,命名空间恢复为默认值 (http://schemas.datacontract.org/2004/07/...)。当我使用DataContractSerializer 的实例时,也会发生同样的事情。我尝试将命名空间传递给DataContractSerializer 构造函数,并且只有包装器包含在命名空间中:

var requestMessage = new EchoRequest("hello, world!");
var serializer = new DataContractSerializer(typeof(EchoRequest), 
                                            "EchoRequest", 
                                            "http://example.com/services");
var stream = new MemoryStream();
serializer.WriteObject(stream, requestMessage);
var data = Encoding.UTF8.GetString(stream.ToArray());

此时,“数据”为:

<EchoRequest xmlns="http://example.com/services"
             xmlns:a="http://schemas.datacontract.org/2004/07/TestClient"
             xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <a:Value>hello, world!</a:Value>
</EchoRequest>

为什么DataContractSerializer 似乎忽略了MessageContract 属性? svcutil 是如何完成这项工作的?

【问题讨论】:

  • 感谢您提出这个问题!我刚刚遇到了这个确切的问题,几乎立刻就找到了你的问题。

标签: wcf datacontractserializer datacontract messagecontract


【解决方案1】:

因为消息合约不是数据合约,数据合约使用不同的属性来标记它们的类。尝试使用类型化消息转换器;

EchoRequest echoRequest = new EchoRequest{ value = "Hello" };

TypedMessageConverter echoMessageConverter = TypedMessageConverter.Create(
                 typeof(echoRequest),
                 "YourActionNameHere",
                 "http://example.com/services");
Message request = echoMessageConverter.ToMessage(
    echoRequest,MessageVersion.Soap11);

然后,您将准备好一条消息,并且可以根据需要提取请求正文。

【讨论】:

  • 是的,就是这样!关于如何处理消息契约的书籍和文档显得相当零散,这是我第一次遇到 TypedMessageConverter。谢谢!
  • 如果您的消息协定的成员使用 XmlSerialization 属性而不是 DataContract 属性(它们可以从 DataContractSerializer 无法表示的 WSDL/XSD 生成),请使用 TypedMessageConverter.Create 的重载,它接受XmlSerializerFormatAttribute,指示它使用 XmlSerialization 代替。
  • 使用 EchoRequest 类型创建代理类不是更容易吗?您可以再次将此类命名为 EchoRequest 并将其定义为 MessageContract 在上面的原始类可以是数据合同。这是双重定义,但对我来说很好。
猜你喜欢
  • 2011-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-31
相关资源
最近更新 更多