Set element name same as RootElement attribute - c#

[XmlRootAttribute("ls")]
public class Request<T>
{
[XmlAttribute("ver")]
public string Version { get; set; }
[XmlElement("hdr")]
public Header Header { get; set; }
[XmlElement(Type = typeof(class2), ElementName = "ChildClass")]
public T Data { get; set; }
}
[XmlRoot("ChildClass")]
public class class2
{
[XmlElement("login")]
public string Property1{ get; set; }
}
[XmlRoot("ChildClass3")]
public class class3
{
[XmlElement("User")]
public string Property1{ get; set; }
}
When Request<class2> is serialized , Element name is "Data". I want element Name to be "ChildClass". when Request<class3> is serialized , Element name should be "ChildClass3".
How can i do that

As far as I know the element name must be known at compile time and so you can't try and use the Data objects XmlRoot or class name or similar as these aren't known at compile time. You'll need to define every possible type that you could expect Data to be set to. As follows:
[XmlRoot("ls")]
public class Request
{
[XmlAttribute("ver")]
public string Version { get; set; }
[XmlElement("ChildClass2",typeof(class2))]
[XmlElement("ChildClass3",typeof(class3))]
public object Data { get; set; }
}
public class class2
{
[XmlElement("login")]
public string Property1 { get; set; }
}
public class class3
{
[XmlElement("User")]
public string Property1 { get; set; }
}
The following two objects:
var exampleObject = new Request
{
Version = "versionExample",
Data = new class2 { Property1 = "property1Example" }
};
var exampleObject2 = new Request
{
Version = "versionExample",
Data = new class3 { Property1 = "property1Example" }
};
Then serialized to:
<ls ver="versionExample">
<ChildClass2>
<login>property1Example</login>
</ChildClass2>
</ls>
<ls ver="versionExample">
<ChildClass3>
<User>property1Example</User>
</ChildClass3>
</ls>

Related

C# add properties to an existing class at runtime

