使用NetDataContractSerializer将Guid传递给WCF服务

时间:2015-09-23 09:14:49

标签: c# .net wcf serialization netdatacontractserializer

我已经创建了合同

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    [NetDataContract]
    void PassGuid(Guid id);

    [OperationContract]
    [NetDataContract]
    void PassInt(int id);
}

属性NetDataContractAttribute描述了here。 当我打电话给PassGuid时,我收到了错误消息:

  

其他信息:格式化程序在尝试时抛出异常   反序列化消息:尝试时出错   反序列化参数http://tempuri.org/:id。 InnerException   消息是' XML'元素' ' http://tempuri.org/:id'不含   预期属性   ' http://schemas.microsoft.com/2003/10/Serialization/:Type&#39 ;.该   反序列化器不知道要反序列化的类型。校验   被序列化的类型与类型具有相同的契约   反序列化。&#39 ;.有关详细信息,请参阅InnerException。

但可以调用PassInt而没有错误。

完整源代码here

编辑: 这个问题不是关于发送guid的效率,比如this one,它主要是关于使用NetDataContractSerializer。

2 个答案:

答案 0 :(得分:1)

问题是客户端自动生成的合同(请参阅文件WcfClient\Service References\TestService\Reference.cs)没有[NetDataContract]属性。

因此DataContractSerializer用于客户端。

为了使NetDataContractSerializer能够在客户端和服务器上运行,您需要在客户端进行适当的合同定义(通过引用服务器DLL或通过将合同提取到单独的DLL中)。然后你将不得不创建自己的Proxy类(继承自ClientBase<ITestService>)而不是自动生成的(或者只使用ChannelFactory<ITestService>而不使用任何代理类。)

答案 1 :(得分:1)

您在服务器端使用自定义序列化程序NetDataContractSerializerNetDataContractSerializerDataContractSerializer之间的区别在于序列化会添加类型的其他信息。

E.g。 DatacontractsSerializer序列化为:

<Customer xmlns="http://www.contoso.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <FirstName>Zighetti</FirstName>
  <ID>101</ID>
  <LastName>Barbara</LastName>
</Customer>

NetDataContractSerializer会将同一个对象序列化为:

<Customer z:Id="1" z:Type="NetDCS.Person" z:Assembly="NetDCS, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns="http://www.contoso.com" xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
  <FirstName z:Id="2">Zighetti</FirstName>
  <ID>101</ID>
  <LastName z:Id="3">Barbara</LastName>
</Customer>

引出更多类型特定信息。

在您的情况下,服务器知道NetDataContractSerializer但客户端不知道。您必须通过将此行为放在共享代码库中来将此行为共享给客户端。然后,您可以使用以下代码将此enw行为添加到客户端:

       using (var client = new TestServiceClient())
        {
            // Get the channel factory
            var factory = client.ChannelFactory;

            // Attach the behavior
            foreach (OperationDescription desc in factory.Endpoint.Contract.Operations)
            {
                DataContractSerializerOperationBehavior dcsOperationBehavior = desc.Behaviors.Find<DataContractSerializerOperationBehavior>();
                if (dcsOperationBehavior != null)
                {
                    int idx = desc.Behaviors.IndexOf(dcsOperationBehavior);
                    desc.Behaviors.Remove(dcsOperationBehavior);
                    desc.Behaviors.Insert(idx, new WcfClient.NetDataContractAttribute.NetDataContractSerializerOperationBehavior(desc));
                    //return true;

                }
            }

            // pass
            client.PassInt(0);
            // fail
            client.PassGuid(Guid.NewGuid());
            client.Close();
        }

您还可以使用通过配置文件附加行为。