I have been developing an application for the last five months and just ran into this problem.
We are using EF5 and, similar to this question, I designed the class hierarchy to have all entity classes derived from an abstract base class to force validation interfaces to be implemented. We are also using the validation attributes in the entity classes.
Everything has worked fine until I started trying to use the entity classes in WCF Services. I am getting a bunch of serialization exceptions, and have been trying to figure out what "POCO" rule I broke in the design. This article tells me the class (obviously...) cannot be abstract, but since my classes are DERIVING from an abstract class, have I perhaps broken a rule I don't know about?
UPDATE: Here is the exception that I am struggling with:
System.Runtime.Serialization.SerializationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Type 'System.Data.Entity.DynamicProxies.WorkSession_63308485A9007DE087FF55AD9F246FD677863AA39AD56FEF4586AB87E21832DD' with data contract name 'WorkSession_63308485A9007DE087FF55AD9F246FD677863AA39AD56FEF4586AB87E21832DD:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.
Since your POCOs use lazy loading, you don't get actual types from the EF but rather proxies so that navigation properties are auto implemented for lazy loading.
My advice is to forget the idea of exposing domain objects from web services. I bet there will be answers trying to convince you that this is possible in this particular case with a bunch of extra spells casted. However, the safest approach is to switch your thinking to DTOs, Data Transfer Objects, a pattern where you create an extra layer of "data-only" classes which are light and safe to serialize and send over the wire.
There are a lot of great articles explaining on how to expose your data using the DTO pattern and a couple of extra supporting technologies like the AutoMapper. You will find details easily and you can come back for further answers.
You didn't break a "POCO rule". The "dynamic proxy" mentioned in the exception is a class that is derived from your WorkSession entity, but it isn't derived in your code but dynamically at runtime. Entity Framework does this - by default - to make lazy loading and dynamic change tracking possible if you have marked your navigation properties (and maybe also scalar properties) as virtual.
You should disable dynamic proxy creation when you intend to serialize an entity with WCF. You can do this by simply setting a flag on the context before you load your entities from the database:
context.Configuration.ProxyCreationEnabled = false;
var worksessions = context.WorkSessions.....ToList();
The loaded worksessions are of the real runtime type WorkSession now, not of a dynamic proxy type and WCF shouldn't complain anymore.
Related
Diagram below depicts how
producer creates new messages/requests filling data members,
messages are serialized,
sent to consumer,
dserialized,
Consumer invokes virtual function - uses polymorphic behavior of base class reference.
This article discusses a similar question.
But I need to separate DTO (in DataContract.DLL) and some implementation (App.EXE) linked to this DTO within the same class hierarchy (I try to avoid introducing another family of classes like RequestProcessors).
Implementation should be overridden in a different assembly than dll with definition of DTO/message - this dll should be lightweight - used by different teams. Therefore I can't refer to derived class in attribute [KnownType(typeof(SomeData))] like in mentioned article. I don't want to include method implementation in DataContract.DLL.
How to implement polymorphism in hierarchy with serialised classes (DataContract messages) where DataContracts and implementation are separated in different assemblies? Is it possible?
I didn't find the way but C# is not my primary language. I see that producer should not depend on Consumer.EXE but should create most derived class. So, all classes should be introduced in DataContracts.DLL. Partial class definition likely are not cross assembly.
Maybe multiple file assembly will work? Maybe extension method are closest approximation.
Updated (quotation from article):
DTOs that are decorated as DataContract classes are real objects. They can have methods in them, but the methods are not part of the serialization process
How to implement polymorphism in hierarchy with serialised classes (DataContract messages)
"Polymorphic data contract " is an oxymoron.
Data contracts are DTOs (Data Transfer Objects) implementation for WCF.
WCF clearly separates data (data contracts, DTOs) from behavior (services).
Do not mix them.
In other words:
don't try to implement polymorphism in DTO hierarchy;
do not add any behavior to DTOs.
I try to avoid introducing another family of classes like RequestProcessors
But you shouldn't!
This is natural approach for service-based solutions, and this is not about WCF (SOAP) only. E.g., REST (ASP .NET Web API in case of .NET) does the same.
Moreover, service-based way suits well for business-logic implementation inside applications, because it perfectly fits Dependency Injection containers.
Do implement some IRequestProcessor hierarchy - this is the right way to go.
Note, that linked question is about inheritance, but it is not about behavior inheritance. IMO, term "polymorphism" is misused there. You can (and often should) derive one data contract from another, but you can (should) derive data, not behavior.
Is there a weaver for WCF that auto implements the DataContract and DataMember attribute to my entity class?
We are migrating the local back-end of our system to a WCF Service. We have too many entity class and it will really take an awful lot of time to add that attribute in each of our entity class.
Please refer to this link for reference of a weaver, It is for INotifyPropertyChange for WPF and it really does help.
My code is in C#, framework 4.0, build in Visual Studio 2010 Pro.
Any help will be greatly appreciated.
Thanks in advance.
Depending on what technology you use, you may decide not to directly expose your entity classes. For instance, it's not a good idea to expose Entity Framework entities, as this will also serialize the base classes, which you probably don't want.
I recommend you try serializing one of your entities, then look at the resulting client code to see if anything undesirable comes across the wire.
If there is a problem, then you may want to design Data Transfer Objects to correspond to each of your entities. This might be done using code generation, so you don't have to do it all by hand.
You do not have to apply DataContract/DataMember attributes on all entities.
By default, the DataContractSerializer infers the data contract and serializes all publicly visible types. All public read/write properties and fields of the type are serialized.
Source: Using Data Contracts
I have a WCF service that uses generics in its data contract, for example (simplified):
public GetDetails(StatusField<string> status);
Now WCF supports generics by creating a non-generic equivalent type for every possible value of T in the generic. So, for the above example, the client consuming the WCF service will see the following signature for the above function:
public GetDetails(stringStatusField status);
//...
Now the client has a copy of the generic version of the StatusField class. We want to use AutoMapper in the client, to map between this generic StatusField and the types generated above by WCF (such as stringStatusField) so we can call the service. We could do this by manually creating the maps at client startup, like so:
Mapper.CreateMap<StatusField<string>, stringStatusField>();
However this is laborious as there are 50+ possible values of that WCF has converted. Extending this idea, we could use reflection to automatically create maps for all the types and this is the solution we are currently using.
Ideally what i would like to see is a solution that ties into the architecture of AutoMapper to avoid having to do the reflection manually. conceptually, this would require some way of defining a convention that AutoMapper would use to allow it to tie the two types together, similar to how it allows custom conventions to be specified when matching properties. As yet, i have not seen a way to do this and this is the question i would like answered here, if anyone knows how this can be done, specifically in relation to the above scenario.
BTW i am aware that some may be thinking of Mapper.DynamicMap() as a solution to this problem. Firstly, we dont want to use this as it means debugging could potentially be harder (as indicated by some in other posts similar to this) and also if the StatusField is deeply nested in an object graph being passed to the WCF method, im not sure this solution would work and could potentially lead to a type being incorrectly mapped and other such issues. I would really like to concretely define the allowable mappings if possible.
Unsure if AutoMapper provides the support you are after, but if it did it would be using reflection as you propose.
If you are opposed to the reflection solution due to performance concerns (which should be a one-time startup cost), then maybe a T4 template-based code generation solution might be worth considering?
I'm sorry if this has been asked before, I tried many combinations of keywords to describe the issue but was unable to find anything on Google or SO.
The problem is simple: and I have a List of objects. I've marked this list with ObjectCollectionValidator so that objects get validated. Some of the objects in the list aren't, however, of type T, but of some derived type.
Those derived types have properties not present on their parents that need to be validated. They simply won't. I believe that VAB isn't checking inherited types when dealing with ObjectCollectionValidator, but that is a flaw in my opinion, so I'm hoping I'm wrong.
By the way, I'm using EntLib's 4.1 (and while I wanted, I cannot switch to EntLib 5.0).
What you're witnessing is a design quirk of VAB 4.1 that has been solved in VAB 5.0. In VAB 5.0, when you decorate a collection property with a ObjectCollectionValidatorAttribute, you can leave out the actual type and in that case, the validator will validate objects by their actual type.
If you can't switch to VAB 5.0, the only thing you can do is write your own object collection validator. This isn't really difficult. Just look at the source of of the ObjectCollectionValidatorAttribute and ObjectCollectionValidator of VAB 5.0.
Good luck.
How can I use an interface (from which classes implement) in an XML web service?
When I do so, I get a YSOD claiming the interface is not serializable. If I add the Serializable attribute to the interface's class, there's another error which hampers progress (can't remember which).
For the most part interfaces are not serializable without some work. Usually this error is encountered when the class being serialized contains an object that is using an interface as a variable, or some variation of this. For instance, a property like this would throw an error:
[Serializable]
public class TestClass
{
private ICustomInterface _iCustomInterfaceObject;
public ICustomInterface CustomInterfaceProperty
{
get { return _iCustomInterfaceObject; }
set { _iCustomInterfaceObject = value; }
}
}
For the sake of the argument (and not making me type additional validation code), let's say that you always are assigning CustomInterfaceProperty to an object that inherits from ICustomInterface (as is required when using interface types like this). Even if it is 100% sure to always be populated, it won't allow you to serialize the TestClass.
To get around this, you need to make sure the interface you are using, the one that is throwing the error, also inherits from ISerializable. That way you are promising that all of the objects inheriting from ICustomInterface also have serialization methods implemented.
Unfortunately, this is not the case when using xml serialization. If you are using the serializers found in System.Xml.Serialization then this method won't work, since, as Robert Harvey pointed out, an interface does not contain a parameterless constructor (which is required when using the xml serializers). My suggestion for now, if you are set on this method of serialization, attach the attribute [XmlIgnore] to the section in question and move on from there.
My advice is to treat the objects that go over the wire as basic data transfer objects and nothing more. You're tempted to just use your domain objects and serialize them, but as you're already seeing, normal in-memory objects can have far more complexity than can be serialized without a lot of work, and sometimes not at all.
You can also end up limiting functionality of your domain classes just to keep them serializable.
Finally, a more subtle bug to avoid, and a reason to have separate DTO's, is that you otherwise are tightly coupling your domain objects to a publicly published interface i.e. the web service itself. Versioning a web service can be a hassle, and it's easier if your service interface isn't tightly coupled to your domain classes.
I'm guessing that the other message is that you can't serialize the interface because it doesn't contain a default (parameterless) constructor.
If the underlying classes are framework classes, you might be hosed. Some of them are not marked serializable, and some of them do not have parameterless constructors.
Also, you may be getting confused between runtime serialization and XML serialization. XML Serialization is what the old ASMX web services use. It does not pay much attention to the [Serializable] attribute, but mostly just serializes the public read/write properties of public classes which have a default constructor.