WCF Attribute Weaver - c#

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

Related

Undiscovered POCO class requirements

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.

How to create a WCF Data Services OData with with the Reflection Provider using model classes from different project?

Following the instructions to use the Reflection Provider (http://msdn.microsoft.com/en-us/library/dd728281.aspx) everything works well, until I move the classes Order and Item to a Class Library and reference the class library from the web project with the SVC file.
Move the POCO classes into the WCF project all goes well.
Move the POCO classes out of the WCF project into separate assembly, I get a 500 with no explanation.
I want to be able to keep my poco classes in a separate project and expose them with an OData endpoint. What am I doing wrong?
--UPDATE--
The scenario described above is meant to illustrate a problem I have found using the WCF OData Reflection Provider. It is not my real problem, but is easier to explain for illustrative purposes.
Try upgrading to the latest version of WCF Data Services (currently 5.3), if you aren't already on it. I reproduced your issue using the version of WCF Data Services that ships with .Net 4.5, but once I upgraded the references in both assemblies to the latest release of Microsoft.Data.Services using NuGet, the problem went away.
If you're already using the most up-to-date version of WCF Data Services, make sure that both assemblies are referencing the exact same version of WCF Data Services.
If neither of these fix your problem, add the following attribute to your DataService class to get a more detailed error message and stack trace:
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
public class YourService : DataService<...>
And then please update your question with the results of that (if the solution doesn't immediately jump out from the stack trace).
(disclaimer: I usually don't like answers of the kind that don't help you with your problem but rather explain why your problem isn't the correct problem, but I think it's justified in this case :))
If you think about it, you don't really want to do that:
The Order and Item classes aren't really POCOs at all; they're not 'plain' C# objects; they have data attributes on them, which make them data transfer objects (DTOs).
They belong to the interface between your service and its clients;
The domain entities (or POCOs) Item and Order will, most likely, be a bit more complex, and contain other things besides data, such as operations and business logic.
I believe the correct way to go is to have a rich domain model, in which Order and Item contain a full set of attributes and operations, and on top of that, a DTO layer, which contains only those attributes that your service client needs.
Sending your POCOs over the wire was termed 'the stripper pattern', and I believe it's best avoided.

Adding AutoMapper Type Mapping Conventions For Generic Types in WCF Contract

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?

xsd.exe - schema to class - for use with WCF

I have created a schema as an agreed upon interface between our company and an external company. I am now creating a WCF C# web service to handle the interface.
I ran the XSD utility and it created a C# class. The schema was built in BizTalk, and references other schemas, so all-in-all there are over 15 classes being generated.
I put [DataContract} attribute in front of each of the classes.
Do I have to put the [DataMember] attribute on every single property?
When I generate a test client program, the proxy does not have any code for any of these 15 classes.
We used to use this technique when using .asmx services, but not sure if it will work the same with WCF. If we change the schema, we would want to regenerate the WCF class, and then we would haev to each time redecorate it with all the [DataMember] attributes? Is there an newer tool similar to XSD.exe that will work better with WCF?
Thanks,
Neal Walters
SOLUTION (buried in one of Saunders answer/comments):
Add the XmlSerializerFormat to the Interface definition:
[OperationContract]
[XmlSerializerFormat] // ADD THIS LINE
Transaction SubmitTransaction(Transaction transactionIn);
Two notes:
1) After I did this, I saw a lot more .xsds in the my proxy (Service Reference) test client program, but I didn't see the new classes in my intellisense.
2) For some reason, until I did a build on the project, I didn't get all the classes in the intellisense (not sure why).
Neal, besides all the options John has given you, you should also check out the WCSF.blue tool on Codeplex: http://wscfblue.codeplex.com/
It's a "contract first" approach to doing WCF, and one of the many options it offers is to create a WCF DataContract file from your XSD:
This then pops up a dialog in which you can set a slew of parameters on how to create your C# class file from the XSD:
Quite useful, even if you want to use it for nothing more than converting XSD to C# classes that work as WCF DataContracts :-)
Also see this blog post for more explanations on the XSD DataContract generation process.
Classes that use [DataContract] will serialize to a very limited schema. For instance, there will be no attributes, only elements. This is intentional, and is done for performance and interoperability.
In general, a schema of the kind you may be working with may be much more complicated. Such a schema will not be usable with the Data Contract Serializer. You will need to use the XML Serializer instead.
In particular, don't edit the classes created by XSD.EXE. In fact, you should never edit generated code, as your edits will be removed as soon as the code is generated again. These classes should already have the attributes on them that will be needed for WCF to work with them.
What happens if you just use them as-is?
I'm shocked that no one pointed me to this utility, which I believe is what I was asking for:
http://msdn.microsoft.com/en-us/library/system.runtime.serialization.xsddatacontractimporter.aspx
I haven't tried it yet, but it looks like XsdDataContractImporter was what I was looking for, or the SVCUTIL with the /dataContractOnly flag.
I learned this when interviewing a candidate yesterday. She said DataContract serialization is faster and would be preferred to use.
Neal
Re: your XsdDataContract class mentioned in your followup, IMO, This is a niche class (as is ServiceContractGenerator etc) so i'm not surprised no one pointed you to it.
You still need to package it up to make it really useful. I'm pretty sure that code sample covers only very basic use cases so I would expect to do a lot of work with that to get it to a proper working state. . And like i mentioned on the WSCF forum, Svcutil, wscf, xsd.exe and others all use this class and related classes in the code gen process.
Regards the serializer performance, there are really good posts on Youssef Moussaoui's blog on the different serializers and their performance especially
http://blogs.msdn.com/youssefm/archive/2009/07/10/comparing-the-performance-of-net-serializers.aspx
There’s also a really good discussion here on Connect regarding the two serializers (XS and DCS) and a useful point that XS is still the way forward for WSDL/XSD First development as the DCS is only intended to support a simplified programming model and thus doesn’t support various xml constructs.
http://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=451277
Hope this helps,
Cheers,
Benjy

Converting from One Class to another Class using Xml Serialization in C#

In our project we are consuming WCF webservices exposed at Central location as services with basicHttpBinding.
In client desktop application we need consume those webservices. I am able to generate proxy class using WSDL.exe.
But, I need to convert data/class given by the webservice into my local class, for that now I am xmlserialzing those class/objects given by webservice and deserializing into my local classes as both classes schema matches exactly same.
Is there any better way that I can follow?
or
Do I need to assign each property from one class to another?
thanks
nRk.
declare class manually instead of generating. This is the most DRY solution.
try Automapper
If you have control on your local classes (they are not generated code; or you are generating them, yourself) you can use xml attributes to decorate your class, so you can serialize and deserialize it to that xml you work with and you do not have to have specific names for your properties. In addition to this, you may have additional properties on your local class.
If you have not control on defining your local classes, then you have to define a converter or as elder_george mentioned, use AutoMapper.
Using a manual written converter IMO is the fastest way and you can define them as implicit converter operators on your local class.
I've done the serialize/deserialize thing myself just as you had. If your classes have the same properties as the proxy classes you could write a helper method that uses reflection to iterate through the properties of the proxy and set the corresponding properties of your class. As long as the property names are the same, that one method should work on all classes.
A few thoughts:
use assembly sharing via WCF; this allows you to use the same actual assembly at both ends. As long as this is a DTO assembly, this is fine (not hugely portable, though). This is /reference (also /r) in svcutil.exe, or you can do it via the IDE
use DataContractSerializer and round-trip (like you are already; just that WCF maps most closely to DataContractSerializer, not XmlSerializer)

Categories

Resources