WCF DataMember List<> without enclosing element - c#

The following DataContract:
[DataContract(Namespace = "http://namespace", Name = "Blarg")]
public class Blarg
{
[XmlAttribute("Attribute")]
public string Attribute{ get; set; }
[DataMember(Name = "Record", IsRequired = false, Order = 4)]
public List<Record> Record{ get; set; }
}
Serializes into this:
<Blarg Attribute="blah">
<Record>
<Record/>
<Record/>
<Record/>
</Record>
</Blarg>
But I want this:
<Blarg>
<Record/>
<Record/>
<Record/>
<Blarg/>
The DataContractSerializer seems to be inserting the header parent automagically and I don't want it.
How do I go about removing the wrapping <Record>?

I don't think you can do that.
The DataContractSerializer is optimized for speed, and in the process it sacrifices some flexibility and some features (like XML attributes). I don't think you have much chance to influence the DCS - it does its job as it sees fit, and as quickly as possible. You get to define quite neatly what to serialize (with the [DataMember] attribute, but you don't really have a say in how to serialize.
If you need more control, you could pick the XmlSerializer instead - in that case, you have 10-15% slower serialization, but you can control things like the shape of the data etc. But even in this case - I am not aware of any way you can tell the XML serializer to serialize a collection into a series of XML tags without an enclosing tag for the collection.

I found the answer here.
See the short story bellow(for the long one checkout the url):
[XmlElement ("Parameter")]
public List<Parameter> Parameters;

Related

How to change xml attribute while deserialization with xmlserializer c#?

Is there any way of modifying attribute value when deserializing xml using XmlSerializer?
For instance, I have such xml:
<chunkList>
<chunk id="ch1" type="p">
<sentence id="s1">
<tok>
<orth>XXX</orth>
<lex disamb="1">
<base>XXX</base>
<ctag>subst:sg:nom:f</ctag>
</lex>
</tok>
</sentence>
</chunk>
</chunkList>
I want to deserialize chunk element into Chunk class and set attribute id="ch1" to Id property - is there any way of trimming this ch substring and asigning number 1 to property of type int?
[XmlAttribute("id")] //maybe there is some attribute to achive this?
public int Id { get; set; }
I have read some of MSDN documentation but didn't found any solution.
There is no elegant way to achieve this using a single attribute. The only way I know to achieve the desired result is to make use of [XmlIgnore] and to create a second property specifically for the stringified xml ID, and a localized converter property for your internal integer value. Some along the lines of:
[XmlAttribute("id")]
public string _id_xml {get; set;}
[XmlIgnore]
public int Id {
// convert local copy of xml attribute value to/from int.
get => int.Parse(_id_xml.Replace("ch",""));
set => _id_xml = $"ch{value}";
}
My converter here is very basic and clearly you will need to improve it and consider error handling.
The serializer will operate against the [XmlAttribute] as normal, but pass over the [XmlIgnore]. Your c# code could use either.
Unfortunately, the XmlSerializer requires public properties, so you can not hide the _id_xml property from your code, but you could use [Obsolete] to signal a warning in the compiler.
You could do the conversion to/from int with the _id_xml getter & setter, but doing this could be problematic when managing errors during serialization.

Deserializing XML in C# where a property could be either an attribute or an element

