简体   繁体   中英

Does WCF keep a cache of (generated) Datacontracts and how to clear it

Does Windows Communication Foundation (WCF) keep a cache of (generated) Datacontracts and how to clear it? Why I expect this in my situation:

I have made a subclass "ChildClass" of a class "BaseClass". The "BaseClass" is part of Datacontract definition between a server-application and a UI-application. Now I wanted to let the server send the "ChildClass" over the interface to the UI, but disguise it as a "BaseClass". I tried some different decorations for my "ChildClass" (inspired by examples here: WCF: Returning a derived object for a contract with base object (DataContractResolver) ). I always got an error when deserializing the object on the UI-side, but the error did reference some of my Decorations on the "ChildClass", so something was working.

Then I tried another approach: I just added the "ChildClass" to the DataContract of the interface by adding: [KnownType(typeof(ChildClass))] This worked. (Note that the code is part of much larger code base that I did not write. It includes client specific definitions of the datacontracts and some code is generated). However, it could then also happen that the client would send back this object and this resulted in an error:

{"The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter BaseClassUISpecificDefinition. The InnerException message was 'Element 'UINamespace:BaseClassUISpecificDefinition' contains data from a type that maps to the name ' http://schemas.datacontract.org/2004/07/ServerChildClassNamespace:ChildClass '. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver if you are using DataContractSerializer or add the type corresponding to 'ChildClass' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to the serializer.'. Please see InnerException for more details."}

Besides this error, using this approach where the client would return the ChildClass, could lead to other logical problems, because the server used unique identifiers in the ChildClass, which should not be returned by the client, so I wanted to revert back to my original solution.

But then no matter how much I rebuild, deleted bin/obj files, generated code, checked out older commits, I always got the same error when the client received an object:

{"The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter UINamespace:UIServiceContract. The InnerException message was 'Element 'UINamespace:UIServiceContract' contains data from a type that maps to the name ' http://schemas.datacontract.org/2004/07/ServerChildClassNamespace:ChildClass '. The deserializer has no knowledge of any type that maps to this name. Consider using a DataContractResolver if you are using DataContractSerializer or add the type corresponding to 'ChildClass' to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding it to the list of known types passed to the serializer.'. Please see InnerException for more details."}

Then to test my hypothesis that there is cache somewhere, I run the exact same code on a buildserver (which makes a clean build in a clean environment), and indeed I got a different error there. I expect that this error occurs when the client tries to deserialize the object and it is:

The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlyinig network resource issue. Local socket timeout was '00:01:00'.

So is there caching/code generation somewhere? Where is it stored and how to clear it?

A great article that describes how to declare child-classes in WCF is this one: https://www.c-sharpcorner.com/uploadfile/c1de77/data-contract-and-known-type-in-wcf/

The correct attributes for my classes had to be:

In BaseClass.cs:

namespace ServerBaseClassNamespace
{
    //
    // Summary:
    //     Coordinates system in all the Machine Control and Subsystem software.
    [DataContract]
    [KnownType(typeof(BaseClass))]
    public class BaseClass
    {
    }
}

In ChildClass.cs:

namespace ServerChildClassNamespace
{
    using ServerBaseClassNamespace;

    [System.Runtime.Serialization.KnownType(typeof(ChildClass))]
    [System.Runtime.Serialization.DataContract(Name = "BaseClass", Namespace = "ServerBaseClassNamespace")] /* We disguise ChildClass as an BaseClass.
    It is sent over the interfaces as an BaseClass. The interface contracts: [ServiceContract], must define [ServiceKnownType(typeof(ChildClass))] to use this.
    See: https://www.c-sharpcorner.com/uploadfile/c1de77/data-contract-and-known-type-in-wcf/
    for explanation. */
    public class ChildClass : BaseClass
    {
    }
}

In IExampleContract.cs:

namespace UiService
{
    using System;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using ServerChildClassNamespace;

    [ServiceContract(Namespace = "UiService",SessionMode = SessionMode.Required)]
    [ServiceKnownType(typeof(ChildClass))] // On the server side this is an ChildClass, but the client will receive it as a BaseClass.
    public interface IExampleContract
    {
        [OperationContract]
        BaseClass ExampleMethod(BaseClass ExampleArgument);
    }
}

In UIServiceImplementation.cs:

namespace UiService
{
    using System;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using ServerChildClassNamespace;

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
    [ServiceKnownType(typeof(ChildClass))] // On the server side this is an ChildClass, but the client will receive it as a BaseClass.
    public sealed class UIServiceImplementation : IExampleContract
    {
    BaseClass ExampleMethod(BaseClass ExampleArgument);
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM