DataContractSerializer, Ordering inconsistency between .Net and Mono - c#

For DataContractSerializer, items in XML must be ordered.
It is by "Order" attribute. Or in alphabetical order for .NET
For a Mono, it is ignored, so order is as data members mentioned in the serializable class. The bug with Mono is described here:
https://bugzilla.xamarin.com/show_bug.cgi?id=10545
Now, the problem is, we have a big project working on Mono. There are tons of config (XML-Config) files. As well as tons of Serializable objects.
In order for this to work in .Net, while still to be compatible with both, Mono and .Net, I have following options:
Explicitly add "Order" attribute to each of the serializable objects. So, .Net will repeat the same same numbering
Switch to the XmlSerializer. For this one I have to change attributes which are different between both. E.g., XML one includes all attributes unless it is told opposite (ignore attribute)
Both #1 and #2 assume lot of work. Is there a way or Serializer implementation, which will reuse existing Data classes done for DataContractSerializer?

Related

Can I use a .NET attribute without depending on the assembly that defines it?

I am unclear about the rules regarding attributes and assembly dependencies.
Is it possible (and not a terrible idea) to annotate the types in an assembly with custom attributes from a NuGet package without introducing a run-time dependency on that NuGet package? Could clients use the types in the assembly without also needing to have the custom package's assemblies present?
I ask because My .NET application uses two packages:
A third party NuGet package called YamlDotNet for serializing types to YAML. It lets you control YAML serialization with custom attributes analogous to Microsoft's XML attributes (e.g. it has YamlIgnoreAttribute like MS' XmlIgnoreAttribute)
My own package, PackageA which does not depend upon YamlDotNet.
I want my app to serialize my types from PackageA using YamlDotNet. But they will not serialize correctly unless I do one of the following:
annotate the types in PackageA with YamlDotNet custom attributes
create annotated wrappers for PackageA types in the App to do the serialization for me.
I can do #2, but it would be easier to do #1. But I do not want to introduce a run-time dependency on YamlDotNet for all clients of PackageA. Ideally, I would like anybody using PackageA who also happens to be using YamlDotNet to get those attibutes for free and for them to be invisible to anyone else.
Is what I want possible?
Attributes are a compile-time feature, you will always need reference to YamlDotNet in order to use one of its types as compile-time type metadata, unless you are open to doing things like generating your model classes in run-time (which is quite probably way more troublesome than having a one extra package reference).
This is a general problem where using attribute-driven features of a serializer pollutes the target assembly and couples it with that serializer.
There are three ways to address this:
Accept this as a compromise
Move YamlDotNet-specific into a separate assembly
Have a separate serialization model
The first point should be quite clear - this is what you don't want and your first ssuggestion.
The second point could be creating YamlDotNet-specific type wrappers or type converters (if it supports such things) in a separate assembly so that the core assembly stays clean. This is your second suggestion, just with a twist of converters that may be more pleasant than wrapping everything from consumer perspective.
The third point is about creating DTOs/payloads in the core assembly so that you never have to use any serializer-specific attributes and the serialization just works out of the box. If you need to [YamlIgnore] properties, the model used for serialization probably also serves other purposes so this is basically just a separation of concerns. If you serialize your application model, you might find it impossible to provide backwards compatibility without affecting business logic at various places as a result.

DataContract Issues

