Why is WCF suddenly requiring DataContractAttributes? - wcf

I built a number of WCF services as part of an application. Until recently, most of the classes that were used as parameters of the many operations in a service did not had the DataContract or DataMember attributes applied to them.
Now, I've made a few changes in a row and all of a sudden WCF is complaining that he can't serialize my classes.
Does anyone knows if any changes in configuration or even in the ServiceContract, OperationContract etc. can cause WCF to become picky about the classes it can serialize?
I'd rather not need the attributes in those classes (they should be pure C# classes as possible).
Also of note, if I return to a previous version in my source control, WCF goes back to "normal", so I believe that it's not a machine/environment thing.

The ability to create WCF Data Contracts without the use of the [DataContract] and [DataMember] attributes is a feature added to WCF in .NET 3.5 SP1. Since everything works for you when reverting your code to a previous version, I'm assuming you are already using at least that version.
Nevertheless, in order for classes to be serializable by WCF, the class must meet several requirements listed here. The main requirements of the data contract class are:
It must be public.
It must have a parameterless constructor.
It must not have any data members that do not meet all these requirements. If you do have such a member, mark it with [IgnoreDataMember] and it will be excluded from WCF serialization.
You can get more information about what fails to serialize by performing the serialization manually using the DataContractSerializer class. See this article for more details and code examples. Another method is to mark all members with [IgnoreDataMember] and gradually remove the attributes from members until serialization fails, which will tell you which member is causing the problem.

WCF is lenient towards classes that have [serializable] attribute. You don't require [DataContract]. You must have added something that is not serializable.

I know a way to do that. it's not professional but it works for me
I'm also need pure c# classes so I do it in this way.
I convert each parameter of my class to an object then gather them into array of objects and send it to the other side. in the other side I do the reverse operation to get my parameters back. but this operation will reduce the performance i think

Related

WCF data contract design with dependency injection

So I have a layered application that I am adding a WCF service interface on top of. The service is simply a facade with all of our business logic already existing in Business Objects (BOs) within the Business Logic Layer (BLL) which is a class library. Within the BLL we use constructor injection to inject dependencies into the BOs. This is all working with good unit testing, etc. On to the problem...
Ordinarily I'd simply create a set of Request/Response objects as DataContracts for each service method with the appropriate properties for the operation. If the operation required one of our "entities" to be passed either to or from the method, I'd simply define a property of that type and everything would be fine (all of our BOs are serializable). However when one of these "entities" is passed into a service method, WCF deserializes the object without ever invoking the constructors we've defined and, as a result, the dependencies don't resolve.
Let's use the case of a service method called CreateSomething. I'd normally define this as a service operation with a signature like:
CreateSomethingResponse CreateSomething(CreateSomethingRequest request);
CreateSomethingRequest would be a DataContract and have amongst its properties a property of type Something that represented the "entity" being passed into the service. Something, in this case, is a business object that expects to receive an instance of the ISomethingRepository interface from the DI container when instantiated - which, as I said above, does not happen when WCF deserializes the object on the server.
Option #2 is to remove the Something property from the DataContract and define each of the properties explicitly in my DataContract then inside my service method, create a new instance of the Something class, letting the container inject the dependency, then map the property values from the DataContract object into the BO. And I can certainly do that but I am concerned about now having two places to make changes if, say, I want to add a property to the Something type. And, with a lot of properties, there's a lot of code duplication.
Has anyone crossed this bridge and, if so, can you share your thoughts and how you have or would approach this situation in your own applications? Thx!!!
There are two answers on your problem:
First: Do not send your entities and use data transfer objects instead. Your entities are business objects with its logic and data. The logic of business objects is most probably used to control the data. So let the business object control its data in business layer and exchange only dummy crates.
Second: If you don't want to follow the first approach, check documentation of your IoC container. There are ususally two methods for resolving dependencies. For example Unity offers:
Resolve - builds new instance and injects all dependencies (necessary for constructor injection)
BuildUp - takes existing instance and resolves all property dependencies. This should be your choice.
Thanks, Ladislav, for your answer as you confirmed what was already in my head.
What I ended up doing was to change my approach a little. I realized that my use of a business object, per se, was overkill and unnecessary. Or perhaps, just misdirected. When evaluating my requirements, I realized that I could "simplify" my approach and make everything work. By taking each logical layer in my application and looking at what data needed to pass between the layers, I found a design that works.
First, for my business logic layer, instead of a business object, I implemented a Unit of Work object: SomethingManager. SomethingManager is tied to my root Something entity so that any action I want to perform on or with Something is done through the SomethingManager. This includes methods like GetById, GetAll, Save and Delete.
The SomethingManager class accepts two objects in its constructor: an IValidator<Something> and an ISomethingRepository. These will be injected in by the IoC container. The former lets me perform all of the necessary validation using whatever framework we chose (initially the Validation Application Block) and the latter gives me persistance ignorance and abstracts the use of Linq-to-SQL today and makes upgrading to EF4 much easier later on.
For my service layer, I've wired the IoC container (Unity in this case) into WCF so the service instance is created by the container. This allows me to inject an instance of ISomethingManager into my service. Using the interface, I can break the dependency and easily unit test the service class. Plus, because the container is injecting the ISomethingManager instance, it is constructing it and will automatically resolve it's dependencies.
I then created DataContracts to represent how the data should appear when transferred across the wire via the service. Each Request/Response object contains these DataContracts as DataMembers rather than referencing my entity classes (or BOs) directly. It is up to the service method to map the data coming from or going to the Business Logic Layer (via ISomethingManager) - using AutoMapper to make this clean and efficient.
Back in the data layer, I've simply extended the generated entity classes by defining a partial class that implements the desired interface from the BLL. For instance, the Something L2S entity has a partial defined that implements ISomething. And ISomething is what the SomethingManager (and ISomethingManager interface) and ISomethingRepository work with making it very easy to query the database and pass the L2S entity up the chain for the service layer to consume and pass on (without the service layer having any knowledge or dependency on the L2S implementation).
I appreciate any comment, questions, criticisms or suggestions anyone has on this approach.

