I have an ASP.NET Core application which can have components of different types. These types are not know until runtime. I have a set of settings which are in a taxonomy of types, and a top-level settings object that stores a collection of the configured components. E.g.,
public class ServiceSettings
{
List<ComponentSettingsBase> Components { get; set; }
}
public abstract class ComponentSettingsBase
{
}
public class ASettings : ComponentSettingsBase { get; set; }
public class BSettings : ComponentSettingsBase { get; set; }
Using a Json file, I can create the base ServiceSettings object and map it correctly for simple types like strings. When it comes to the collection it just ignores it. I've tried adding type information like Json.NET (Newtonsoft) does for type name handling, but haven't found anywhere to configure how it should be deserialized. I thought that's what they used to use, and there are easy configuration settings for the Json serializer used for Web API communication, but this does not seem to effect the settings/configuration serialization.
Is there a way that I can do this using the built-in settings provider? Or will I need to do something like use the settings provider to point to another file, then use a more fully-fledged Json deserializer to deserialize the settings?
I think the problem here is that you want to map a JSON array to a C# List<T>.
What I would do is to change my code to something like this:
public class ServiceSettings
{
ComponentSettingsBase[] Components { get; set; }
}
I might be wrong, however...
Next thing I would try is to go the other direction and
build an example object model in memory
serialize it to a JSON
see how that JSON looks like to learn the format your environment likes
reproduce what you need in the format you have learned in the previous step
Related
Both Typescript and C# supports type safe access to the members of an object checked at “compile” type, and json is used to transport “data transfer objects” between web application back ends and their front end.
I would expect here to be tooling that could generate typescript “wrapper classes” from the C# classes that defined the JSON messages – yet I have never heard about such tooling being used.
It may be that not being an active TypeScript developer I have missed something in the TypeScript toolset for doing this, or that one of the “standard” JSON toolkits for .net already does it. Or I could just be asking a very daft question…..
TypeLITE will convert C# classes into TypeScript interfaces:
public class Address {
public string Street { get; set; }
}
public class Person {
public string Name { get; set; }
public List<address> Addresses { get; set; }
}
Becomes:
interface Address {
Street: string;
}
interface Person {
Name: string;
Addresses: Address[];
}
This would keep your TypeScript honest when consuming a C# API.
Reinforced.Typing looks like it is an option and it seems to generate TypeScript code to call the webservice as well as the interfaces/objects to describe the returned data.
Simply, this thing converts your .NET assemblies to TypeScript code.
It integrates to VisualStudio build process.
I think it is used less then TypeLITE, both are open source so can be expanded to match the needs of a given project.
Look at Reinforced.Typings and particularly this sample. There it is shown how to convert your MVC application controllers to AngularJS services returning ng.IPromise<> of your models and ensure type safety on build-time.
This question already has answers here:
Is DataContract attributes required for WCF
(4 answers)
Closed 9 years ago.
I was wondering if there is any way to define a WCF Contract class without using the [DataContract] and [DataMember] annotation. The reason is that domain model we currently have is fairly clean so we would like to keep it this way. Whats the best practice here? Create a Transfer object and copy the domain model object into a transfer object (that has the required annotations and is the Contract transfered between Client and Server)? Or somehow not annotate the object model and specify the contract in a different way.
If you do not add any serialization attributes to your class, and use it as part of a WCF service contract method, WCF will use the default serialization rules to produce a data contract anyway. This means that the class will implicitly become a [DataContract] every public property that has both a get and set accessor will implicitly become a [DataMember].
The only time you need to apply the attributes is if you want to override the default behavior, e.g. hiding some attributes, applying namespaces, etc. It's generally considered good practice to do so anyway, because relying on the default behavior might get you in trouble later. (It also makes it explicit that your class is meant for use by WCF). But it's not strictly required, as long as the default behavior meets your needs.
In response to your follow-up:
As far as I know there's no completely external way to change the serialization behavior of the DataContractSerializer for a given class; every option requires at least some level of attribution on the class being serialized. As #Yair Nevet describes below, my preferred method for turning existing domain objects into data contracts is the MetadataType attribute.
Alternatively, you can bypass the whole issue by doing what you suggested in your question: don't serialize your domain objects, but create custom DTO objects and serialize them. I tend to do this whenever I'm using the Entity Framework, for example, because serializing those can be tricky. This is also a good approach to take if your domain objects have lots of behaviors built into them -- you get a clear separation of "data being passed around" vs. "objects participating in my business logic."
You often end up with lots of redundant code, but it does achieve your goal of zero changes to your existing objects.
You can use the MetadataType attribute and a metadata model class in order to separate the annotations from your model.
For example:
[MetadataType(typeof(MyModelMetadata))]
public class MyModel : MyModelBase {
... /* the current model code */
}
[DataContract]
public class MyModelMetadata {
[DataMember]
public string Name { get; set; }
}
WCF is capable of serializing your objects without the attributes. The attributes are there to allow for customization. For example, the two classes will serialize identically by the DataContractSerializer:
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
[DataContract]
public class Customer
{
[DataMember] public string FirstName { get; set; }
[DataMember] public string LastName { get; set; }
}
It is worth mentioning that you really should mark your class with the attributes. They aren't as "messy" as you think. It will actually save you from headache in the future. For example:
[DataContract(Name = "Customer")]
public class Customer
{
[DataMember(Name = "FirstName")]
public string FirstName { get; set; }
[DataMember(Name = "LastName")]
public string LastName { get; set; }
}
In the previous code sample, I explicitly set the names of the class and members. This will allow me to refactor the names without breaking consumers code. So, if someone decides that my class should be named CustomerDetail instead of Customer, I can still leave the name as Customer so that consumers of my service continue to work.
You could always use DTOs. Make a separate class that has everything that is needed to serialize your objects. Then project your domain model on to the DTO. You could use something like AutoMapper to make this process a little easier.
Regarding Performance
Unless you have hundreds, probably thousands, or objects or a very large number of properties per class, the act of converting to and from DTOs probably isn't that much performance overhead.
If you are using something like EF, and you are not serializing every property, you might even be able to reduce some overhead by projecting your EF query directly on to your DTOs.
This is kind of a dramatic case, but I had (poorly designed) database models with 50+ properties per type. By changing to DTOs that only have the 10-15 properties I cared about, I was able to almost double the performance of a WCF service.
I am generating classes from XSD and need to populate the classes to serialize to xml.
I have different classes, containing all the info that goes into the classes generated.
The problem is that the generated classes come in versions, and properties in those classes are other classes in the same version.
class LocalData
{
public MyClass property { get; set; }
}
class XmlVersion1
{
public MyClassV1 property { get; set; }
}
class XmlVersion2
{
public MyClassV2 property { get; set; }
public MyClassXV2 newProperty { get; set; }
}
The data in MyClassV1 and V2 are basically the same, so the same code can be used.
I wanted to make a factory that just took the LocalData class and any of the versioned classes and populated the data in the versioned class, but I run into a problem when I want to do property = new MyClassVx, because the factory does not know which version it's supposed to create.
I could do
if (parameter is MyClassV1)
paramter.MyClassV1 = new MyClassV1
and so on, but that is a LOT of code.
This is for generating xml messages that are specified by an external company, and they come in different versions, and we have to be able to serialize and deserialize the content into our internal system.
We have not found a solution to this specific issue and chose to use AutoMapper which seems to solve our problem in a different way.
We made a tool that takes the generated classes and creates the mapping classes needed for AutoMapper through assembly. If you have large generated classes you could do this as well. We can now create thousands of lines of code needed to map classes. It solves an issue we had when mapping types of 'object' to specific classes. I don't know if it's helpful but there it is.
Idea is very simple. Factory will not care about version. But newer clients will always support old versions' features. If version 0.5 has a method to receive orders list (for example this is a shopping app) version 0.6 also should have same method. We have same structure and we are doing this way.
I would like to use ServiceStack on the server side, and I would like to use protobuf-net as the serialization system used by ServiceStack. However, some of the clients will not be using the ServiceStack client libraries. They will be using protobuf-net directly.
In reading the widely linked ServiceStack protocol buffers howto (http://stevenhollidge.blogspot.in/2012/04/servicestack-rest-with-protobuf.html), it indicates using [DataContract] and [DataMember(Order=i)] attributes on the classes and properties respectively. However, when I read the protobuf-net documentation it indicates attributes are [ProtoContract] and [ProtoMember(i)] instead.
If I want my DTOs to work with both native protbuf-net and ServiceStack's protobuf-net wrapper do I need to add both attributes to every class and property, or will one or the other be sufficient?
ProtoBuf requires a mapping from Properties to numerical indexes, both of the options you've specified are equivalent ways to do this:
[DataContract]
public class Dto
{
[DataMember(Order=i)]
public string PropertyName { get; set; }
}
[ProtoContract]
public class Dto
{
[ProtoMember(i)]
public string PropertyName { get; set; }
}
This question already has answers here:
Can I optionally turn off the JsonIgnore attribute at runtime?
(3 answers)
Closed 4 years ago.
I am currently using the same C# DTOs to pull data out of CouchDB, via LoveSeat which I am going to return JSON via an ASP MVC controller.
I am using the NewtonSoft library to seralise my DTOs before sending them down through the controller.
However, as CouchDB also uses NewtonSoft it is also respecting the property level NewtonSoft attributes such as
[JsonIgnore]
[JsonProperty("foo")]
Is there anyway to tell the newtonsoft library to ignore these attributes explicitly? LoveSeat allows me to provide my own implementation of IObjectSerializer, which gives me full control over netwonsofts JsonSerializerSettings. So, can I ignore the attributes by using those settings ?
I ask as the only alternative I can see at this point, is to dupe my DTOs. While not that's not terrible, it isn't great either.
The only other way I can see is to bring in my own version of the Newtonsoft.Json source into my project, with a different assembly name etc etc. But this way madness definitely lies and I will just dupe the DTOs before I go down this road.
I'm not sure if this is what you're after, but from what I understand you're looking for the [JsonIgnore] attribute. Stops properties from being serialized with the rest of the object into to JSON.
[JsonIgnore]
public string Whatever{ get; set; }
One suggestion that you may not like. For best practices, I recommend having two almost identical objects. One specifically for your Data Access Layer (Domain Object) which maps to your DB. And a separate DTO that your apps care about. This way the Domain Object will mostly contain more properties than the DTO and you can separate the concerns.
According to Json.NET documentation
You can add method to your class: public bool ShouldSerialize_________(){...} and fill in the blank with the name of the property you don't want to serialize. If the method returns false, the property will be ignored.
The example from the documentation doesn't want to serialize an employee's manager if the manager is the same employee.
public class Employee
{
public string Name { get; set; }
public Employee Manager { get; set; }
public bool ShouldSerializeManager()
{
// don't serialize the Manager property if an employee is their own manager
return (Manager != this);
}
}
You could put some kind of inhibit setting on your class:
public class DTO
{
[JsonIgnore]
public bool IsWritingToDatabase { get; set; }
public string AlwaysSerialize { get; set; }
public string Optional { get; set; }
public bool ShouldSerializeOptional()
{
return IsWritingToDatabase;
}
}
But, this isn't much simpler than having two objects. So I would recommend doing as #zbugs says, and having separate definitions for API-side and DB-side.
I ended up making all properties I needed to only add attributes to virtual, and overriding them alone in another class, with the relevant newtonsoft attributes.
This allows me to have different serialisation behavior when de-serialising from CouchDB and serialising for a GET, without too much dupe. It is fine, and a bonus, that the two are coupled; any changes in the base i would want anyway.
It would still be nice to know if my original question is possible?
This newtonking.com link helped in a similar situation. It extends the DefaultContractResolver class. To make it work I had to replace
protected override IList<JsonProperty> CreateProperties(JsonObjectContract contract)
with
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)