I need to develop a webservice which will be exposed to a java client over SOAP. We have a well defined schema in place which we use to communicate between both the systems. Now I need to expose an operation on my WCF contract which takes the Schema object and store it inside our DB.
I have followed the following for developing the webservice.
Host it over basichttp in wcf
Create an object model of the schema using xsd.exe
Take the schema as a parameter on the operation something like DoThis(SchemaObject schema)
Since this is going to be exposed in WCF, I have gone and modified the xsd tool generated object model. Our schema has mutiple level of nesting, and is a combination of 4 different schema linked together. The object graph generated by xsd tool has abstract classes, inheritence etc.
For this to work, I have gone and defined DataContract attrbute on everyclass and added the namespace to it, which was already there in the XmlTypeAttribute. Also I have added DataMemebers to each properties.
Some of the properties in the schema are arrays which was defined by the tool using xmlarrayitem attribute.
Now when I send a request using SOAP UI, the object is not getting deserialized as expected. Almost all the fields are coming as null, which has some sort of inheritence hierarchy. I have added KnownType attribute to the appropriate datacontracts, but still not working.
My question is:
Is this the right way to develop a webservice.
Is there a way to avoid putting the datacontract and data members and just work witht he serialization attributes added by the xsd tool?
Is it necessary to use datacontract attribute, will it not work with the xmlserialization attributes as it works inthe case xml deserialization?
WCF supports two types of serialization - DataContractSerializer and XmlSerializer.
XSD.exe generates strong type entities with all necessary XmlSerializer attributes. You do not need to add any DataContract or DataMemeber attributes to work with generated classes in WCF.
See MSDN for more details - http://msdn.microsoft.com/en-us/library/ms733901.aspx
Be also very careful with your entities generated by xsd.exe. As you probably already seen WCF server will eat many serialization changes you can do in these files but that will be breaking change for clients because they relay on XSD.
If possible I would remain these auto-generated entities without changes to guarantee that interface is not broken. You may introduce separate DTO classes for using in Business Layer. You can implement inheritence hierarchy over there.
Bunch of Unit Tests can help if you feel that auto-generated classes need to be changed. These Test Cases should generate different data sets, serialize them into XML and check that XML over XSD.
Technically, I don't see any particular flaw in the way you are implementing the service.
But from the architectural point of view it's too complicated for me. It's always easier to send 'flat' data-structures and hide complexity somewhere else.
I would suggest the following steps
Develop some special 'transport' scheme, maximally flattening it. It makes changes of the service easier when your model changes. And also it makes less painful to generate and cope with xsd.
Code special transformators on both sides of the channel to translate normal model to 'flat' and then vice-versa.

What's the difference between DataContractJsonSerializer and JavaScriptSerializer?

The .NET Framework ships with System.Runtime.Serialization.Json.DataContractJsonSerializer and System.Web.Script.Serialization.JavaScriptSerializer, both of which de/serialize JSON. How do I know when to choose one of these types over the other? MSDN doesn't make it clear what their relative advantages are.
We have several projects that consume or emit JSON, and the class selected for each thus far has depended on the opinion of the primary dev on each project. Some are simple, two have complex logic regarding producing managed types from JSON (the types do not map closely to the streams) but don't have any emphasis on speed, one requires speed. None interact with WCF, at least as of now.
While I'm interested in alternative libraries, I am hoping that somebody might have an answer to my question too.
The DataContractJsonSerializer is intended for use with WCF client applications where the serialized types are typically POCO classes with the DataContract attribute applied to them. No DataContract, no serialization. The mapping mechanism of WCF makes the sending and receiving very simple, but only if your platform is homogeneous. If you start mixing in different toolsets, your program might go sideways.
The JavaScriptSerializer can serialize any type, including anonymous types (one way), and does so in a more conformant way. You lose the "automagic" of WCF, but you gain more integration options.
As you can see by the comments, there are a lot of options out there for AJAX serialization, and to address your speed vs. maintainability questions, it might be worth investigating them to find a solution that meets the needs of all the teams, to reduce maintainability issues in the long term as everybody does things their own way.
2014-04-07 UPDATE:
I suggest using JSON.NET if you can. See http://james.newtonking.com/json Feature Comparison for a review of the 3 libraries considered in this question.
2015-05-26 UPDATE:
If your company requires the use of commercially licensable products, or you need every last bit of performance, you may also want to check out https://servicestack.net/.
Both do approximately the same but using very different infrastructure thus applying different restrictions on the classes you want to serialize/deserialize and providing different degree of flexibility in tuning the serialization/deserialization process.
For DataContractJsonSerializer you must mark all classes you want to serialize using DataContract atrtibute and all members using DataMember attribute. As well as if some of you classes have enum members, then the enums also must be marked as DataContract and each enum member - with EnumMember attribute.
Also DataContractJsonSerializer allows you fine control over the whole process of serialization/deserialization by altering types resolution logic and replacing the types you serialize with surrogates.
For JavaScriptSerializer you must provide parameterless constructor if you plan on deserializing objects from json string.
For me, I usually use JavaScriptSerializer in presentation logic, where there's a simple model I want to render in Json together with page, without additional ajax requests. And I even usually don't have to deserialize them back to c# - so there's no overhead at all. But if it's persistence logic, where I want to save objects into a data store (usually no-sql storage), to load them later, I prefer using DataContractJsonSerializer because the overhead of putting attributes is worth of flexibility in the serialization/deserialization process tuning, especially when it comes to loading of serialized data into the objects of the newer version, with updated definitions
Personally, I think that DataContractJsonSerializer reeks of over-engineering. I'd skip it and go with JavaScriptSerializer. In the event where JavaScriptSerializer isn't available, you can use FridayThe13th (a library I wrote ;p).

