How to define behave during serialization an object to attribute in XML - c#

I have some problem with serialization an object to XML. At the beggining, this is class Order which have some properties of types like string, int...
public class Order
{
[XmlAttribute("ObjectType")]
public string TypeName
{
get; set;
}
[XmlAttribute("ID")]
public string ID
{
get; set;
}
[XmlAttribute("TID")]
public string TID
{
get; set;
}
[XmlAttribute("Command")]
public Command Command
{
get; set;
}
public Order()
{
}
}
As you can see, this class has also one property of type Command. Command class has one string property called Name:
public class Command
{
[XmlAttribute("Name")]
public string Name
{
get; set;
}
}
What's the problem? I need to get result like this:
<Order ObjectType="TestCase" ID="2" TID="W404" Command="SomeCommand" />
Where 'SomeCommand' is value of 'Name' property of this Command object.
With simple words: i need to define behave of how Command object should be serialized to XML attribute - return Name string. Very important thing is that also I have to be able to deserialize this XML to objects structure.
Hope my post is understandable and my problem is explained clearly. ;)
Best regards!

Assuming you have some way to reconstruct the command from the command name, you can introduce a derived property CommandName to serialize the name, and use xml serialization attributes to make XmlSerializer output the desired properties as attributes with the desired names:
public class Order
{
[XmlAttribute("ObjectType")]
public string TypeName
{
get;
set;
}
[XmlAttribute("ID")]
public string ID
{
get;
set;
}
[XmlAttribute("TID")]
public string TID
{
get;
set;
}
[XmlIgnore]
public Command Command
{
get;
set;
}
[XmlAttribute("Command")]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
[Browsable(false)]
public string CommandName
{
get
{
return Command == null ? null : Command.Name;
}
set
{
// Logic to convert CommandName to Command, e.g.:
Command = Command.FindByName(value); // or whatever.
}
}
public Order()
{
}
}
The CommandName property must be public in order for this to work.

Related

How to make JsonProperty() attribute have a dynamic propertyName?

Essentially I have a Root class to serialize/deserialize JSON data that looks like this:
public class Root
{
[JsonIgnore]
public string JoystickName { get; set; }
public Root(string joystickName)
{
JoystickName = joystickName;
}
[JsonProperty("g")]
public string G { get; set; }
[JsonProperty(PropertyName = JoystickName)] // This line produces error
public DxsJoyConfig Joystick { get; set; }
}
*EDIT:
How do I change the property name at runtime?
I'm also running into an object reference error required at the indicated line. How can I make an instance of JoystickName within the attribute?

Passing values from concretized instance of an base class to another base class instance

I am currently working on making viewmodels capable of parsing data extracted from database to the UI and vice versa, and to do so I do a lot of manual mapping between my two viewmodels.
Currently I try to pass some values that determines an attribute, but since each attributetype requires specifying a lot specific parameter, and 90% of the variables will be redundant in all cases since attributes only have one type..
Thus i have create a placeholder base class, which just contains an Id, that each atttribute have,
and each of the specific attribute type parameter will then use this placeholder as base class..
example:
public class BooleanViewSpecification : AttributeTypeSpecification
{
public string TrueOptionText { get; set; }
public string FalseOptionText { get; set; }
}
public class DateTimeTypeViewSpecification : AttributeTypeSpecification
{
public DateTime EarliestDataTime { get; set; }
public DateTime LatestDataTime { get; set; }
}
and my Attribute class is just an
public class AttributeView
{
public DataType Type { get; set; }
public AttributeTypeSpecification AttributeTypeViewSpecification { get; set; }
}
And the same Goes for my DB view model
public class BooleanSpecification : AttributeTypeSpecification
{
public string TrueOptionText { get; set; }
public string FalseOptionText { get; set; }
}
public class DateTimeTypeSpecification : AttributeTypeSpecification
{
public DateTime EarliestDataTime { get; set; }
public DateTime LatestDataTime { get; set; }
}
and my Attribute class is just an
public class Attribute
{
public DataType Type { get; set; }
public AttributeTypeSpecification AttributeTypeSpecification { get; set; }
}
Problem is then mapping from one class to another class
public static IEnumerable<AttributeView> MapToViewModel(this IEnumerable<Attribute> attributes)
{
return attributes.Select(z => new AttributeView()
{
Type = z.Type,
AttributeTypeViewSpecification = z.AttributeTypeSpecification
});
}
Which does not seem to work?
I use entity framework and migrate using Code-First what I receive is the Id of the location, and not the actual values?
I cant seem to understand why I cant be given the values - if it during the mapping does have the value?
So why cant they be mapped over?
I retrieve the value
Context.Include(Attribute).ThenInclude(AttributeTypeSpecification)
The only thing I receive is the actual Id rather than the specified entries?

How can I automap an object with a JSON property to an object without a JSON property?

