Serializing POCO class derived from baseclass with DataContract? - json.net

I noticed that when serializing/deserializing a POCO class with JSON.NET that derives from a base class that uses explicit DataContract attributes then any POCO properties on the derived class are ignored.
For example, in this example, "Address" is not serialized/deserialized:
[DataContract]
public class MyBaseClass
{
[DataMember(Name = "SomeName")]
public string Name { get; set; }
}
public class MyDerivedClass : MyBaseClass
{
public string Address { get; set; }
}
Is that intentional?
FWIW, it does seem that DataContractSerializer (at least the XML one) does the "right thing" here and serializes/deserializes "Address".
Thanks!
Henrik

In JSON.NET, at least as of v4.5.6, it detects the DataContract of the base class and assumes opt-in serialization. Since Address is not decorated with the DataMember attribute it does not get serialized.
This is by design according to James Newton-King with no planned change.

Related

Make an XML element mandatory

Here I am currently working on a program that will serialize an XML file asp.net object. My problem is that I can not find the attribute that makes it mandatory to have a tag in the XML file.
You will find below the definition of my object.
[System.SerializableAttribute()]
public class EchangeIdentification
{
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("agrement")]
public string Agrement{ get; set; }
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("cvi")]
public string NumeroCvi { get; set; }
/// <remarks/>
[Required]
[XmlElement("siret")]
public string Siret { get; set; }
}
As far as I know, there is no way to declaratively force elements and attributes to be required using the XmlSerializer. C# object properties that can be null are always optional.
A few observations
[Serializable] is not used by the XML Serializer.
There is no way to make it required using the XML Serializer, but if you don't have to use XmlSerializer? DataContractSerializer provides the following option:
[DataMember(IsRequired = true)]
You don't need the "Attribute" name in the code, your code could look like this
[Serializable]
public class EchangeIdentification
{
[XmlElement("agrement")]
public string Agrement{ get; set; }
[XmlElement("cvi")]
public string NumeroCvi { get; set; }
[XmlElement("siret")]
public string Siret { get; set; }
}
Define "serialize an XML file asp.net object" and "makes it mandatory to have a tag in the XML". It all depends on how you're using this class.
Are you using it as a deserialization container, into which you will deserialize XML you receive? Then create an XSD schema, and validate the incoming XML before (or rather during) serialization. See Validating an XML against referenced XSD in C#.
On the other hand, if the user of this code is assigning properties of an instance of this class at runtime, and you serialize it through XmlSerializer, you could validate the output after serializing. See the linked question above, and Can I fail to deserialize with XmlSerializer in C# if an element is not found?.
Alternatively, you could implement serialization callbacks and create a validation method that throws an exception if [Required] properties have the default value for their type.
I'd go with the XSD route either way.

Self referencing loops with EF5 and Newtonsoft.Json

I am using MVC4 with EF5 database first and Newtonsoft.Json for serializing objects to JSON for example in Web API controllers.
To avoid the problem of self referencing loops i set the attribute [JsonIgnore] to the specific collections in my generated classes.
My problem is now that each time i update my model i have to readd the attributes to the classes.
How can i avoid that? I think i have to edit the DBModel.tt script? What have i to do?
You should be able to use a metadata class with the MetadataType attribute. If your generated class is:
public partial class MyClass{
public string SomeProperty {get; set; }
public string SomePropertyToIgnore {get; set; }
}
Then you need to create a metadata class like so (in the same namespace):
public class MyClass_Metadata{
[JsonIgnore]
public string SomePropertyToIgnore {get; set; }
}
The create a partial of your generated class (in the same namespace) with the MetadatType attribute applied:
[MetadataType(typeof(MyClass_Metadata))]
public partial class MyClass{
}
Ref: http://msdn.microsoft.com/en-us/library/ee707339(v=vs.91).aspx

ASP.NET MVC3 Metadata problem on class named as .NET keyword

I've a problem when adding metadata to a class named as a reserved keyword. During the generation of the data model (the DBML file), an # has been added to the class name to have it working.
When I apply metadata to the class, it is not working (metadata info is not taken in consideration - the DisplayName and other validation stuff). For all other classes of my project (that do not have a class name as a reserved keyword, it is working). It is currently not possible to rename that class.
Generated class definition:
[global::System.Data.Linq.Mapping.TableAttribute(Name="dbo.operators")]
public partial class #operator : INotifyPropertyChanging, INotifyPropertyChanged
{...}
MetaData class definition:
[MetadataType(typeof(OperatorMetaData))]
public partial class #operator
{
}
public class OperatorMetaData
{
[DisplayName("Operator Type")]
[Required(ErrorMessage = "Operator type is required.")]
public int operator_type_id { get; set; }
...
}
Anyone any idea how to work around this? Or what did I do wrong ?

ASP.NET MVC, Linq to SQL Data Annotation Validation