I hava a class like;
public class MainClass
{
public class Class1
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public int Property3 { get; set; }
}
public class Class2
{
public Class2()
{
List1 = new List<Class1>();
}
public string Property4 { get; set; }
public List<Class1> List1 { get; set; }
}
public List<Class2> List2 { get; set; }
public string Property5 { get; set; }
public bool Property6 { get; set; }
}
I want to add parameters in MainClass at runtime
public class MainClass
{
...
public string Parameter1 { get; set; }
public string Parameter2 { get; set; }
...
}
or create new class with inheritance existing class.
public class NewClass : MainClass
{
public string Parameter1 { get; set; }
public string Parameter2 { get; set; }
}
or something else. These's my ideas. Unfortunately, using a dictionary will not solve my problem because I am using xtrareport and I must show a fieldlist.
You could bind your ExtraReport to a DataSet instead of binding to collection of a strong typed objects (which can't be changed at execution-time). So if you add new fields to the data-source it’s a matter of changing the report for showing that new fields. If you create a Stored Procedure to retrieve data, you can even change the query without having to compile the Application. You can iterate through the DataTable object of the DataSet to read all the fields & place them dynamically using XRBinding DevExpress Objects.
See: https://www.devexpress.com/Support/Center/Question/Details/T408680/binding-datatable-object-to-xtrareport-xrtable

NewtonSoft incorrect deserialization

This is what I'm trying to deserialize.
I let Visual Studio generate these classes for deserialization.
But whenever I deserialize this data, I end up with the _56787 set being null. Here's the re-serialized data.
using (var client = new WebClient())
{
string temp = client.DownloadString($"https://api.frankerfacez.com/v1/room/leonardvdj");
Rootobject FFZEmotes = JsonConvert.DeserializeObject<Rootobject>(temp);
Console.WriteLine(JsonConvert.SerializeObject(FFZEmotes));
}
This is the code I use to retrieve the JSON. I've checked "temp"s value, and it download's correctly.
Anyone have any idea why this is happening?
You need to make sets into a dictionary instead of a type and rename _56787 to something more sensible:
public class Rootobject
{
public Room room { get; set; }
public Dictionary<string, Set> sets { get; set; }
}
public class Set
{
public int _type { get; set; }
public object css { get; set; }
public object description { get; set; }
public Emoticon[] emoticons { get; set; }
public object icon { get; set; }
public int id { get; set; }
public string title { get; set; }
}

Why an XML string cannot be deserialized due to prefixes in root elements?

I have the XML below:
<y:input xmlns:y='http://www.blahblah.com/engine/42'>
<y:datas>
<y:instance yclass='ReportPeriod' yid="report">
<language yid='en'/>
<threshold>0.6</threshold>
<typePeriod>predefinedPeriod</typePeriod>
<interval>month</interval>
<valuePeriod>April</valuePeriod>
<fund yclass="Fund">
<name>K</name>
<indexName>CAC40</indexName>
</fund>
</y:instance>
</y:datas>
</y:input>
That I am trying to deserialize to
[XmlRoot(ElementName="fund")]
public class Fund
{
[XmlElement(ElementName="name")]
public string Name { get; set; }
[XmlElement(ElementName="indexName")]
public string IndexName { get; set; }
[XmlAttribute(AttributeName="yclass")]
public string Yclass { get; set; }
}
[XmlRoot(ElementName="instance", Namespace="http://www.blahblah.com/engine/42")]
public class Instance
{
[XmlElement(ElementName="language")]
public Language Language { get; set; }
[XmlElement(ElementName="threshold")]
public string Threshold { get; set; }
[XmlElement(ElementName="typePeriod")]
public string TypePeriod { get; set; }
[XmlElement(ElementName="interval")]
public string Interval { get; set; }
[XmlElement(ElementName="valuePeriod")]
public string ValuePeriod { get; set; }
[XmlElement(ElementName="fund")]
public Fund Fund { get; set; }
[XmlAttribute(AttributeName="yclass")]
public string Yclass { get; set; }
[XmlAttribute(AttributeName="yid")]
public string Yid { get; set; }
}
[XmlRoot(ElementName="datas", Namespace="http://www.blahblah.com/engine/42")]
public class Datas
{
[XmlElement(ElementName="instance", Namespace="http://www.blahblah.com/engine/42")]
public Instance Instance { get; set; }
}
[XmlRoot(ElementName="input", Namespace="http://www.blahblah.com/engine/42")]
public class Input
{
[XmlElement(ElementName="datas", Namespace="http://www.blahblah.com/engine/42")]
public Datas Datas { get; set; }
[XmlAttribute(AttributeName="y", Namespace="http://www.blahblah.com/engine/42", Form = XmlSchemaForm.Qualified)]
public string Y { get; set; }
}
However, when deserializing the XML above:
public static class Program
{
public static void Main(params string[] args)
{
var serializer = new XmlSerializer(typeof(Input));
using (var stringReader = new StringReader(File.ReadAllText("file.xml")))
{
using(var xmlReader = XmlReader.Create(stringReader))
{
var instance = (Input)serializer.Deserialize(stringReader);
}
}
}
}
I get an error due to the y prefix...
There is an error in XML document (1, 1). ---> System.Xml.XmlException: Data at the root level is invalid. Line 1, position 1.
Reading some posts like that one: https://stackoverflow.com/a/36163079/4636721 it seems that there is maybe a bug with the XmlSerializer.
The cause of the exception is that you are passing stringReader rather than xmlReader to serializer.Deserialize(). You should be passing the XML reader instead:
Input instance = null;
var serializer = new XmlSerializer(typeof(Input));
using (var stringReader = new StreamReader("file.xml"))
{
using(var xmlReader = XmlReader.Create(stringReader))
{
instance = (Input)serializer.Deserialize(xmlReader);
}
}
(Apparently XmlReader.Create(stringReader) advances the text reader a bit, so if you later attempt to read from the stringReader directly, it has been moved past the root element.)
You also have some errors in your data model. It should look like:
[XmlRoot(ElementName="fund")]
public class Fund
{
[XmlElement(ElementName="name")]
public string Name { get; set; }
[XmlElement(ElementName="indexName")]
public string IndexName { get; set; }
[XmlAttribute(AttributeName="yclass")]
public string Yclass { get; set; }
}
[XmlRoot(ElementName="instance")]
[XmlType(Namespace = "")] // Add this
public class Instance
{
[XmlElement(ElementName="language")]
public Language Language { get; set; }
[XmlElement(ElementName="threshold")]
public string Threshold { get; set; }
[XmlElement(ElementName="typePeriod")]
public string TypePeriod { get; set; }
[XmlElement(ElementName="interval")]
public string Interval { get; set; }
[XmlElement(ElementName="valuePeriod")]
public string ValuePeriod { get; set; }
[XmlElement(ElementName="fund")]
public Fund Fund { get; set; }
[XmlAttribute(AttributeName="yclass")]
public string Yclass { get; set; }
[XmlAttribute(AttributeName="yid")]
public string Yid { get; set; }
}
[XmlRoot(ElementName="datas", Namespace="http://www.blahblah.com/engine/42")]
public class Datas
{
[XmlElement(ElementName="instance", Namespace="http://www.blahblah.com/engine/42")]
public Instance Instance { get; set; }
}
[XmlRoot(ElementName="input", Namespace="http://www.blahblah.com/engine/42")]
public class Input
{
[XmlElement(ElementName="datas", Namespace="http://www.blahblah.com/engine/42")]
public Datas Datas { get; set; }
//Remove This
//[XmlAttribute(AttributeName="y", Namespace="http://www.blahblah.com/engine/42", Form = XmlSchemaForm.Qualified)]
//public string Y { get; set; }
}
// Add this
[XmlRoot(ElementName="language")]
public class Language
{
[XmlAttribute(AttributeName="yid")]
public string Yid { get; set; }
}
Notes:
xmlns:y='http://www.blahblah.com/engine/42' is an XML namespace declaration and thus should not be mapped to a member in the data model.
The child elements of <y:instance ...> are not in any namespace. Unless the namespace of the child elements is specified by attributes somehow, XmlSerializer will assume that they should be in the same namespace as the containing element, here http://www.blahblah.com/engine/42".
Thus it is necessary to add [XmlType(Namespace = "")] to Instance to indicate the correct namespace for all child elements created from Instance. (Another option would be to add [XmlElement(Form = XmlSchemaForm.Unqualified)] to each member, but I think it is easier to set a single attribute on the type.)
A definition for Language is not included in your question, so I included one.
It will be more efficient to deserialize directly from your file using a StreamReader than to read first into a string, then deserialize from the string using a StringReader.
Working sample fiddle here.

Store Object with Dynamic property in Cosmos DB

I have a message processor where I would like to take a lump of json with a wrapper of known schema, but with a property that is a dynamic object like the following:
public class NotificationDetails
{
[JsonProperty(PropertyName = "id")]
public string NotificationID { get; set; }
public DateTime? DateCreated { get; set; }
public DateTime? DateSent { get; set; }
public string TemplateUrl { get; set; }
public dynamic Model { get; set; }
}
as you can see, the last property is of dynamic. the notifications will all have different Model schemas, so I would like it to just be stored as a nested object.
That said, when I attempt to Create the object via
client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(DatabaseId, collectionId), item)
I get the following error message:
The best overloaded method match for 'MyClass.CreateNotification(NotificationDetails))' has some invalid arguments
I thought I could throw anything into these docs. what am I doing wrong? should I use something other than dynamic for this Model property?
UPDATE I figured out it was something about how I was calling the Wait() method on the task returned from the DocumentClient. Once I reverted to the async await strategy it started working correctly.
According to your description. I have tested your code and it worked as below. You can refer to what I did:
public static void CreateCosmosDocument()
{
DocumentClient client = new DocumentClient(new Uri("https://xxxxx/"), "C2y6yDjf5/R+ob0N8A7Cgv30VRDJxxxxM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==", new ConnectionPolicy { EnableEndpointDiscovery = false });
TestEntity testEntity = new TestEntity { x = 11, y = 11, name = "wakaka", dynam = "hello dynam" };
var createdItem = client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri("ToDoList", "Items"), new NotificationDetails { DateCreated=DateTime.Now, DateSent=DateTime.Now, TemplateUrl="www.baidu.com", Model= testEntity });
}
Class of NotificationDetails:
public class NotificationDetails
{
[JsonProperty(PropertyName = "id")]
public string NotificationID { get; set; }
public DateTime? DateCreated { get; set; }
public DateTime? DateSent { get; set; }
public string TemplateUrl { get; set; }
public dynamic Model { get; set; }
}
Class of TestEntity which act as a nested object:
class TestEntity
{
public ObjectId _id { get; set; }
public string name { get; set; }
public double x { get; set; }
public double y { get; set; }
public double z { get; set; }
public dynamic dynam { get; set; }
}
Screenshot of result:
If the error still occured, you'd better share your more detailed code with us for further research.