What is a good way is to automap an object with some properties, one of which is a JSON string, to another object where that JSON string would be represented by properties instead of JSON.
See the source and destination classes below for an example:
CustomJson will look something like this for this example but could be different for other AlertTypes: { "AlertPrice": 500.0 }
//This is the database table representation (source)
public class Alert
{
public int Id { get; set; }
public int UserId { get; set; }
public string AlertType { get; set; }
public string CustomJson { get; set; }
}
//This is the business logic model (destination)
public class UserAlert
{
public int Id { get; set; }
public int UserId { get; set; }
public string AlertType { get; set; }
//This comes from the CustomJson string in the DB
//A different AlertType may need to map to a different object with different properties
public decimal AlertPrice { get; set; }
}
Will a ValueResolver allow me to do this or will it only be able to map part of the object? If not, perhaps I should just have a Custom property which contain the custom info instead of trying to meld it into the top-level object.
CreateMap<sourceobject, destobject>()
.AfterMap((src, dest) =>
{
dest.AlertPrice = JsonConvert.DeserializeObject<T>(json).AlertPrice;
});
CreateMap<sourceobject, destobject().AfterMap((src, dest) =>
{
dest.AlertPrice = decimal.Parse(src.AlertPrice, CultureInfo.InvariantCulture);
});
Please use above code you have use Explicity Mapping

Only return some fields in JSON

I have an API that returns some data of a class in JSON. Is there any way to return only some specific fields of a C# class in JSON?
For example:
class Person {
public int Id{ get; set; }
public string Name { get; set; }
public string Family { get; set; }
public string Gender { get; set; }
}
Person myPerson = new Person();
var Json = (new
{
Person = myPerson
});
return Request.CreateResponse(HttpStatusCode.OK, Json);
It returns ID, Name, Family, Gender. I need to return only the Name and Family. I thought I can create an object and add my specific fields in the class in that object and return object?
Use anonymous types?
return Request.CreateResponse(HttpStatusCode.OK, new {Name = person.Name; Family = person.Family});
You should consider applying the DRY principle.
The DRY principle is not "never write code twice", but rather that "every piece of knowledge must have a single, unambiguous, authoritative representation in the system".
What this means is that you have to build a model that has a meaningful name, contains properties that it actually has, and can be changed as needed later without having to figure out where else in the application it's used. I'm certain you could also find a name that would better represent this area of the application.
Should I create a different model with just the properties I need or
use the same model and have NULL values for the field I don't use? Or just create anonymous type and make this way harder in future?
I don't recommend using the same model for your case, from my understanding of it. It's going to make your life easier down the road if you build a model that has a meaningful name as I said before.
So what should we do? I have seen many people trying to use JsonIgnore in domain model but you should not get down that path. You should avoid using JsonIgnore in domain model. I will give an example for it.
For example:
class Person {
public int Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
public string Gender { get; set; }
}
So you have this model and you want other models to inherit from it but like in your case you don't want to return Id and Gender, only Name and Family. So you go like this.
class Person {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Family { get; set; }
public virtual string Gender { get; set; }
}
public class PersonNameModel : Person {
[JsonIgnore]
public override int Id { get; set; }
[JsonIgnore]
public override string Gender{ get; set; }
}
If a class has many properties and you only want to serialize a small
subset of them then adding JsonIgnore to all the others will be
tedious and error prone. The way to tackle this scenario is to add the
DataContractAttribute to the class and DataMemberAttributes to the
properties to serialize. This is opt-in serialization, only the
properties you mark up with be serialized, compared to opt-out
serialization using JsonIgnoreAttribute.
But, you can do it with the help of JsonIgnore but this way does not support XML format. So, in case your application has to support XML format more (or only support XML), instead of using Json.Net, you should use [DataContract] which supports both JSON and XML.
Datacontract is a great solution. It gives me a clean REST API. At the same time when I save the data in a no-sql, the ignored properties are persisted despite the objects being stored as json.
[DataContract]
public class Person {
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Family { get; set; }
public virtual string Gender { get; set; }
}
public class PersonNameModel : Person {
// included in JSON
[DataMember]
public override string Name { get; set; }
[DataMember]
public override string Family { get; set; }
// other inherited properties will be ignored
}
I will also mention another way of doing it as there are more (custom contact resolver, Web API convention ("ShouldSerialize")...)
Another way you can do it is to decorate your auto property with JsonProperty attribute in order to skip the serialization of that field if it is null.
Example:
class Person {
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int? Id { get; set; }
public string Name { get; set; }
public string Family { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Gender { get; set; }
}
Happy coding!

Dynamic property to a C# object

I am thinking designing a field in db that stores the Serialized Object. When I call that property in entity, that returns String property which is obvious. I am looking for a way to attach a property dynamically and assign the deserialized object to the Class instance. Can any one suggest the best possible way?
DB Structure
Users Table
UserId ..... ..... ..... UserNotes (nvarchar)
Class Structure
[Serializable]
[XmlRoot("Notes")]
public class GenericNotes {
public DateTime Date {
get;
set;
}
public String CommentBy {
get;
set;
}
public string Type {
get;
set;
}
public string Comment {
get;
set;
}
}
public class Users {
public UserId int {
get;
set;
}
public string UserNotes {
get;
set;
}
// I dont have the following definition in the class because its coming from entity framework.
//But I want the following property attached to the class on runtime.
//I will take care of of deserializing using extension methods or some sort methods.
public string List < GenericNotes > NotesCollection {
get;
set;
}
}
Instead of property you can have extension method to do this
public static class UserExtension
{
public static List<GenericNotes> GetNotes(this Users users)
{
//return your deserialized GenericNotes from string
}
}
Then you can use this anywhere like
List<GenericNotes> notes = users.GetNotes();

Categories

Resources