Reputation: 71
What approach should I use if I want to return only some of fields from the model? I want to be able to ask for some fields, something like this:
?fields=email,expiration_date,avatar(thumb_width,thumb_height,thumb_url)
This expression could be also header in the request. I also have nested objects, like the Avatar inside the User.
This will save me hundred of MB of traffic, since some of my models are really heavy ones.
UPDATE: Field selection should work both with Json and XML responses.
Upvotes: 6
Views: 3270
Reputation: 1947
You could also use OData. It gives you plenty of flexibility in how you want to query and API. http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/create-an-odata-v4-endpoint
In your case, you would use $select. I'm also guessing that Avatar is another class, so you would use $expand for that.
/api/endpoint?$select=email,expiration_date&$expand=avatar($select=thumb_width,thumb_height,thumb_url)
I'm not 100% if the syntax for the subselect is right, but I think it is.
Upvotes: 0
Reputation: 38509
I found a nuget package that does this for you
Git hub source code:
https://github.com/dotarj/PartialResponse
It essentially wraps the formatter discussed above, so that you only have to configure it like this:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new PartialJsonMediaTypeFormatter() { IgnoreCase = true });
Then, you can specify ?fields=<whatever>
in your request, and it will return the model with only those fields specified.
Upvotes: 6
Reputation: 9189
I would replace the default contract resolver (see http://frankapi.wordpress.com/2012/09/09/going-camelcase-in-asp-net-mvc-web-api/) with a custom one, override the GetSerializableMembers method from the Newtonsoft.Json.Serialization.DefaultContractResolver class and filter its results with the value of the querystring fields.
Whether you can access the querystring from that class is another question, you may be able to use the static httpcontext.current to get it, but there may be a cleaner option.
Upvotes: 2