I'm writing a C# library that, as one of its functions, needs to be able to accept XML of the following forms from a web service and deserialize them.
Form 1:
<results>
<sample>
<status>status message</status>
<name>sample name</name>
<igsn>unique identifier for this sample</igsn>
</sample>
</results>
Form 2:
<results>
<sample name="sample name">
<valid code="InvalidSample">no</valid>
<status>Not Saved</status>
<error>error message</error>
</sample>
</results>
Here's my class that I'm deserializing to:
namespace MyNamespace
{
[XmlRoot(ElementName = "results")]
public class SampleSubmissionResponse
{
[XmlElement("sample")]
public List<SampleSubmissionSampleResultRecord> SampleList { get; set; }
...
}
public class SampleSubmissionSampleResultRecord
{
...
/* RELEVANT PROPERTY RIGHT HERE */
[XmlAttribute(Attribute = "name")]
[XmlElement(ElementName = "name")]
public string Name { get; set; }
...
}
public class SampleSubmissionValidRecord
{
...
}
}
The problem is that in one XML sample, the name attribute of the Sample element is an element, and in the other it's an attribute. If I decorate the property of my class with both XmlAttribute and XmlElement, I get an exception thrown when creating an instance of XmlSerializer.
I've been googling for a good while now, and I can't find any docs that deal with this situation. I assume, but don't know for sure, that this is because when creating an XML schema, you're not supposed to use the same name for an attribute and a child element of the same element.
So, what do I do here?
One solution might be to have two totally separate models for the different types. That would probably work, but doesn't seem very elegant.
Another option might be to implement IXmlSerializable and write some elaborate code to handle this in the deserialize method. That would be an awfully verbose solution to a simple problem.
Third option I'm hoping for: some way of applying both XmlAttribute and XmlElement to the same property, or an equivalent "either-or" attribute.
Fourth option: Change the web service the XML comes from to use one form consistently. Unfortunately, the folks who own it may not be willing to do this.
Specify only one attribute to Name property. This will correctly parse out the first xml form.
public class SampleSubmissionSampleResultRecord
{
[XmlElement(ElementName = "name")]
public string Name { get; set; }
}
To parse the second xml form, subscribe the XmlSerializer to the UnknownAttribute event.
var xs = new XmlSerializer(typeof(SampleSubmissionResponse));
xs.UnknownAttribute += Xs_UnknownAttribute;
In the event handler, we get the desired value.
private void Xs_UnknownAttribute(object sender, XmlAttributeEventArgs e)
{
var record = (SampleSubmissionSampleResultRecord)e.ObjectBeingDeserialized;
record.Name = e.Attr.Value;
}

WCF DataContractSerializer Performance with long property names

I am transferring large chunks of data over WCF, and I am trying to optimize the results sent. I have switched from NetDataContactSerializer to DataContractSerializer, but since it is no longer being serialized as XML, I wonder exactly what happens.
As an example, imagine I serialize a collection (100,000 records) of the following to XML:
public class SomeDataObject
{
public string AnExcessivelyLongPropertyNameJustToIllustrateMyPoint { get; set; }
}
It would look something like this:
<a:SomeDataObject>
<b:AnExcessivelyLongPropertyNameJustToIllustrateMyPoint>
ABC
</b:AnExcessivelyLongPropertyNameJustToIllustrateMyPoint>
</a:SomeDataObject>
Now, from the above, it is clear that for hundreds of thousands of records, there is a significant performance gain in naming the property something else, like this:
<a:SomeDataObject>
<b:NormalName>ABC</b:NormalName>
</a:SomeDataObject>
My question is: When using a netTcp binding and the default DataContactSerializer, is it intelligent enough to not actually repeat the names of the properties being serialized?
Or if you don't know the answer to this, is there an easy way to measure this?
For WPF serialization to have smaller XML add short name in Name attribute like:
[DataContract(Name="sdo")]
public class SomeDataObject
{
[DataMember(Name = "axlpnjtimp")]
public string AnExcessivelyLongPropertyNameJustToIllustrateMyPoint { get; set; }
}
For manual XML serialization using XmlSerializer add attribute [XmlType(TypeName = "x")] for class and [XmlElement("y")] for properties.
In your case I would so something like:
[XmlType(TypeName = "sdo")]
public class SomeDataObject
{
[XmlElement("axlpnjtimp")]
public string AnExcessivelyLongPropertyNameJustToIllustrateMyPoint { get; set; }
}
And serialized xml:
<?xml version="1.0" encoding="utf-16"?>
<sdo>
<axlpnjtimp>Property Name</axlpnjtimp>
</sdo>
It will reduce send data size considerably.

Deserialize json array data in c# [duplicate]

