c# - How to prioritize Web Api Controllers over IHttpHandler? -


i have legacy project has single ihttphandler implementing class routes requests using huge switch statement etc.. trying introduce attribute routing apicontrollers first 1 has priority. possible configure system (either code or iis) web apicontrollers have priority on single ihttphandler implementing class? in iis, put attributerouting first , there aspx ones still web api controller not getting processed first..no matter (having them under same project). don't want introduce separate project.

edit: there ihttpmodule decides based on after api/ route specific ashx file. 1 of them 1 described..

edit 2: more specifically: if uri doesn't have list of filtered things [file,message,property ...] routed resource.aspx

so api/file, api/message, api/property handle other .ashx files - otherwise traffic goes resource.ashx...

as result requests have api/endpoint1, api/endpoint2, api/endpoint3 go resource.aspx. question how route api/endpoint3 api controller described below. thanks

simplified code architecture:

 //solutionname/api/mymodule.cs (legacy code)  //this routes based on after api/ resource.ashx or other ashx files  public class mymodule : ihttpmodule {     //if url doesn't contain [file,message,property ...] route resource.ashx  } 

//solutionname/api/resource.ashx (legacy code) //this hit @ request solutionname/api/anything public class defaulthandler : ihttphandler  {    public void processrequest(httpcontext context) {        string apibranch = parse(context);        switch(apibranch)        {            case "endpoint1": methodone(); break;            case "endpoint2": methodtwo(); break;            [...]            default: throw exception(); break;        }    } } 

//solutionname/api/app_start/attributeroutinghttpconfig.cs public static class attributeroutinghttpconfig {     public static void registerroutes(httproutecollection routes)      {             // see http://github.com/mccalltd/attributerouting/wiki more options.         // debug routes locally using built in asp.net development server, go /routes.axd          routes.maphttpattributeroutes();     }      public static void start()      {         registerroutes(globalconfiguration.configuration.routes);     } } 

//solutionname/api/controllers/mycontroller.cs //this should have been hit on solutionname/api/endpoint3/id [routeprefix("endpoint3")] public class mycontroller : apicontroller {     private imodeldao modeldao;      mycontroller(imodeldao modeldao){         this.modeldao = modeldao;     }         [route("{id}")]     [httpget]     public model getsomething(int id)     {         model model = modeldao.getsomething(id);         return model;     } } 

i've found 2 solutions problem. first modify module rewrites urls inserting check if web api routing system can handle request. second add module application, direct requests web api handler using httpcontext.remaphandler().

here's code:

first solution.

if module looks this:

public class mymodule: ihttpmodule {     public void dispose(){}      public void init(httpapplication context)     {         context.beginrequest += (object sender, eventargs e) =>         {             httpcontext httpcontext = httpcontext.current;             string currenturl = httpcontext.request.url.localpath.tolower();             if (currenturl.startswith("/api/endpoint0") ||                 currenturl.startswith("/api/endpoint1") ||                  currenturl.startswith("/api/endpoint2"))             {                 httpcontext.rewritepath("/api/resource.ashx");             }         };     } } 

then need change this:

public void init(httpapplication context) {     context.beginrequest += (object sender, eventargs e) =>     {         httpcontext httpcontext = httpcontext.current;         var httprequestmessage = new httprequestmessage(             new httpmethod(httpcontext.request.httpmethod),             httpcontext.request.url);         ihttproutedata httproutedata =              globalconfiguration.configuration.routes.getroutedata(httprequestmessage);         if (httproutedata != null) //enough if webapiconfig.register empty             return;          string currenturl = httpcontext.request.url.localpath.tolower();         if (currenturl.startswith("/api/endpoint0") ||             currenturl.startswith("/api/endpoint1") ||             currenturl.startswith("/api/endpoint2"))         {             httpcontext.rewritepath("/api/resource.ashx");         }     }; } 

second solution.

module remapping handlers:

public class remappingmodule: ihttpmodule {     public void dispose() { }      public void init(httpapplication context)     {         context.postresolverequestcache += (src, args) =>         {             httpcontext httpcontext = httpcontext.current;             string currenturl = httpcontext.request.filepath;             if (!string.isnullorempty(httpcontext.request.querystring.tostring()))                 currenturl += "?" + httpcontext.request.querystring;             //checking if url rewritten             if (httpcontext.request.rawurl != currenturl)              {                 //getting original url                 string url = string.format("{0}://{1}{2}",                     httpcontext.request.url.scheme,                     httpcontext.request.url.authority,                     httpcontext.request.rawurl);                 var httprequestmessage = new httprequestmessage(                     new httpmethod(httpcontext.request.httpmethod), url);                 //checking if web api routing system can find route specified url                 ihttproutedata httproutedata =                      globalconfiguration.configuration.routes.getroutedata(httprequestmessage);                 if (httproutedata != null)                 {                     //to honest, found out experiments,                      //context route data should filled way                     var routedata = httpcontext.request.requestcontext.routedata;                     foreach (var value in httproutedata.values)                         routedata.values.add(value.key, value.value);                     //rewriting url                     httpcontext.rewritepath(httpcontext.request.rawurl);                     //remapping web api handler                     httpcontext.remaphandler(                         new httpcontrollerhandler(httpcontext.request.requestcontext.routedata));                 }             }         };     } } 

these solutions work when method webapiconfig.register empty, if there routes templates "api/{controller}" path 2 segments starting "api" pass check, if there're no controllers specified name , module can userfull path. in case can, example, use method this answer check if controller exists.

also web api routing system accept route if found controller don't handle requests current http method. can use descendant of routefactoryattribute , httpmethodconstraint avoid this.

upd tested on controllers:

[routeprefix("api/endpoint1")] public class defaultcontroller : apicontroller {     [route("{value:int}")]     public string get(int value)     {         return "testcontroller.get: value=" + value;     } }  [routeprefix("api/endpoint2")] public class endpoint2controller : apicontroller {     [route("segment/segment")]     public string post()     {         return "endpoint2:post";     } } 

Comments

Popular posts from this blog

Java 3D LWJGL collision -

spring - SubProtocolWebSocketHandler - No handlers -

methods - python can't use function in submodule -