c# - Web API action selection based on Accept header -
queue long introduction...
i have resource defined at
http://my-awesome-product.com/api/widgets/3
which represents widget id
of 3. in web api define controller serve resource follows:
public class widgetscontroller : apicontroller { public widget get(int id) { return new widget(...); } }
now, widget
class potentially quite big, , wanting save bandwidth database web server, , web server client, create several dto classes contain restricted number of fields of overall widget
. example:
public class widgetsummary { public int id { get; set; } public string code { get; set; } public string description { get; set; } public decimal price { get; set; } } public class fullwidgetforediting { public int id { get; set; } public string code { get; set; } public string description { get; set; } public decimal weight { get; set; } public decimal price { get; set; } public color color { get; set; } public decimal width { get; set; } public decimal height { get; set; } public decimal depth { get; set; } } public class widgetfordropdownlist { public int id { get; set; } public string code { get; set; } }
with these widget
representations, client request widgetsummary
display on summary grid of widget
s in system, request fullwidgetforediting
on edit page of specific widget
, , request widgetfordropdownlist
use in drop down list on order form.
from understand rest, access widget
there should single url single resource, regardless of representation , client should specify accept
headers media type parameter retrieve widget
in different forms, e.g. my-awesome-product.type=widgetsummary
, my-awesome-product.type=fullwidgetforediting
, , my-awesome-product.type=widgetfordropdownlist
.
i achieve in web api inspecting headers of request so:
public class widgetscontroller : apicontroller { public object get(int id) { if (request.headers.accept.any(x => x.parameters.any(y => y.name == "my-awesome-product.type" && y.value == "widgetsummary"))) { return new widgetsummary(...); } else if (request.headers.accept.any(x => x.parameters.any(y => y.name == "my-awesome-product.type" && y.value == "fullwidgetforediting"))) { return new fullwidgetforediting(...); } else if (request.headers.accept.any(x => x.parameters.any(y => y.name == "my-awesome-product.type" && y.value == "widgetfordropdownlist"))) { return new widgetfordropdownlist(...); } throw new httpresponseexception(httpstatuscode.notacceptable); } }
however, gets messy number of types grow , makes unit testing more difficult. following:
public class widgetscontroller : apicontroller { [httpget(mediatype = "my-awesome-product.type", mediatypevalue = "widgetsummary")] public widgetsummary getwidgetsummary(int id) { return new widgetsummary(); } [httpget(mediatype = "my-awesome-product.type", mediatypevalue = "fullwidgetforediting")] public fullwidgetforediting getfullwidgetforediting(int id) { return new fullwidgetforediting(); } [httpget(mediatype = "my-awesome-product.type", mediatypevalue = "widgetfordropdownlist")] public widgetfordropdownlist getwidgetfordropdownlist(int id) { return new widgetfordropdownlist(); } }
and have web api route specific action method based on media type. investigated overriding apicontrolleractionselector
, however, started pulling in large quantities of existing code attribute because want default action selection, in case of ambiguous actions, want filter list of actions based on media type. want non-intrusive can mix convention routing, standard attribute routing (which in web api v2) , hypothetical attribute routing in same controller if need be.
question time: possible implement such routing strategy web api stands? have reimplement apicontrolleractionselector
achieve (and make sure reimplementation stays date)?
so here question need ponder. 3 representations, or 3 distinct resources? if decided cache representations, uri sufficient identify cached representation, or need vary on accept header?
if accept different enough resources should identified different urls. if decide use hyperlinks in responses, not want ability point 'widgetsummary' independently 'widgeteditform'?
usually multiple representations needed when want support different client devices capable of supporting media types. e.g. device gets rep1 , device b gets rep2. it's rare want device access both device , rep1 , rep2.
just thoughts...
Comments
Post a Comment