Hide public properties from DataContract

I removed [DataMember] attribute from all of my public properties, yet the properties are still showing up in the results of my WCF operations. I found this link here that explains if .Net is on both ends of the wire, then DataMember doesn't have much of an effect on determining what properties are included in the DataContract.
So, how do you exclude public properties from being included in WCF results?
Thanks
There are several different ways that the serialization in WCF can work. They are outlined here. Note that [Serializable] classes can also be used.
Note the last item in that list: Starting with 3.5 SP1, classes that are not annotated with any option would still be serializable by the WCF infrastructure. If you do that, however, you're left with no way to control how that serialization happens and what properties are serialized (which is why I personally feel that option was a mistake to add, but that's another story).
Is there any reason why you removed the [DataContract][DataMember] attributes?

Reuse classes and objects for both WCF and non-WCF

I have several classes such as Order, Customer, etc. These classes serve for holding data and nothing more. I want to be able to reuse these classes in other projects in the future, but for some reason I don't quite understand, WCF forces me to decorate the data members with the [DataMember] attribute, forcing me to reference WCF plumbing that I will never use in other projects.
I would imagine that WCF lets you take any serializable class and use it as a content type. Am I understanding this correctly?
Yes, with .NET 3.5 SP1, the WCF DataContractSerializer will now serialize any POCO class just the same way as the XmlSerializer will - any public property will be serialized.
I don't know for sure whether that's a good thing - one of the pillars of WCF is being explicit, in order to clearly state your intent. I personally find it a good thing to mark your classes with [DataContract] and your fields and properties you want to have serialized explicitly with [DataMember] - it makes it clearer as to what's going on, and it doesn't hurt your POCO class at all.
And btw: you don't have to reference any "WCF plumbing" to do this - those attributes live in System.Runtime.Serialization - a very generic system assembly.....

WCF objects, multiple IList implementation and serialization errors