Why can't I send my custom class through my webservice?

I have these classes:
public abstract class CustomField
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public FieldType Type { get; set; }
public enum FieldType
{
String = 0,
Integer = 1,
Boolean = 2,
List = 3
}
}
public class StringCustomField:CustomField
{
public String Value { get; set; }
public Int32 MinLenght { get; set; }
public Int32 MaxLenght { get; set; }
public StringCustomField()
{
this.Type = FieldType.String;
}
}
public class CustomGroup
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public List<CustomField> FieldList = new List<CustomField>();
}
When I try to transfer CustomGroup through my webservice I get this error:
The remote server returned an error: NotFound
Serialization is failing when C# tries to transfer my StringField through my CustomField.
What am I doing wrong?
Marc Gravel tell me to do that and i understand the solution but some thing is wrong, no effects, cath the same error!! , help!!
[XmlInclude(typeof(StringCustomField))]
[XmlInclude(typeof(IntegerCustomField))]
[XmlInclude(typeof(BooleanCustomField))]
[XmlInclude(typeof(ListCustomField))]
public abstract class CustomField
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public FieldType Type { get; set; }
public enum FieldType
{
String = 0,
Integer = 1,
Boolean = 2,
List = 3
}
}
If you are sending subclasses as xml, you will need [XmlInclude]:
[XmlInclude(typeof(StringCustomField))]
public abstract class CustomField
{...}
You can add multiple [XmlInclude(...)] markers for any other subclasses in the model.
List<CustomField> will serialize and deserialize to a CustomField[] if you're using a web service, won't it?
use
public class CustomGroup
{
public String Id { get; set; }
public String Name { get; set; }
public String Description { get; set; }
public List<CustomField> FieldList = new List< StringCustomField >();
}
instead
If i understand you correctly, you should
1. connect your web service to your app
2. use the namespace of the WS, so all the classes will be used from the Proxy
i don't think that the local class will be understood by the remote web serivce correctly, even if you're using the same assembly on both parties

Categories

Resources