Problem
I call different webservices which returns json strings. I parse these strings to custom objects and save them in a "result class" called APIResult. For instance, one webservice returns a list OBJ1, another returns OBJ2, and sometimes two or more objects are returned as well. The result class is returned to the method calling it with the objects and a boolean indicating whether the request was succesful.
This works, but when I have to call many different webservices the class gets ugly. Right now I have 7 properties like OBJ1, OBJ2, List, List and so on. To avoid adding more properties to the APIResult class I want to redesign it to be more flexible, but I'm not sure what is the best approach.
Ideas
Generics seems to be a good idea. I could initialize my class with new APIResult(ObjectType) and then have one or more properties T Data1. Still a bit ugly to have three properties T Data1, T Data2, T Data3. I am also unsure if I can parse the objects from json to a generic type without reflection and if that would slow things down.
Do you have any suggestions?
Separate the result state from the actual data.
As you suggested, generics are a useful tool for this. Create a result state class that encapsulates the success/failure logic and (in the case of success) provides access to the data.
This could look something like this:
public class ApiResult<T>
{
public bool Success { get; }
public T Dto { get; }
public ApiResult(bool success, T dto)
{
Success = success;
Dto = dto;
}
}
Now design the data classes as simple property bags without any logic. Their only purpose is to define what data is returned from a specific web service. Also, do not try to build deep inheritance hierarchies. Adding the same property to two different DTOs is fine.
public class Dto1
{
string PropertyA { get; set; }
string PropertyB { get; set; }
}
public class Dto2
{
string PropertyA { get; set; }
string PropertyC { get; set; }
}
With this, you are now able to define proxies for the web services you call. A proxy interface could look like this:
public interface ISomeServiceProxy
{
ApiResult<Dto1> GetTheThing(string someParam);
}
In the implementation of this interface you will want to use JSON.NET to deserialize the response into a Dto1 and wrap it in a ApiResult.
Also, you probably want to make the proxy use async. I left that out in these examples, converting them is straight-forward.
There are few things to consider here
Do you need an APIResult class? What are you going to do with it? If you have a well documented REST api (say an odata api) then the response is well described and you can verify that the response you get is what you need. Otherwise what are you going to do if it doesn't match?
if you are just going to parse it into your model you might even consider the generic JObject to hold your response. Then you can check for properties/subobjects on this JObject. You could even pass this into the (newtonsoft) json serializer and have the calling method say what it should look like.
what is the business meaning of your response? Result is always a hard name. However if you you have properties like FirstName, LastName, AddressList, etc then it becomes a lot nicer.
Related
I have an array of objects looking like this
public class ViewFilterData
{
public string Table { get; set; }
public string Field { get; set; }
public string Value { get; set; }
}
Due to calling function in separate dll, I need to pass this array as object[]. The above class is defined in both sections.
Project compiles, however when I try to cast each object in the array to above class, I get an invalidCastException, indicating that it "magically" know the originally class and refuse to cast it to the new one even though they are verbatim identical. Do I need to use reflection and create a new class marshalling over the array object by object and attribute by attribute? Or is there a simpler faster way? Thought about using scructs, however would rather not if possible.
"Unable to cast object of type 'Original.ViewFilterData' to type SeparateDLL.ViewFilterData'."
I call the function like this
var dt = oRepository.Page((object[])oDataRequest.Filters.ToArray())
and define it like this
public DataTable Page(object[] Filters)
Same name doesn't mean, they're of the same types. .NET cannot magically infer that.
for small objects, just write a quick LINQ query:
var separateDllFilters = oDataRequest.Filters.Select(of => new SeparateDLL.ViewFilterData
{
Table = of.Table,
// so on
}).ToArray();
however, if all the fields are same, (or even if they're not) you can use tools like AutoMapper to transform them easily.
typically, this is the order of solutions:
quick LINQ queries.
Extension methods to map the types.
Tools like AutoMapper
the solution you choose depends on factors like, how often you do this, how many callers need this, etc.
The above class is defined in both sections.
This is not valid in C#, each class is distinct from all other classes.
If you want to pass data between libraries you must use consistent types. The most popular method is to use a base library.
I'm refactoring a class that represents the data in some XML. Currently, the class loads the XML itself and property implementations parse the XML every time. I'd like to factor out the XML logic and use a factory to create these objects. But there are several 'optional' properties and I'm struggling to find an elegant way to handle this.
Let's say the XML looks like this:
<data>
<foo>a</foo>
<bar>b</bar>
</data>
Assume both foo and bar are optional. The class implementation looks something like this:
interface IOptionalFoo
{
public bool HasFoo();
public string Foo { get; }
}
// Assume IOptionalBar is similar
public class Data : IOptionalFoo, IOptionalBar
{
// ...
}
(Don't ask me why there's a mix of methods and properties for it. I didn't design that interface and it's not changing.)
So I've got a factory and it looks something like this:
class DataFactory
{
public static Data Create(string xml)
{
var dataXml = new DataXml(xml);
if (dataXml.HasFoo())
{
// ???
}
// Create and return the object based on the data that was gathered
}
}
This is where I can't seem to settle on an elegant solution. I've done some searching and found some solutions I don't like. Suppose I leave out all of the optional properties from the constructor:
I can implement Foo and Bar as read/write on Data. This satisfies the interface but I don't like it from a design standpoint. The properties are meant to be immutable and this fudges that.
I could provide SetFoo() and SetBar() methods in Data. This is just putting lipstick on the last method.
I could use the internal access specifier; for the most part I don't believe this class is being used outside of its assembly so again it's just a different way to do the first technique.
The only other solution I can think of involves adding some methods to the data class:
class Data : IOptionalFoo, IOptionalBar
{
public static Data WithFoo(Data input, string foo)
{
input.Foo = foo;
return input;
}
}
If I do that, the setter on Foo can be private and that makes me happier. But I don't really like littering the data object with a lot of creation methods, either. There's a LOT of optional properties. I've thought about making some kind of DataInitialization object with a get/set API of nullable versions for each property, but so many of the properties are optional it'd end up more like the object I am refactoring becomes a facade over a read/write version. Maybe that's the best solution: an internal read/write version of the class.
Have I enumerated the options? Do I need to quit being so picky and settle on one of the techniques above? Or is there some other solution I haven't thought of?
You can think of such keywords as virtual/castle dynamic proxy/reflection/T4 scripts - each one can solve the problem on a slightly different angle.
On another note, this seems perfectably reasonable, unless I misunderstood you:
private void CopyFrom(DataXml dataXml) // in Data class
{
if (dataXml.HasFoo()) Foo = dataXml.Foo;
//etc
}
What I did:
I created a new class that represented a read/write interface for all of the properties. Now the constructor of the Data class takes an instance of that type via the constructor and wraps the read/write properties with read-only versions. It was a little tedious, but wasn't as bad as I thought.
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.
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.