I'm trying implement Data Annotation to my Linq to SQL objects. The .dbml file is generated and I'm not sure how to add data annotation to the objects without touching the generated source code.
I tried to add data annotations to the a separate partial class of the object, but its not recognizing it, no Intelli sense either.
As I said in my original answer to this question, you should use an interface. The answer posted after mine (which was marked as Accepted) said to use a class. This is not as good. An interface is a better option for the following reasons:
If there is a mismatch between the name in your LINQ class and the name in your interface, the compiler will flag it for you
An interface can not be instantiated, so this protects class users from accidentally instatntiating the metadata type
If you use Resharper (or similar), the interface can be automatically extracted from the LINQ class
An interface is less verbose than an empty class
If you program against interfaces rather than classes (which is a good practice), then you've already got an interface you can use as your metadata type
For a class called, say "User", create an interface for it (say 'IUser'), and then update the definition of your partial User class as follows:
[MetadataType(typeof(IUser))]
public class User : IUser
Then, in your IUser interface, add appropriate Data Annotation attributes to the properties:
[Required]
[StringLength(50, ErrorMessage = "Username cannot exceed 50 characters")]
string Username { get; set; }
For a class called, say "User", create an interface for it (say 'IUser'), and then update the definition of your partial User class as follows:
[MetadataType(typeof(IUser))]
public class User : IUser
Then, in your IUser interface, add appropriate Data Annotation attributes to the properties:
[Required]
[StringLength(50, ErrorMessage = "Username cannot exceed 50 characters")]
string Username { get; set; }
Linq to SQL generates object classes as partial. An easy way to implement data annotations is to create your own partial class of the object, place the [MetadataType(typeof(YourDataAnnotationClass))] on the partial class you created.
Example:
// Linq to SQL Class
public partial class Article
{
public string Title { get; set; }
...... etc
}
Create your own MetaData class with Metadata for each field you want to validate
public class MyMetaDataClass
{
[Required]
[Range(5,20)]
public string Title { get; set; }
}
Create a Partial Class for the Object class you want to add metadata to, in this case Articles class:
[MetadataType(typeof(MyMetaDataClass))]
public partial class Article { }
Note: you don't need to specify anything in the class, just the metadata type.
Thanks,but the problem is MS define the prototype of MetadataTypeAttrubute as
[AttributeUsageAttribute(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class MetadataTypeAttribute : Attribute
So, you had to use class but not interface
From China
Forest Lee: 李晓强
xiaoqianglinsen#163.com (MSN)
lixiaoqiang#webservice.com.cn

Binding IList<IMyInterfaceType> doesn't display members of Interfaces that IMyInterface inherits

I'm binding IList to a GridView. IMyInterface looks like
public interface IMyInterface: IHasTotalHours, IHasLines
{
DateTime GoalStartDate { get; set; }
DateTime GoalEndDate { get; set; }
}
I bind an instance to a Grid like this:
IList<IMyInterface> instance= GetMyData();
myGrid.DataSource = instance;
myGrid.DataBind();
When bind this to the grid, the only members that show up in the grid are the direct members of IMyInterface: GoalStartDate and GoalEndDate.
Why is that? How do I get the grid to display the members of the other interfaces it inherits?
Update
The inherited interfaces define simple data properties like
public interface IHasTotalHours
{
string Description { get; set; }
int Hours{ get; set; }
}
public interface IHasLines
{
double TotalLines { get; set; }
double LinesPerHour { get; set; }
}
There is a class that implements IMyInterface:
public class MyClass : IMyInterface
{
public string Description { get; set; }
public int Hours { get; set; }
public double TotalLines { get; set; }
public double LinesPerHour { get; set; }
public DateTime GoalStartDate { get; set; }
public DateTime GoalEndDate { get; set; }
}
These are cast as IMyInterface, and returned in the list that I'm binding to the GridView.
Data bound controls do not use reflection but a TypeDescriptor to get the properties from a data source. In the TypeDescriptor.GetProperties method, you can read the following:
The properties for a component can
differ from the properties of a class,
because the site can add or remove
properties if the component is sited.
Apparently the default implementation will only return direct properties from an Interface and not the inherited ones.
Luckily this mechanism is extensible, and you can write a TypeConverter class with custom property information implementation. Please refer to the remarks in the TypeConverter documentation for implementing property logic.
The GetProperties implementation of your custom TypeConverter class can call TypeDescriptor.GetProperties(Type) on your interface and all it's inherited interfaces. But maybe you could even write a generic TypeConverter that would find all inherited properties by using reflection.
Then you attach this custom TypeConverter to your interface with the TypeConverterAttribute attribute.
And then, like magic, the data source will find all properties. ;-)
It's because an interface is a contract, and that's the only way to interact with an object is through that specific contract. The other interfaces cannot be assumed and can't be utilized until a cast is made.
So when you bind a List of T to something, the datagrid doesn't know about those other interfaces. And the datagrid isn't going to use reflection to figure out what other classes or interfaces might be inherited. The only object properties that are going to be available to the datagrid are the properties exposed by the T interface.
You need to bind List if you want the datagrid to have access to all the properties.

Resources