1

I've created the contract

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

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

Attribute NetDataContractAttribute described here. When I'm calling PassGuid I get an error:

Additional information: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:id. The InnerException message was 'XML 'Element' 'http://tempuri.org/:id' does not contain expected attribute 'http://schemas.microsoft.com/2003/10/Serialization/:Type'. The deserializer has no knowledge of which type to deserialize. Check that the type being serialized has the same contract as the type being deserialized.'. Please see InnerException for more details.

But PassInt could be called with no errors.

Full source code here.

Edited: This question is not about efficiency of sending guids, like this one, it is mostly about using NetDataContractSerializer.

Community
  • 1
  • 1
bonzaster
  • 313
  • 2
  • 12
  • possible duplicate of [WCF - How to send GUIDs efficiently (not as strings)](http://stackoverflow.com/questions/4220135/wcf-how-to-send-guids-efficiently-not-as-strings) – Backs Sep 23 '15 at 09:24
  • I have updated your github with [change](https://github.com/bonza/WcfNetDataContract/pull/1). `NetDataContractAttribute` class can be placed in shared class library to use in both client and server project. – vendettamit Sep 24 '15 at 19:55

2 Answers2

2

You are using the custom serializer as NetDataContractSerializer at server side. The difference between the NetDataContractSerializer and DataContractSerializer is that the serialization adds additional information of Types.

E.g. DatacontractsSerializer serialized to:

<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 would serialize the same object to:

<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>

Inducing more type specific information.

In your case server knows about the NetDataContractSerializer but client doesn't. You have to share this behavior to the client by putting it in a shared code library. Then you can add this enw behavior to the client using below code:

       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();
        }

You can also use attach the behavior via configuration file.

vendettamit
  • 14,315
  • 2
  • 32
  • 54
1

The problem is that client-side autogenerated contract (see file WcfClient\Service References\TestService\Reference.cs) does not have [NetDataContract] attributes.

Therefore DataContractSerializer is used on the client side.

In order for NetDataContractSerializer to work on both client and server you will need to have proper contract definition on the client side (by referencing server DLLs or by extracting contract into separate DLL). And then you will have to create your own Proxy class (inherited from ClientBase<ITestService>) instead of autogenerated one (or just use ChannelFactory<ITestService> without any proxy classes at all).

Igor Labutin
  • 1,406
  • 10
  • 10