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.
Related
I'm considering migrating current WCF-based based application to protobuf-net.Grpc. It seems to be doable, however I was not able to make protobuf-net serialize properties of (DTO classes) base class without including all derived classes with [ProtoInclude] attribute.
Simplified class hierarchy:
[DataContract]
public abstract class DtoBase
{
[DataMember(Order = 1)]
public int Id { get;set; }
[DataMember(Order = 2)]
public int Version { get;set; }
[DataMember(Order = 3)]
public EditState EditState { get;set; }
}
[DataContract]
public class PersonDto : DtoBase
{
[DataMember(Order=4)]
public string FirstName { get;set; }
[DataMember(Order=5)]
public string LastName { get;set; }
}
I have investigated related questions and it all boils down to the fact that specific type should be known during deserialization - or there should be a way to determine it. Our service methods already know the specific subclass to use, e.g. we have methods like
[ServiceContract]
public interface IPersonService
{
[OperationContract]
ScalarResult<PersonDto> GetById(personId);
}
DataContractSerializer can do that - deserialize base class properties, when specific subclass is already known. It needs hints (known types) when you deserialize subclass having base class signature, like returning PersonDto instead of DtoBase. But when specific subclass is known, known types are not needed and everything just works.
So the question is how to do the same with protobuf-net? And if it's not possible, why?
Protobuf-net, like any library, makes certain assumptions and compromises. If it wants to support additional scenarios, they need to be specified, designed, implemented, tested and supported - all of which takes time. So far, the scenario you describe: hasn't had that time invested.
It may be possible to configure the base-type properties using the RuntimeTypeModel API, but I must emphasize: whenever a question arises that is essentially:
My existing model isn't working well with my chosen serializer
my default response (based on literally decades of experience in this field) is:
If your existing model isn't a great fit for a different serializer: stop fighting the serializer. Instead, create a new model that works perfectly with your new choice of serializer, and shim between models at the point of (de)serialization
Let's say I have an interface like this:
public interface IUser
{
int Id { get; }
string Name { get; }
List<IMonthlyBudget> MonthlyBudget { get; }
}
and then I have a model that implements this:
public class User : IUser
{
public int Id { get; set; }
public string Name { get; set; }
public List<IMonthlyBudget> MonthlyBudget { get; set; }
}
and here I have the IMonthlyBudget:
public interface IMonthlyBudget
{
int Id { get; }
float MonthlyMax { get; }
float CurrentSpending { get; }
float MonthlyIncome { get; }
}
Now I have my models. But the issue comes with using SQLite. SQLite can't understand what is the real implementation of IMonthlyBudget. I understand why, but I really don't want remove the interface and expose the real implementation to all the clients that use these models. In my project structure I have a Core project that has all the model interfaces, and the model implementation are in a data access project.
Is there something wrong with how I'm approaching this problem? I assume i'm not the first one to run into a issue like this. Isn't it completely normal practice to keep model interfaces (what repositories etc then use as their return types, parameters and stuff like that) and implement the actual concrete models in a data access project?
And can someone explain why I can't do this:
public class User : IUser
{
public int Id { get; set; }
public string Name { get; set; }
public List<MonthlyBudget> MonthlyBudget { get; set; }
}
MonthlyBudget implements IMonthlyBudget, shouldn't it be completely fine to use the concrete model as the type instead of the the interface when the concrete model actually implements the interface?
A few questions here, so I'll break it down into sections:
Use of Interfaces
It is definitely good practice to interface classes that perform operations. For example, you may have a data service (i.e. data access layer) interface that allows you to do operations to read and modify data in your persistent store. However, you may have several implementations of that data service. One implementation may save to the file system, another to a DBMS, another is a mock for unit testing, etc.
However, in many cases you do not need to interface your model classes. If you're using an anemic business object approach (as opposed to rich business objects), then model classes in general should just be containers for data, or Plain Old CLR Objects (POCO). Meaning these objects don't have any real functionality to speak of and they don't reference any special libraries or classes. The only "functionality" I would put in a POCO is one that is dependent only upon itself. For example, if you have a User object that has a FirstName and LastName property, you could create a read-only property called FullName that returns a concatenation of the two.
POCOs are agnostic as to how they are populated and therefore can be utilized in any implementation of your data service.
This should be your default direction when using an anemic business object approach, but there is at least one exception I can think of where you may want to interface your models. You may want to support for example a SQLite data service, and a Realm (NoSQL) data service. Realm objects happen to require your models to derive from RealmObject. So, if you wanted to switch your data access layer between SQLite and Realm then you would have to interface your models as you are doing. I'm just using Realm as an example, but this would also hold true if you wanted to utilize your models across other platforms, like creating an observable base class in a UWP app for example.
The key litmus test to determining whether you should create interfaces for your models is to ask yourself this question:
"Will I need to consume these models in various consumers and will those consumers require me to define a specific base class for my models to work properly in those consumers?"
If the answer to this is "yes", then you should make interfaces for your models. If the answer is "no", then creating model interfaces is extraneous work and you can forego it and let your data service implementations deal with the specifics of their underlying data stores.
SQLite Issue
Whether you continue to use model interfaces or not, you should still have a data access implementation for SQLite which knows that it's dealing with SQLite-specific models and then you can do all your CRUD operations directly on those specific implementations of your model. Then since you're referring to a specific model implementation, SQLite should work as usual.
Type Compatibility
To answer your final question the type system does not see this...
List<IMonthlyBudget> MonthlyBudget
as being type-compatible with this...
List<MonthlyBudget> MonthlyBudget
In our minds it seems like if I have a list of apples, then it should be type-compatible with a list of fruit. The compiler sees an apple as a type of fruit, but not a list of apples as a type of a list of fruit. So you can't cast between them like this...
List<IMonthlyBudget> myMonthlyBudget = (List<IMonthlyBudget>) new List<MonthlyBudget>();
but you CAN add a MonthlyBudget object to a list of IMonthlyBudget objects like this...
List<IMonthlyBudget> myMonthlyBudget = new List<IMonthlyBudget>();
myMonthlyBudget.Add(new MonthlyBudget());
Also you can use the LINQ .Cast() method if you want to cast an entire list at once.
The reason behind this has to do with type variance. There's a good article on it here that can shed some light as to why:
Covariance and Contravariance
I hope that helps! :-)
I've built a REST API with the WCF Web API Preview and I wanna build a library with the classes that you pass to this API (Just to make the .Net developers life easier). The should be simple POCO classes without much functionality.
But on the receiver side it would make sense for me to add some functionality to these classes. I have an example below:
[WebInvoke(UriTemplate = "", Method = "POST")]
public Supertext.API.Order Create(Supertext.API.Order apiOrder)
{
And this is an example POCO class:
public class Order
{
public string Service { get; set; }
public string OrderTitle { get; set; }
public string Currency { get; set; }
}
Now, what's a good way to extend this class on the server side?
I guess using a subclass would not work.
Delegates?
Actually have two different versions of the class? One for clients and one for the server?
What do other people do?
The problem with adding extra functionality to this POCO class is you are turning it into a domain object. The nature of this domain object will now be constrained by the fact that, essentially, this class acts as the definition of the interface into the operation. Changing details about this class will potentially break clients.
It is a far cleaner model to keep this class purely as a Data Transfer Object whose single responsibility is aiding the bridging of the wire format to objects and use a mapper such as AutoMapper to map the data from the DTO to a real domain object. The real domain object is fully under your control and you can happily refactor it without threatening a cascading effect to your service consumers
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)
I am writing web application and I have huge class that have more then 40 members, 3 types of arrays and have many methods.
This class represents a task with all task's ingrediants including pricing of task.
The problem is that I need to pass the client list of 40 first tasks therefore I pass 40 complete task items which turns to be very big and weight a lot of KB.
How can I reduce this object??..
Here is a pic of the class diagram:
http://www.imagehousing.com/image/624350
The first thing I would tackle before even thinking of sending anything is that you refactor that class into more manageable subcomponents. Take for instance properties like DeliveryNote, DeliveryNoteId, DeliveryNoteSerial could be housed in a Delivery class. The same could be said for the Group, Payback and other similarly named properties. When designing properties of a class, you need to ask yourself whether the properties are specific to the parent model, or are specific to a smaller problem domain.
Once you've refactored that class, you then need to determine what data the client needs. Do they need every article of data in that class. If not, why not produce a view class based on what the client needs and send only that.
If you don't think a partial view is appropriate for your data, you can use DataContractAttribute and DataMemberAttribute attributes to control which parts of your model actually represent the data contract to be passed to the client. E.g.:
[DataContract]
public class Task
{
[DataMember]
public string PropertyA { get; set; }
[DataMember]
public string PropertyB { get; set; }
public string PropertyC { get; set; }
}
In the above example, using these attributes I can enforce that PropertyA and PropertyB form component parts of the data contract. PropertyC will not be part of the contract, so will not be serialised. This is of course dependent using the DataContractSerializer or a WCF-service (which uses that serialiser).
This also limits a single-data contract view of the model.
In first glance, I think you need to reduce/simplify your class, that 40 members ain't really necessary to be direct members, e.g.:
Discount, DiscountTypeCode, DiscountTypeId, DiscountTypeSign can all becomes a class ->
class Discount {
float rate;
int typeCode, typeId;
string sign;
}
Simpily group every member with same prefix to a class. This is needed not only to trim the size, but better maintenance. To reduce size, it's up to you whether you need to include those sub objects to send to the client, since it's a web application, I don't think everytime your client need everything in the object, so while you return your object, consider return just a partial of it, create that in another view model.
I think you have you to follow some basic rule.
Having big class create problem to understand the code and maintain it.
List down all the nouns and Verbs
Group common nouns and related verbs and create a class
Repeat same procedure untill there is no noun and verbs remain.
Now you to give serious thought to created classes and their methods
a. Findout Generic and Specialise Classes
b. If there is need of design pattern then think about and create relationship like
Generalisation and Specialisation, Association, Dependency and realization
The above step will automatic give better shape to classe.