c# - Dynamic .NET WebAPI 5.2 Controllers based on some an abstract base type -
assuming rest , data access interactions standard, want able create abstract type represent entity objects pass , forth rest client (e.g. javascript in browser) persistence layer without writing/registering/routing bunch of different webapi controllers.
how can 1 create 1 controller base type implementation manage persistence of several different entity type rest interactions? i.e. how can make work webapi?
using system; using system.collections.generic; using system.diagnostics.contracts; using system.linq; using system.web; using system.web.http; namespace dynamicentityapicontrollers { /// <summary> /// /// </summary> public class entitycontroller<t> : apicontroller t : entityobject { private readonly idaoprovider daoprovider; /// <summary> /// initializes new instance of <see cref="entitycontroller{t}"/> class. /// </summary> /// <param name="daoprovider">the dao provider.</param> protected entitycontroller(idaoprovider daoprovider) { this.daoprovider = daoprovider; } /// <summary> /// gets name of collection. /// </summary> /// <value> /// name of collection. /// </value> protected string collectionname { { return (string)this.requestcontext.routedata.values["controller"]; } } /// <summary> /// gets specified entity key collection. /// </summary> /// <param name="key">the key.</param> /// <returns></returns> public t get(string key) { return this.daoprovider.output<t>(this.collectionname, key).data; } /// <summary> /// creates or updates specified entity key in collection. /// </summary> /// <param name="key">the key.</param> /// <param name="updating">the updating.</param> /// <returns></returns> public t put(string key, [frombody] t updating) { var daoobject = daoentity.create(this.collectionname, key, updating); return this.daoprovider.input<t>(daoobject).data; } /// <summary> /// creates or updates collection specified entirely. /// </summary> /// <param name="replacingcollection">the replacing collection.</param> /// <returns></returns> public ienumerable<t> put([frombody] ienumerable<t> replacingcollection) { return this.daoprovider.input<t>(replacingcollection .select(o => daoentity.create(this.collectionname, o))); } /// <summary> /// creates new entity in specified collection. /// </summary> /// <param name="creating">the creating.</param> /// <returns></returns> public t post([frombody] t creating) { var daoentity = daoentity.create(this.collectionname, creating); return this.daoprovider.input(daoentity).data; } /// <summary> /// deletes specified entity key collection. /// </summary> /// <param name="key">the key.</param> public void delete(string key) { this.daoprovider.delete(this.collectionname, key); } } }
the javascript client must look/act this:
$.ajax({url: '/book', method: 'post', data: {title: 'this stackoverflow post', pagecount: '124' }) .done(function(data) { $.get('/book/'+data.key).done(function(data) { // return book created console.dir(data); }) }) $.ajax({url: '/book', method: 'post', data: {title: 'some other stackoverflow post', pagecount: '236' }) .done(function(data) { $.get('/magazine/'+data.key).done(function(data) { // return 404 status code because you're asking book's key // in magazines collection console.dir(data); }) })
the sample solution has bunch todo here (like right etag header, if-match, etc...) had 4 queries across stackoverflow find these bits.
prerequisites:
- autofac (ioc) integration webapi
- webapi controller location / dependencyresolver (these not same things)
- c# generics
- reflection il emitting
- very minimal rest understanding , etag is.
briefly, here logic:
- create base type (entityobject)
- identify entities @ ioc registration time via reflection (implementer responsible specifying assemblies scan)
- create concrete implementations of abstract class entitycontroller via il emitting
- tell supportsdynamiccontrollertyperesolver these dynamic types
- idaoprovider implementation "persistence" layer. implement persistence logic here.. in sample, in memory dictionary used.
and happens when request made: - routetable interrogated (finds {controller}/{key} route httproute - controller name matches entityobject implementer name minus entity. i.e. bookentity => bookcontroller - supportsdynamiccontrollertyperesolver required here dynamic assembly types valid candidates webapi try activate. - http put/get/post/delete methods find correct method - persistence layer rest
Comments
Post a Comment