I'm using attribute-free DataContract serialization (.NET 3.5 SP 1).
I want change EmitDefaultValue to false for all my DataContracts.
How I can achieve this?
If you want to use the EmitDefaultValue property on the DataMemberAttribute that you apply to a property, then you will have to apply the DataContractAttribute to the type.
This has the unfortunate side-effect of having to place the DataMemberAttribute attribute on all members of the type that you wish to serialize (the ones you were assuming before you used attribute-free Data Contract serialization) due to the nature of Data Contract serialization being all-in when using the attributes.
You can try implementing ISeriaizable interface.
In this case, DataContractSerializer will call your code to perform the mapping, giving you complete control.
Related
What is the benefit of keeping attribute in WCF service?
What I mean is why to give them [Datamember] and [Datacontract] and what's advantage and disadvantage?
What happens if I make attributes and its class in different project with simple class library project and I insert its "dll" reference to WCF service class library, which contains all operation that are [ServiceContract] and [operatinconntract] on this attribute.
WCF parameters need to be serializable. Value types such as int and string will be by default and therefore just work.
DataContractAttribute is used to mark complex types as serializable. See Using Data Contracts for more information.
Pre-WCF, serialization was done using the XmlSerializer class and by marking a type as [Serializable] it meant that all members were serialized by default.
However with DataContractSerializer which is the preferred serializer used in WCF, members of a class will not be serialized unless indicated.
Re having contract types in a different assembly - yes this is possible, and actually it's best practice to keep your contract types separate from your service implementation assembly.
A class that has the [DataContract] attribute, is it not automatically serialized?
If not, is it a requirement to use the [Serializable] attribute (or inherit from ISerialize)?
I ask this because I have old code from a previous project that apparently the [DataContract] classes do not mention anything, explicitly, about serialization.
The ultimate question:
I want a WCF operation (method) to return a DataContract class.
Does the method have to explicitly serialize the class before returning it, or is it automatically serialized? I always thought it would be the latter.
Thanks!
No, [Serializable] is not necessary on a data contract. It is also not necessary for XML Serialization.
There's a few options for serialization in .NET. SerializableAttribute and ISerializable go back to the beginning and are used by the BinaryFormatter, SoapFormatter, etc.
DataContractSerializer, being relatively new, can support objects that define their serialization ability with SerializableAttribute, but it's not necessary. If you are just serializing the object using DataContractSerializer then using the data contract attributes is all you need to do.
Obviously the members you mark as serializable must also be of serializable types.
For more information, see Types Supported by the Data Contract Serializer on MSDN.
Just to add on to this, DataContractSerializer supports far more than just DataContract types. See this excellent blog post for a detailed walk-through of the entire universe of types supported by DataContractSerializer: http://blogs.msdn.com/b/sowmy/archive/2006/02/22/536747.aspx
I created a simple WCF application which expose one operation. This operation takes a composite data type as parameter.
I have not decorated this composite data type with [DataContract] attribute. But this is working and I can see the Schema for this in WSDL.
Now my understanding is that this new custom type should be decorated with [Serializable] or [dataContract] attribute to take part in the Web services operation.
What I am missing here?
POCO support have been introduced in WCF since .NET 3.5 SP1 and you no longer need to decorate your objects with [DataContract] and [DataMember] attributes. Public properties will be automatically exposed. Although I would recommend you explicitly marking them with those attributes.
As Darin says, sp1 introduced support for inferred data contracts. If the marshalled type is a public type and it is not decorated with the DataContract attribute, WCF will automatically infer such an attribute and apply the DataMemeber attribute to all public members of the type.
In his book "Programming WCF Services", Juval Löwy says;
In my opinion, relying on inferred data contracts is a sloppy hack that goes against the grain of most everything else in WCF. ... Do use the DataContract attribute, and be explicit about your data contracts. This will enable you to tap into data contract features such as versioning.
I have a WCF service method that expects an object and then retrieves its properties using reflection.
On the client side I create an anonymous type object
var obj = new {FirstName="John", LastName="Doe"}
and pass it to the method. I'm getting an exception:
Type '<>f__AnonymousType0`2[System.String,System.String]' cannot be serialized.
Consider marking it with the DataContractAttribute attribute, and marking all
of its members you want serialized with the DataMemberAttribute attribute.
See the Microsoft .NET Framework documentation for other supported types.
I can't mark the type or its members with serialization attributes because there is really no type nor properties declared explicitly. Is there a way to overcome that problem?
The answers suggesting that you can't use an anonymous type over WCF are wrong.
If you are using the default DataContractSerializer to serialize your types on the channel, then yes, the answers are correct. This is because the DataContractSerializer supports the following scenarios:
Types serialized using the Serializable attribute
Types serialized using XML Serialization
Types serialized using the DataContract attribute
Plain-Old-C#-Object (POCO) Serialization
Respectively, they fail with anonymous types because of the following:
You can't apply attributes to anonymous types.
XML Serialization requires a default parameterless constructor, which anonymous types do not have.
Same as 1.
Same as 2.
However, you are not forced to use the DataContractSerializer to serialize your messages in WCF. You can create a custom message formatter which you can use to perform the serialization yourself.
You have a problem if the types you are sending out as the results of requests are anonymous types. When you get the results back, it's going to have a definite name within a namespace (not in a .NET sense, but in a SOA sense) and you are going to have to handle the mapping of that concrete type back to the anonymous type. However, because you don't have access to the actual anonymous type or ways of constructing it in code (at least in a dynamic way), you have no choice but to pass it along as an object if it's passed back to you, which makes it kind of worthless, since everyone will have to use bad practices such as dynamic (not a bad practice in itself, but to get around these limitations in this case, yes), or cast-by-example.
So in the end I will say that while it certainly is possible to serialize anonymous types and send them over the wire, the work invovled is usually not worth it.
Don't do this.
It's an attempt to be clever. Don't. Just declare the datatype you need, and use it. If you need a more loosely-defined datatype, just use a key-value mapping of some sort.
It will take you 5 minutes to write something that can handle this for good. Using any technique like this will cost you hours of debugging at some future point down the road.
You could serialize the object into a JSON string and send it through WCF, like so:
//in WCF Server
dynamic mysentclass = new { FirstName = "John", LastName = "Doe" };
string jsonstring = JsonConvert.SerializeObject(mysentclass, Newtonsoft.Json.Formatting.Indented);
//send the string through WCF
//in WCF client
dynamic myreceivedclass = JsonConvert.DeserializeObject<dynamic>(jsonstring);
MessageBox.Show(myreceivedclass.FirstName.ToString() + " " + myreceivedclass.LastName.ToString());
The example uses Json.Net, which can be obtained here:
http://www.nuget.org/packages/Newtonsoft.Json/
You could also use System.Web.Script.Serialization.JavaScriptSerializer (in System.Web.Extensions.dll), which is not as powerful as Json.Net, but would suffice for simple objects.
No, there is not. While there are tricks and techniques to return objects of an anonymous type from a method, you cannot send them over WCF.
WCF needs to know all of its concrete types that will be sent across, since you're not really just calling a .NET method. Instead, the message call gets converted into a serialized message, and therefore, any "thing" being passed over a WCF call must be serializable - no exceptions.
You've already got the answer. It can't be done.
In fact, you can't pass an instance of an anonymous type from one method to another within your program. You certainly can't pass them between programs.
As said before, the objects must be deserializable and so you will have to define the structure beforehand. However, you can use inheritance to defining them, and hence lower the pain. WCF provides the KnownType attribute to allow a Service Operation to receive an object of the base class and deserialize it into an object of a derived class. So you will still only have one (or a few) Service Operations that can handle all your scenarios.
I am working with WCF .NET 3.5 SP1 and have read that one does NOT have to decorate their Entities/Collections with such things as [DataMember], [DataConract], and/or [Serializable]? What is the best way to go? What have you all encountered?
I am on 3.5 SP1.
See Using Data Contracts.
New complex types that you create must
have a data contract defined for them
to be serializable. 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. You can opt out members
from serialization by using the
IgnoreDataMemberAttribute. You can
also explicitly create a data contract
by using DataContractAttribute and
DataMemberAttribute attributes. This
is normally done by applying the
DataContractAttribute attribute to the
type. This attribute can be applied to
classes, structures, and enumerations.
The DataMemberAttribute attribute must
then be applied to each member of the
data contract type to indicate that it
is a data member, that is, it should
be serialized. For more information,
see Serializable Types.
Like #Terry said, it's probably better to proactively declare which properties you want to expose. This way you could future proof your code from unintentionally exposing fields when the base class adds a public property in the future.
I'm of the opinion that it won't hurt to proactively express you intent to use the class as a DataContract. I would guess that a class that isn't serializable still won't be useful as a DataContract in SP1... :)