Is it possible to serialize complex object with Protocol Buffers C# (ProtoBuf-net)

Is it possible to serialize complex object with Protocol Buffers C# (ProtoBuf-net) without using Protocontract and proto files ?
[ProtoBuf.ProtoContract(ImplicitFields = ProtoBuf.ImplicitFields.AllPublic)]
I have tried to use the ProtoContract but even then I can't serialize object (It is a LLBLGen ORM object).
Yes; there are various options here;
firstly, note that "implicit fields" is brittle if you add members, since it has to make more guesses than I would like; only use that with stable contracts
you can apply a default behaviour globally via GlobalSettings, but I tend to advise against it
protobuf-net v1 can also work with:
XmlType/XmlElement attribute pairs, as long as the XmlElement specifies an Order
DataContract/DataMember attribute pairs, as long as the DataMember specifies an Order
partial classes; even for properties, via ProtoPartialMember attribute(s), etc
protobuf-net v2 can be used 100% without attributes of any kind, by using a TypeModel to describe the interesting types at runtime; this can also compile the model to a dedicated serialization dll if you need (in particular for use with AOT-dependent devices)
I can advise more, but there are a number of options presented; tell me which is/are most appropriate and I can add more detail.
Re .proto files; those are (and have always been) entirely optional with protobuf-net, as I recognise that there are a lot of cases where a code-first approach (or retrofit of serialization to an existing model) is useful. Three is a code-generator if you choose to use .proto, of course.

Why is Serializable Attribute required for an object to be serialized

Based on my understanding, SerializableAttribute provides no compile time checks, as it's all done at runtime. If that's the case, then why is it required for classes to be marked as serializable?
Couldn't the serializer just try to serialize an object and then fail? Isn't that what it does right now? When something is marked, it tries and fails. Wouldn't it be better if you had to mark things as unserializable rather than serializable? That way you wouldn't have the problem of libraries not marking things as serializable?
As I understand it, the idea behind the SerializableAttribute is to create an opt-in system for binary serialization.
Keep in mind that, unlike XML serialization, which uses public properties, binary serialization grabs all the private fields by default.
Not only this could include operating system structures and private data that is not supposed to be exposed, but deserializing it could result in corrupt state that can crash an application (silly example: a handle for a file open in a different computer).
This is only a requirement for BinaryFormatter (and the SOAP equivalent, but nobody uses that). Diego is right; there are good reasons for this in terms of what it does, but it is far from the only option - indeed, personally I only recommend BinaryFormatter for talking between AppDomains - it is not (IMO) a good way to persist data (to disk, in cache, to a database BLOB, etc).
If this behaviour causes you trouble, consider using any of the alternatives:
XmlSerializer, which works on public members (not just the fields), but demands a public parameterless constructor and public type
DataContractSerializer, which can work fully opt-in (using [DataContract]/[DataMember]), but which can also (in 3.5 and above) work against the fields instead
Also - for a 3rd-party option (me being the 3rd party); protobuf-net may have options here; "v2" (not fully released yet, but available as source) allows the model (which members to serialize, etc) to be described independently of the type, so that it can be applied to types that you don't control. And unlike BinaryFormatter the output is version-tolerant, known public format, etc.

Categories