I'm using ApiController and I want it to return a list of tuples, like: List<Tuple<DateTime,DateTime>>.
(My action returns it in IHttpActionResult object.)
The problem is, when I receive the response and I try to deserialize it to the above object - list of tuples, I got a strange result the json in my client side is: [{"m_Item1":"2020-01-30T12:13:23","m_Item2":"2020-01-30T12:13:23"}].
I want it to look like this: [{"Item1":"2020-01-30T12:13:23","Item2":"2020-01-30T12:13:23"}].
Maybe somebody knows how can I avoid it?
I know that I can create an object which contains 2 fields of datetimes, but I don't want because my client does not know the server, so it also doesn't know the object that I declare...
Or maybe you have another idea to resolve it?
Thanks a lot!
Yeah, it's extremely easy to avoid this issue. Create a proper dto class like every good person should and return it from your api instead.
Related
My question is little theoretical but it's interesting one.
I want to know which approach is best while using web api.
I've two methods
One has List<Customer> as parameter
public void Create(List<Customer>) { //... }
Second has CustomerList as parameter (Where CustomerList class has property public List<Customer> customers {get; set;})
public void Create(CustomerList customer) { //... }
I know how for method 1, I need to pass json array and for method two I need to wrap json array to json object.
But my question is which approach is best and why?
When it comes to APIs, I always try to be as explicit as possible when it comes to the contract it exposes. So when you expect a List, use a JSON array. It will be much clearer to users of your API what is expected.
Having said that, the advantage of using a JSON object is that it won't be a breaking change if you decide to accept extra properties with your request later on.
In the end, it all depends on your use-case. Is this going to be an endpoint exposed to other people than just you? Do you already know you're going to want to accept additional data along with the customer list in the future? These are some of the questions you need to ask yourself.
I have a bit of a weird issue. Working in C# script with SSIS I have developed a need to build a List based off Dynamic Data.
Background
To explain it, a script task is fired that has a variable API URL, this goes off and pulls a JSON string back and then throws it into a strongly typed list using the following code.
var listobject = get_APIData<ApplicationOneDataSet>(url)
The class that does this is long winded and not really needed in the context of this issue.
ApplicationOneDataSet is a strongly typed match to one of the possible JSON results returned by get_APIData.
Now I have a need to change ApplicationOneDataSet to ApplicationTwoDataSet dynamically based on which API URL I pass to the script.
So what I have done is send through a second variable to the script called class name which contains the string "ApplicationDataSetOne" or "ApplicationDataSetTwo" based on which context I call it under.
The Question
My question is how can I dynamically vary this line:
var listobject = get_APIData<ApplicationOneDataSet>(url)
With the string variable passed into the script.
My original thinking was something along the lines of this:
var ClassType = (string) Dts.Variables["AppClassName"].Value;
Type type = Type.GetType(ClassType);
var listobject = get_APIData<type>(url)
Though it doesn't seem to like that. Any tips would be great!
As long as there is exactly two types you can use and you know them at compile time, I would not look further than a simple if. It works, it's easy, everyone understands it.
You can do it totally dynamic at runtime, but that's a huge pain in the... where you don't want it to be. If you really want to go down that rabbit hole, you can find more information here.
I'm not sure I fully understood what you are trying to do, but how about writing an interface ApplicationDataSet and then making a list of it? This way your list is going to be able to contain both types of data.
My Problem is that when I browse to the service URL I see "key-value" pairs but I don't see the name of the array or object, I need the name because I want to use that service for android.
it looks like this:
My code looks like this:
1. In ValueController I have method:
[AcceptVerbs("GET", "POST")]
public List<BuzzMonitor.Web.Message> Search(string text, DateTime dateFrom, DateTime dateTo, [ModelBinder]List<int> themeIds, [ModelBinder]List<int> sourceIds)
{
MessageHandler mh = new MessageHandler();
List<BuzzMonitor.Web.Message> messages = null;
messages = mh.Search(text,dateFrom,dateTo,themeIds,sourceIds);
return messages;
}
2. In Global.asax I added:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Does anyone have an idea on what is missing when I don't see full JSON, and see just key:value pairs? Thank you for help!
I think you are thinking that you are not seeing the array name or class right? and that is an error?
The answer is NO.
Reason? Well, JSON was invented to share objects easily over network and the main goal was to make it independent of the underlying architecture -
http://www.json.org/
that is why you don't see array names or variable names, only the object notation. Thats JSON stands for Java Script Object Notation. It's the responsibility of the receiving side to re-construct the object from the data provided in json format.
in your case messages is an array with a list of data and so does the output -
[] means array and {} inside that means it has only one object in it.
EDIT: You can also use this to parse json -
http://developer.android.com/reference/org/json/JSONTokener.html
I'm really new to API design and MVC concepts, but as far as I can tell, something like GET /api/products should return a list of products and GET /api/products/1 should return a single product. In terms of speed my feeling is that /api/products should return less information i.e. just id and name, whereas /api/products/1 should return more i.e. id, name, and description.
As far as I can see, the best way to handle this is to make certain fields of the product class not be returned in the /api/products endpoint. This is especially necessary in the case of /api/products?fields=name . I'm using ASP.Net Web Api 2 and have tried the following:
http://www.nuget.org/packages/WebApi.PartialResponse/ - installing this package caused an assembly version error.
Adding ShouldSerialize methods on the Product fields. For reasons I won't go into here, this method is a little cumbersome.
Looked at ASP.NET Web API partial response Json serialization but there doesn't seem to be a conclusive answer there.
ASP.NET WebApi and Partial Responses suggests using a product class with all nullable fields. I'm not sure I understand exactly what to do there.
Is there any simple way to do what I'm trying to do?
Otherwise could you suggest a better API design than what I'm doing?
You could also use WebApi.PartialResponse (http://www.nuget.org/packages/WebApi.PartialResponse/). It's a package I wrote which uses LINQ to JSON (Json.NET) to manipulate the returned objects. It uses the fields syntax used by Google in their API's, eg.:
fields=items/id,playlistItems/snippet/title,playlistItems/snippet/position
fields=items(id,snippet/title,snippet/position)
fields=items(id,snippet(title,position))
You can find more information on the GitHub project page: https://github.com/dotarj/PartialResponse.
I'd recommend using separate classes to map to when returning a list of entities.
Particularly as the problem is not just what you return to the user, but also what you select from the database.
So, make getting and entity return a Product object, and getting a list of entities return a ProductLink object or something similar.
Edit
As per jtlowe's comment, if you have many different methods returning slight variations of product properties, use anonymous classes (though I'd question whether this is necessarily a good design).
Consider something like this in your action
return from p in this.context.Products
select new
{
p.Id,
p.Name,
p.SKU
};
This:
Only selects the columns you need from the database.
Needs no additional classes defined for new variations of the product
This doesn't make it easy to pass the result of this statement around to other methods because you can only return it as IEnumerable, object or dynamic. If you are putting this in the controller then it may be good enough. If you are implementing a repository pattern, you'll be unable to return strongly typed lists if you use anonymous types.
Stumpled over this topic and just want to share my feelings - maybe it helps others :) I recommend to use something like OData.
You can implement it so that you can write /api/products?$select=Id,Name,Price
some advantages:
with OData you can use further functions, like $filter, $orderby to work with filters and sort it
$skip, $top, $count to get a nice paging
more $-functions :)
you can directly apply it to a IQueryable<T>. Why is this great? You reduce the result not just in the response of your API, but you even reduce the result your database generates, which makes your application much faster. - and you don't even have to change your query
some disadvantages:
you can't filter directly on columns that are calculated
setting it up will take a little time
hint: sometimes it's better to just use ODataQueryOptions<T> in the parameter instead of complete implementation.
I have a small WinRT client app to my online service (Azure Web Service). The server sends a JSON encoded object with (with potential additional metadata) to the client and the client's responsibility would be to deserialize this data properly into classes and forward it to appropriate handlers.
Currently, the objects received can be deserialized with a simple
TodoItem todo = JsonConvert.DeserializeObject<TodoItem>(message.Content);
However, there can be multiple types of items received. So what I am currently thinking is this:
I include the type info in the header serverside, such as "Content-Object: TodoItem"
I define attributes to TodoItem on the client side (see below)
Upon receiving a message from the server, I find the class using the attribute I defined.
I call the deserialization method with the resolved type
(Example of the attribute mentioned in 2.)
[BackendObjectType="TodoItem"]
public class TodoItem
My problem with this approach however is the Type to Generics in the deserialization as I can't call:
Type t = ResolveType(message);
JsonConvert.DeserializeObject<t>(message.Content);
I tried finding some solutions to this and getting method info for the DeserializeObject and calling it using reflection seemed to be the way to go. However, GetMethod() does not exist in WinRT and I was not able to find an alternative I could use to retrieve the generic version of the DeserializeObject (as fetching by the name gives me the non-generic overload). I don't mind using reflection and GetMethod as I can cache (?) the methods and call them every time a message is received without having to resolve it every time.
So how do I achieve the latter part and/or is there another way to approach this?
Alright, I feel like this was not really a problem at all to begin with as I discovered the DeserializeObject(string, Type, JsonSerializerSettings) overload for the method. It works splendidly. However, I would still like to hear some feedback on the approach. Do you think using attributes as a way to resolve the type names is reasonable or are there better ways? I don't want to use the class names directly though, because I don't want to risk any sort of man-in-the-middle things be able to initialize whatever.
Just a few minutes ago we have posted the alternative way to do what you want. Please look here, if you will have any questions feel free to ask:
Prblem in Deserialization of JSON
Try this
http://json2csharp.com/
Put your Json string here it will generate a class
then
public static T DeserializeFromJson<T>(string json)
{
T deserializedProduct = JsonConvert.DeserializeObject<T>(json);
return deserializedProduct;
}
var container = DeserializeFromJson<ClassName>(JsonString);