I need to deserialize some JavaScript object represented in JSON to an appropriate C# class. Given the nice features of automatic properties, I would prefer having them in these classes as opposed to just having fields. Unfortunately, the .NET serialization engine (at least, by default) totally ignores automatic properties on deserialization and only cares about the backing field, which is obviously not present in the JavaScript object.
Given that there's no standard way to name backing fields and to be honest I don't even want to bother with the "let's create a JavaScript object that looks like it had C# backing fields" approach as it sounds a bit dirty, the only way I could serialize JavaScript fields to C# auto-properties if I could force the serialization engine to somehow ignore the backing field and use the property directly. Unfortunately, I can't figure out how this is done or if this can be done at all. Any ideas would be appreciated.
EDIT: Here's an example:
Javascript:
function Cat()
{
this.Name = "Whiskers";
this.Breed = "Tabby";
}
var cat = new Cat();
This is then serialized to "{Name: 'Whiskers'}".
The C# class:
[Serializable()]
public class Cat
{
public string Name { get; set; }
public string Breed { get; set; }
}
And the deserialization code, that fails:
new DataContractJsonSerializer(typeof(Cat)).ReadObject(inputStream);
And it is apparent from the exception that it fails because it is looking for the backing field.
EDIT2: Here's the exception, if that helps (no inner exceptions):
System.Runtime.Serialization.SerializationException
"The data contract type 'Test.Cat'
cannot be deserialized because the
required data members
'<Name>k__BackingField, <Breed>k__BackingField' were not
found."
What's happening here is the deserializer is trying to guess the name of your backing fields.
You can solve this by adding explicit mappings (DataContract/DataMember attributes) like this:
[DataContract]
public class Cat
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Breed { get; set; }
}
You can do this with JavaScriptSerializer found in the System.Web.Script.Serialization namespace:
JavaScriptSerializer serializer = new JavaScriptSerializer();
Cat c = serializer.Deserialize<Cat>(jsonString);
I have POCO objects with automatic properties and this works just fine.
EDIT: I wrote about JSON Serializers in .NET which compares this serializer with DataContractJsonSerializer.
baretta's answer solved the k__BackingField bloat for me. Just a tiny addendum that you can decorate this class to auto serialize into either XML or JSON in a similar way:
[Serializable, XmlRoot, DataContract]
public class Cat
{
[XmlElement]
[DataMember]
public string Name { get; set; }
[XmlElement]
[DataMember]
public string Breed { get; set; }
}
... and then use a DataContractJsonSerializer or XmlSerializer to prepare it for your endpoint.
I'm assuming you are passing data via a web service. If you are using the WebService class with the ScriptMethod attribute uncommented-out, the web service methods can read JSON natively. They even use the same JavaScriptSerializer that was mentioned above. If you are using WCF I'm a little more fuzzy on the logic.
But make sure your JSON object are returning data for EVERY property in your class. In your error, there is mention of a Breed property that is not in your example.
Also, on the JavaScript side, do to the dynamic nature of JavaScript it is easy to add new properties to your objects. This can sometimes lead to circular references. You should remove any extra data that you might have added (just as you are sending data via the web method, then add it again once you are done).

Duplicate values when deserializing xml from external api using built in xml deserialization in C#

I'm using the built in XML deserialization (not because it was my choice, but legacy code) to deserialize xml to a strong typed object.
NOTE: I have no control over the xml, it is an external api
The problem is an xml node has been extended to include a child node of the same name and it's breaking the serialization.
For example, the xml as follows:
<people>
<person>
<id>1234</id>
<person>
<name>This is my name</name>
<person>
</person>
</people>
With the following objects
[XmlType("person")]
public class Person {
[XmlElement("id")]
public int Id { get; set; }
[XmlElement("person")]
public PersonTitle Title{ get; set; }
}
[XmlType("person")]
pulic class PersonTitle
{
[XmlElement("name")]
public string Name { get; set; }
}
This is throwing an error when calling (T)xmlserializer.Deserialize(stream) due to the duplicate names even though the xml is valid. Personally I would not have gone to the trouble to replicate the xml layout in objects just to automatically deserialize it when manually deserializing is easier to maintain (especially when it's never serialized by .net in the first place).
However, I'd like to know if there's a way I can get around this even if it means flattenting the child object out.
I know this doesn't work, but as example:
[XmlType("person")]
public class Person {
[XmlElement("id")]
public int Id { get; set; }
[XmlElement("person/name")]
public string Title{ get; set; }
}
Any help is appreciated.
The easiest method might be to run it through an XSLT transform before deserializing it- match the person/person/name elements and output just the person/name part. Then deserialize the result.
Here's a SO post on applying XSLT within C#: How to apply an XSLT Stylesheet in C#
And here is one on using XSLT to replace elements: http://cvalcarcel.wordpress.com/2008/09/06/replacing-arbitrary-xml-located-within-an-xml-document-using-xslt/
In a worst case scenario you could write the class however you like (don't compromise due to serialization) and then implement IXmlSerializable. Implement ReadXml, throw NotImplementedException for WriteXml if you like.

Categories