By default, the Webapi route in the MVC framework template provided by Microsoft does not support the namespace parameter. This leads to some larger projects that cannot separate WEBAPI into a separate class library.
This article provides a solution to the problem.
Microsoft has given an extension on Webapi support namespace, the main thing is that the custom implementation of the Ihttpcontrollerselector interface, through the routing configuration to replace the self- contained MVC Defaulthttpcontrollerselector to achieve Webapi support namespace. But after my test, the effect is not good. This will not be affixed to the official Microsoft source code.
Let me introduce my solution.
First look at my custom directory structure, such as:
First define a class, the name can be arbitrary, I named zhusirnamespacehttpcontrollerselectorhere, he inherits from the MVC framework Default The Defaulthttpcontrollerselector class, the primary purpose of the inheriting class, is to retrieve the WEBAPI controller of the namespace we specify when the request URI reaches the WEBAPI route. Here is the source code for the Zhusirnamespacehttpcontrollerselector class, which you can copy directly into your own project:
<summary>////extended from Defaulthttpcontrollerselector class controller selector, currently in use///</summary> public class Zhusi Rnamespacehttpcontrollerselector:defaulthttpcontrollerselector {Private Const string Namespaceroutevariablena me = "namespaces"; Private ReadOnly httpconfiguration _configuration; Private ReadOnly lazy<concurrentdictionary<string, type>> _apicontrollercache; Public Zhusirnamespacehttpcontrollerselector (httpconfiguration configuration): Base (configuration) { _configuration = Configuration; _apicontrollercache = new lazy<concurrentdictionary<string, type>> (New Func<concurrentdicti Onary<string, Type>> (Initializeapicontrollercache)); } private Concurrentdictionary<string, type> Initializeapicontrollercache () {Iassembliesre Solver assembliesresolver = this._configuration. Services.getassembliesresolver (); var types = this._configuration. Services.gethttpcontrollertyperesolver (). Getcontrollertypes (Assembliesresolver). ToDictionary (t = t.fullname, t = t); return new concurrentdictionary<string, type> (types); } public ienumerable<string> Getcontrollerfullname (httprequestmessage request, String controllername) {Object namespacename; var data = Request. Getroutedata (); ienumerable<string> keys = _apicontrollercache.value.todictionary<keyvaluepair<string, Type>, string , type> (t = t.key, t = t.value, stringcomparer.currentcultureignorecase). Keys.tolist (); if (!data. Values.trygetvalue (Namespaceroutevariablename, out namespacename)) {return from K in keys where K.endswith (string. Format (". { 0}{1} ", Controllername, Defaulthttpcontrollerselector.controllersuffix), STRINGCOmparison. currentcultureignorecase) Select K; } string[] namespaces = (string[]) namespacename; Return from N in namespaces joins K in keys on string. Format ("{0}.{ 1}{2} ", N, Controllername, Defaulthttpcontrollerselector.controllersuffix). ToLower () equals K.tolower () select K; } public override Httpcontrollerdescriptor Selectcontroller (Httprequestmessage request) {Type Ty Pe if (request = = null) {throw new ArgumentNullException ("request"); } string controllername = this. Getcontrollername (Request); if (string. IsNullOrEmpty (Controllername)) {throw new httpresponseexception (request. Createerrorresponse (Httpstatuscode.notfound, String. Format ("Could not be routed through API to the URI you requested ' {0} '", new object[] {request. RequestUri})); } ienumerable<string> Fullnames = Getcontrollerfullname (request, controllername); if (fullnames.count () = = 0) {throw new httpresponseexception (request. Createerrorresponse (Httpstatuscode.notfound, String. Format ("Could not be routed through API to the URI you requested ' {0} '", new object[] {request. RequestUri})); } if (This._apicontrollercache.value.trygetvalue (Fullnames.first (), out type)) {Retu RN New Httpcontrollerdescriptor (_configuration, controllername, type); } throw new Httpresponseexception (request. Createerrorresponse (Httpstatuscode.notfound, String. Format ("Could not be routed through API to the URI you requested ' {0} '", new object[] {request. RequestUri})); } }
In the second step, we need to configure the Webapi routing settings, add the { namespaces } fragment variable, and set the default value directly for it, and then replace the Defaulthttpcontrollerselector in the original MVC framework The selector is the zhusirnamespacehttpcontrollerselector selector we previously extended. It is important to note that the variable name of the fragment variable namespaces must be defined in our Zhusirnamespacehttpcontrollerselector the value of the Namespaceroutevariablename string constant is consistent. The following post Webapiconfig source code:
public static class Webapiconfig {public static void Register (Httpconfiguration config) {//With The Check API control suffix is apicontroller//var suffix = typeof (Microsoftnamespacehttpcontrollerselector)//. GetField ("Controllersuffix", BindingFlags.Static | BindingFlags.Public); if (suffix! = null)//{//suffix. SetValue (NULL, "Apicontroller"); }//Web API Configuration and Services//configure the Web API to use anonymous token authentication only. Config. Suppressdefaulthostauthentication (); Config. Filters.add (New Hostauthenticationfilter (Oauthdefaults.authenticationtype)); Use mixed case for JSON data. Config. Formatters.JsonFormatter.SerializerSettings.ContractResolver = new Camelcasepropertynamescontractresolver (); Web API Routing config. Maphttpattributeroutes (); Config. Routes.maphttproute (Name: "Defaultapi", Routetemplate: "Api/{controller}/{id}/{namespaces} ", defaults:new {id = routeparameter.optional, namespaces = new[] {" ZhuSir.HMS.WebApi . Apicontrollers "}}); Config. Services.replace (typeof (Ihttpcontrollerselector), new Zhusirnamespacehttpcontrollerselector (config)); } }
As the source code. We replaced the original MVC framework with the Defaulthttpcontrollerselector as zhusirnamespacehttpcontrollerselector, and specifies that the default namespaces is ZhuSir.HMS.WebApi.ApiControllers. The general meaning is that when the URL is http://XXX/api/testApi , the WEBAPI route will be ZhuSir.HMS.WebApi.ApiControllers Look for the Get method for the WEBAPI controller named Testapi under the namespace.
Of course, the WEBAPI controller in addition to the integration word Apicontroller accidentally also notice the naming specification, all need to end with a controller, in order not to let the API controller and MVC control name, I end with Apicontroller. The following post Testapi source code:
namespace zhusir.hms.webapi.apicontrollers{public class Testapicontroller:apicontroller { [httpget] Public string Gettest () { return "test Data";}} }
Program debug, Input URL: http://localhost:4541/api/TestApi, get the following results:
As you can see, the WEBAPI route successfully accesses the WEBAPI controller in other class libraries.
I hope this article will be helpful to you, if reproduced please specify the source: http://www.cnblogs.com/smallprogram/p/5673066.html
MVC5 support for Webapi add namespaces