Problem:
WCF contract objects cannot implement 2 types of lists (ie: List and List).
Long-winded explanation:
I'm building a WCF service on top of an existing core system, and I'm trying to work out the best way to implement some of my business objects.
The core system utilizes interfaces for all business objects - Person management functionality, for instance, requires that I pass in an object which implements IPerson. Nothing out of the ordinary here.
The goal is to have a contact object (Person) which can be used on the service side of things, and also implements IPerson so that it can be passed into the core without requiring a conversion layer. This all works just fine for items like Person.
The issue comes in for lists: a method in the core, for instance, might require a IPersonList to be passed in, and as anyone who's dealt with inherited generics will know, List does not inherit from IList.
In our currently running ASMX service, we implement this with some up/down casting in the web objects. "WebPerson" will inherit from List, and implement IList explicitly so that the IList properties do not show up on the WSDL.
In WCF, however, if you try to use this same object, you will get the following error:
Type 'Cssi.IBroker.Service.Cssi.Contracts.PersonList' with CollectionDataContractAttribute attribute is an invalid collection type since it has multiple definitions of interface 'IList`1'.
Apparently, now that the new WCF serializer knows how to serialize IList, it's no longer able to ignore the second explicit implementation.
If possible, I'd like to avoid creating a PersonList object just for the contracts and then converting to and from an IPersonList object for each call. Changing the core business logic to use concrete objects designed just for the WCF services isn't an option.
Help!
I ended up deciding the best route was a set of dedicated objects used only for the contracts. With them being dedicated to one task, I was able to keep them cleaner without having to compromise my internal design for the sake of the WSDL. For the WSDL objects themselves, I ended up using arrays instead of IList.
The extra step of conversion is a bit cumbersome, but less than trying to keep my core objects WCF friendly would be.

WCF Contracts from Entity Framework?

I've been coming up with a lot of dead ends on this question. Supposedly, .NET 3.5 SP1 has Support for ADO.NET Entity Framework entities in WCF contracts. But when I look for solid info on it I'm not getting a lot of answers. I found this one snippet on an MSDN thread. Does anyone have any experience with this? What happened to the [DataContract]? Is this all there is to it? Why is there so little material on this?
This the answer from Tim Mallalieu in Microsoft.
Entity Types that are generated in the Entity Framework are, by default Data Contracts.
If I were to create a simple model in the Entity Designer like the following:
The cart Entity Type is by default a DataContract with all properties annotated as data members. We can then use this in a WCF service as follows:
[ServiceContract]
public interface IService1
{
[OperationContract]
Cart[] AllCarts();
}
public class Service1 : IService1
{
public Cart[] AllCarts()
{
using (MSPetShop4Entities context = new MSPetShop4Entities())
{
var carts = from c in context.Carts select c;
return carts.ToArray();
}
}
}
As the Entities are DataContracts you can now roll your services as you see fit and send these across the wire.
I recommend that you not return Entities directly. Unfortunately, Microsoft chose to include implementation-specific data as part of the DataContract for entities. This will not interoperate with other platforms, and is the sort of thing that might fail to interoperate even between .NET versions.
Instead, I recommend you follow the Data Transfer Object pattern and just return POCO classes that are copies of the data in the entities, with no behavior. You can return List of such classes to represent a table, etc.
The "sharing interfaces and not type" tenet presupposes that you don't own both ends of the wire and/or you're writing a public-facing web service. WCF can be used (and is used) in contexts where this is decidedly not the case. Many enterprise n-tier architectures have a WCF-fronted application tier to facilitate load-balancing among other things. In these cases it is perfectly valid to share type and, in fact, is desired.
You could go the easy way and use ADO.NET Data Services.
Some more detail in response to comments:
There are several problems with the classes generated by EF. I'm looking now at an AdventureWorks example with SalesOrderHeader and SalesOrderDetail. The SalesOrderDetail entity has both "SalesOrderHeader" and "SalesOrderHeaderReference" properties, both marked as DataMembers. This looks like a bug, since the "SalesOrderHeader" property is also marked [XmlIgnore] and [SoapIgnore].
Also, consider whether you want to serialize the link back to the parent SalesOrderHeader in the first place. Besides, what exactly should be serialized? SOAP doesn't support references in an interoperable manner.
Finally, the base classes of the entities are also data contracts. Yet they have nothing to do with the data you are returning - they are purely an implementation artifact.
In short, Microsoft screwed up on this one. They didn't think it through.
About ways to generate the DTO classes, I suggest looking into various code generation tools, like CodeSmith. You can write code to do this yourself; I did so in my previous position. The nice thing about generating the DTO is that you also get to generate the methods to translate to and from the DTO.
As to overhead, the overhead of moving some data around in memory is nothing compared to the amount of time it's going to take to send the data over a network!