We have a 3rd party dll wich contains (among other things) our entities.
The entites are all marked with the [Serializeable] attribute.
We now need to creat a new WCF services which will expose some of this entities.
The problem is, since the entites are not declared with the DataContract and DataMember attributes, the property names are appended with __BackingField!
I know using the DataContarct\Member attributes will solve this issue, but given that I cannot modify the 3rd party dll with the entities, is there a different workaround?
Types decorated with the [Serializable] attribute have their fields serialized, not properties (that's the [Serializable] "contract"). If the 3rd party types use automatic properties (as shown below), the compiler will create a field with the k_BackingField suffix, and this is what will be serialized.
If you cannot change the types in the 3rd party library, one alternative would be to use that same library on the client. When creating the proxy for the service (using either svcutil or Add Service Reference), you can reference the 3rd party library, and the generated client won't create new types for the contracts, instead reusing the types from the library. This way you won't have to deal with types with public _BackingField property names.
Automatic properties:
[Serializable]
public class MyType
{
public string MyProp { get; set; }
}
The compiler will turn it into something similar to
[Serializable]
public class MyType
{
private string <MyProp>k_BackingField;
public string MyProp
{
[CompilerGenerated]
get { return this.<MyProp>k_BackingField; }
[CompilerGenerated]
set { this.<MyProp>k_BackingField = value; }
}
}
You can use the XmlSerializerFormatAttribute to use XmlSerializer instead of DataContractSerializer in the service implementation.
It will perform slower but it should sovle your problem.
I am assuming you want to expose these third party types from a service.
One solution which you may consider is to maintain a separate library which mirrors the types in the third party library.
This has the following benefits:
Ownership - You own the types you are exposing therefore you control the serialization/deserialization across your service boundary.
You are insulated from sudden changes to the other party's types and can change your interfaces in a controlled fashion.
From a SOA perspective if you are exposing another party's types on your service the other party should supply the types in a contractural format like XSD. I think your design calls for some fairly unreasonable hoop-jumping on your part.
It may be more work up front but it is kind of a one-off exercise.
Hope this helps some.
Related
Following advices from people on the internet about service references, I got rid of them now and split the service/data contracts into a common assembly accesible by both the server and the client. Overall this seems to work really well.
However I’m running into problems when trying to use custom objects, or rather custom subtypes, in the service. Initially I wanted to define only interfaces in the common assembly as the contract for the data. I quickly learned that this won’t work though because the client needs a concrete class to instantiate objects when receiving objects from the service. So instead I used a simple class instead, basically like this:
// (defined in the common assembly)
public class TestObject
{
public string Value { get; set; }
}
Then in the service contract (interface), I have a method that returns such an object.
Now if I simply create such an object in the service implementation and return it, it works just fine. However I want to define a subtype of it in the service (or the underlying business logic), that defines a few more things (for example methods for database access, or just some methods that work on the objects).
So for simplicity, the subtype looks like this:
// (defined on the server)
public class DbTestObject : TestObject
{
public string Value { get; set; }
public DbTestObject(string val)
{
Value = val;
}
}
And in the service, instead of creating a TestObject, I create the subtype and return it:
public TestObject GetTestObject()
{
return new DbTestObject("foobar");
}
If I run this now, and make the client call GetTestObject, then I immediately get a CommunicationException with the following error text: “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 underlying network resource issue. Local socket timeout was '00:09:59.9380000'.”
I already found out, that the reason for this is that the client does not know how to deserialize the DbTestObject. One solution would be to declare the base type with the KnownTypeAttribute to make it know about the subtype. But that would require the subtype to be moved into the common assembly, which is of course something I want to avoid, as I want the logic separated from the client.
Is there a way to tell the client to only use the TestObject type for deserialization; or would the solution for this be to use data transfer objects anyway?
As #Sixto Saez has pointed out, inheritance and WCF don't tend to go together very well. The reason is that inheritance belongs very much to the OO world and not the messaging passing world.
Having said that, if you are in control of both ends of the service, KnownType permits you to escape the constraints of message passing and leverage the benefits of inheritance. To avoid taking the dependency you can utilise the ability of the KnownTypeAttribute to take a method name, rather than a type parameter. This allows you to dynamically specify the known types at run time.
E.g.
[KnownType("GetKnownTestObjects")]
[DataContract]
public class TestObject
{
[DataMember]
public string Value { get; set; }
public static IEnumerable<Type> GetKnownTestObjects()
{
return Registry.GetKnown<TestObject>();
}
}
Using this technique, you can effectively invert the dependency.
Registry is a simple class that allows other assemblies to register types at run-time as being subtypes of the specified base class. This task can be performed when the application bootstraps itself and if you wish can be done, for instance, by reflecting across the types in the assembly(ies) containing your subtypes.
This achieves your goal of allowing subtypes to be handled correctly without the TestObject assembly needing to take a reference on the subtype assembly(ies).
I have used this technique successfully in 'closed loop' applications where both the client and server are controlled. You should note that this technique is a little slower because calls to your GetKnownTestObjects method have to be made repeatedly at both ends while serialising/deserialising. However, if you're prepared to live with this slight downside it is a fairly clean way of providing generic web services using WCF. It also eliminates the need for all those 'KnownTypeAttributes' specifying actual types.
Im am not new to WCF web services but there has been a couple of years since the last time I used one. I am certain that last time I used a WCF service you could determine the type of object returned from a service call when developing the code. EG;
MyService.Models.ServiceSideObjects.User user = myServiceClient.GetUser();
You were then free to use the 'user' object client-side. However now it seems as if the WCF service will not return anything more than objects containing basic value types (string, int ect). So far I have remedied this by defining transfer objects which contain only these basic value types and having the service map the complex 'User' objects properties to simple strings and int's in the transfer object.
This becomes a real pain when, for example you have custom type objects containing more complex objects such as my Ticket object.
public class Ticket
{
public Agent TicketAgent {get;set;}
public Client Owner {get;set;}
public PendingReason TicketPendingReason {get;set;}
}
As simply mapping this object graph to a single transfer class with a huge list of inter-related system-typed properties gives a very 'dirty' client-side business model. Am I wrong in thinking that I SHOULD be able to just receive my Ticket object from a service method call and deal with it client side in the same state it was server-side ?
I realise this is probably a violation of some SoA principal or similar but my desktop app currently consuming this service is the ONLY thing that will consume ever consume it. So i do not care if many other clients will be able to manage the data types coming back from the service and therefore require some hugely normalised return object. I just want my service to get an object of type Ticket from its repository, return this object to the client with all its properties intact. Currently all I get is an object with a single property 'ExtentionData' which is unusable client-side.
Hope this makes sense, thank you for your time.
I might've missed a memo, but I think you need to decorate your model classes with DataContractAttribute and your properties with DataMemberAttribute, like so:
[DataContract( Namespace = "http://example.com" )]
public class Ticket
{
[DataMember]
public Agent TicketAgent { get; set; }
[DataMember]
public Client Owner { get; set; }
[DataMember]
public PendingReason TicketPendingReason { get; set; }
}
This is why you probably want to set up a DTO layer, to avoid polluting your model classes.
As for ExtensionData, it's used for forward-compatibility: http://msdn.microsoft.com/en-us/library/ms731083.aspx
I have marked Niklas's response as an answer as it has solved my issue.
While it seems you do not NEED to use [DataContract] and [DataMember], in some cases, I believe it could cause the issues I was experiencing. When simply transferring custom typed objects which, in themselves, only have simply typed properties, no attributes needed. However, when I attempted to transfer a custom typed object which itself had collections / fields of more custom typed objects there attributes were needed.
Thank you for your time.
I understand that we can have more controls on a class if we use datacontract, however, consider the following 2 cases
[DataContract]
public class Customer
{
[DataMember]
public string CustomerName {get; set;}
[DataMember]
public int Age{get; set;}
}
and
public class Customer
{
public string CustomerName {get; set;}
public int Age{get; set;}
}
They both get serialized correctly on .net client. And personally I do not use second example. Can anybody point me the differences in the 2 classes? I meant to send all public properties in both classes.
The second version is the POCO (plain old CLR object) version of your data contract and can be used with WCF since 3.5 sp1.
I would not recommend using it though as it gives you very little control on the serialization (namespace attributes...) and it couples your service entities with your business entities (which can be same with POCO)
Anyway here is a better story from "Programming WCF services, 3rd Edition"
While using the Serializable attribute
is workable, it is not ideal for
service-oriented interaction between
clients and services. Rather than
denoting all members in a type as
serializable and therefore part of the
data schema for that type, it would be
preferable to have an opt-in approach,
where only members the contract
developer wants to explicitly include
in the data contract are included. The
Serializable attribute forces the data
type to be serializable in order to be
used as a parameter in a contract
operation, and it does not offer clean
separation between the ability to use
the type as a WCF operation parameter
(the “serviceness” aspect of the type)
and the ability to serialize it. The
attribute offers no support for
aliasing type names or members, or for
mapping a new type to a predefined
data contract. The attribute operates
directly on member fields and
completely bypasses any logical
properties used to access those
fields. It would be better to allow
those properties to add their values
when accessing the fields. Finally,
there is no direct support for
versioning, because the formatter
supposedly captures all versioning
information. Consequently, it is
difficult to deal with versioning over
time.
I am very confused about the DataContract attribute in WCF. As per my knowledge it is used for serializating user defined type like classes. I wrote one class which is exposed at client side like this.
[DataContract]
public class Contact
{
[DataMember]
public int Roll { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public string Address { get; set; }
[DataMember]
public int Age { get; set; }
}
It is working properly but when I remove DataContract and DataMember it also works properly. I can't understand why it is working properly. Can any one tell me what is the actual use of DataContract?
My service contract looks like this
[ServiceContract]
public interface IRestServiceImpl
{
[OperationContract]
Contact XmlData(string id);
}
Since a lot of programmers were overwhelmed with the [DataContract] and [DataMember] attributes, with .NET 3.5 SP1, Microsoft made the data contract serializer handle all classes - even without any of those attributes - much like the old XML serializer.
So as of .NET 3.5 SP1, you don't have to add data contract or data member attributes anymore - if you don't then the data contract serializer will serialize all public properties on your class, just like the XML serializer would.
HOWEVER: by not adding those attributes, you lose a lot of useful capabilities:
without [DataContract], you cannot define an XML namespace for your data to live in
without [DataMember], you cannot serialize non-public properties or fields
without [DataMember], you cannot define an order of serialization (Order=) and the DCS will serialize all properties alphabetically
without [DataMember], you cannot define a different name for your property (Name=)
without [DataMember], you cannot define things like IsRequired= or other useful attributes
without [DataMember], you cannot leave out certain public properties - all public properties will be serialized by the DCS
So for a "quick'n'dirty" solution, leaving away the [DataContract] and [DataMember] attributes will work - but it's still a good idea to have them on your data classes - just to be more explicit about what you're doing, and to give yourself access to all those additional features that you don't get without them...
In terms of WCF, we can communicate with the server and client through messages. For transferring messages, and from a security prospective, we need to make a data/message in a serialized format.
For serializing data we use [datacontract] and [datamember] attributes.
In your case if you are using datacontract WCF uses DataContractSerializer else WCF uses XmlSerializer which is the default serialization technique.
Let me explain in detail:
basically WCF supports 3 types of serialization:
XmlSerializer
DataContractSerializer
NetDataContractSerializer
XmlSerializer :- Default order is Same as class
DataContractSerializer/NetDataContractSerializer :- Default order is Alphabetical
XmlSerializer :- XML Schema is Extensive
DataContractSerializer/NetDataContractSerializer :- XML Schema is Constrained
XmlSerializer :- Versioning support not possible
DataContractSerializer/NetDataContractSerializer :- Versioning support is possible
XmlSerializer :- Compatibility with ASMX
DataContractSerializer/NetDataContractSerializer :- Compatibility with .NET Remoting
XmlSerializer :- Attribute not required in XmlSerializer
DataContractSerializer/NetDataContractSerializer :- Attribute required in this serializing
so what you use depends on your requirements...
A data contract is a formal agreement between a service and a client that abstractly describes the data to be exchanged. That is, to communicate, the client and the service do not have to share the same types, only the same data contracts. A data contract precisely defines, for each parameter or return type, what data is serialized (turned into XML) to be exchanged.
Windows Communication Foundation (WCF) uses a serialization engine called the Data Contract Serializer by default to serialize and deserialize data (convert it to and from XML). All .NET Framework primitive types, such as integers and strings, as well as certain types treated as primitives, such as DateTime and XmlElement, can be serialized with no other preparation and are considered as having default data contracts. Many .NET Framework types also have existing data contracts.
You can find the full article here.
A data contract is a formal agreement between a service and a client that abstractly describes the data to be exchanged.
Data contract can be explicit or implicit. Simple type such as int, string etc has an implicit data contract. User defined object are explicit or Complex type, for which you have to define a Data contract using [DataContract] and [DataMember] attribute.
A data contract can be defined as follows:
It describes the external format of data passed to and from service operations
It defines the structure and types of data exchanged in service messages
It maps a CLR type to an XML Schema
It defines how data types are serialized and deserialized. Through serialization, you convert an object into a sequence of bytes that can be transmitted over a network. Through deserialization, you reassemble an object from a sequence of bytes that you receive from a calling application.
It is a versioning system that allows you to manage changes to structured data
We need to include System.Runtime.Serialization reference to the project. This assembly holds the DataContract and DataMember attribute.
Data contract: It specifies that your entity class is ready for Serialization process.
Data members: It specifies that the particular field is part of the data contract and it can be serialized.
Also when you call from http request it will work properly but when your try to call from net.tcp that time you get all this kind stuff
DataMember attribute is not mandatory to add to serialize data. When DataMember attribute is not added, old XMLSerializer serializes the data. Adding a DataMember provides useful properties like order, name, isrequired which cannot be used otherwise.
The data is to be transferred and processed within service and they store the values, so in the WCF terminology they are called “Data Contract”.
Where each member of the Class; i.e., The data contract is called “Data Member” and they are also to be decorated with the Attributes.
Source
In some enterprise-like project (.NET, WCF) i saw that all service contracts accept a single Request parameter and always return Response:
[DataContract]
public class CustomerRequest : RequestBase {
[DataMember]
public long Id { get; set; }
}
[DataContract]
public class CustomerResponse : ResponseBase {
[DataMember]
public CustomerInfo Customer { get; set; }
}
where RequestBase/ResponseBase contain common stuff like ErrorCode, Context, etc. Bodies of both service methods and proxies are wrapped in try/catch, so the only way to check for errors is looking at ResponseBase.ErrorCode (which is enumeration).
I want to know how this technique is called and why it's better compared to passing what's needed as method parameters and using standard WCF context passing/faults mechanisms?
The pattern you are talking about is based on Contract First development. It is, however not necessary that you use the Error block pattern in WCF, you can still throw faultexceptions back to the client, instead of using the Error Xml block. The Error block has been used for a very long time and therefore, a lot of people are accustom to its use. Also, other platform developers (java for example) are not as familiar with faultExceptions, even though it is an industry standard.
http://docs.oasis-open.org/wsrf/wsrf-ws_base_faults-1.2-spec-os.pdf
The Request / Response pattern is very valuable in SOA (Service Oriented Architecture), and I would recommend using it rather than creating methods that take in parameters and pass back a value or object. You will see the benefits when you start creating your messages. As stated previously, they evolved from Contract First Development, where one would create the messages first using XSDs and generate your classes based on the XSDs. This process was used in classic web services to ensure all of your datatypes would serialize properly in SOAP. With the advent of WCF, the datacontractserializer is more intelligent and knows how to serialize types that would previously not serialize properly(e.g., ArrayLists, List, and so on).
The benefits of Request-Response Pattern are:
You can inherit all of your request and responses from base objects where you can maintain consistency for common properties (error block for example).
Web Services should by nature require as little documentation as possible. This pattern allows just that. Take for instance a method like public BusScheduleResponse GetBusScheduleByDateRange(BusDateRangeRequest request); The client will know by default what to pass in and what they are getting back, as well, when they build the request, they can see what is required and what is optional. Say this request has properties like Carriers [Flag Enum] (Required), StartDate(Required), EndDate(Required), PriceRange (optional), MinSeatsAvailable(Option), etc... you get the point.
When the user received the response, it can contain a lot more data than just the usual return object. Error block, Tracking information, whatever, use your imagination.
In the BusScheduleResponse Example, This could return Multiple Arrays of bus schedule information for multiple Carriers.
Hope this helps.
One word of caution. Don't get confused and think I am talking about generating your own [MessageContract]s. Your Requests and Responses are DataContracts. I just want to make sure I am not confusing you. No one should create their own MessageContracts in WCF, unless they have a really good reason to do so.