Reputation: 537
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:
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?
Upvotes: 13
Views: 8965
Reputation: 5946
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:
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 querysome disadvantages:
hint: sometimes it's better to just use ODataQueryOptions<T>
in the parameter instead of complete implementation.
Upvotes: 0
Reputation: 488
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.:
You can find more information on the GitHub project page: https://github.com/dotarj/PartialResponse.
Upvotes: 8
Reputation: 8595
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:
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.
Upvotes: 4