In a previous post, I described the processing architecture of the new ASP.NET Web API, namely its division into three layers: hosting, message handler pipeline and controller handling.
In this post, I’m going to address one of the hosting options: web hosting, i.e., hosting on top of the ASP.NET classical pipeline.
Routing
On the ASP.NET platform, routing is commonly performed by adding routes to the RouteTable.Routes static property, which holds a RouteCollection. For example, the following code excerpt shows the default routing defined by the ASP.NET MVC project template.
protected void Application_Start() { RegisterRoutes(RouteTable.Routes); } public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); }
Most of the routing logic is performed by the UrlRoutingModule, attached to the PostResolveRequestCache ASP.NET pipeline event. On each request, this module matches the current request against the route collection, obtaining a RouteData instance. If there is a match, then:
- A route handler is obtained from the route data.
- A HTTP handler, implementing the IHttpHandler interface, is obtained from the route handler.
- Finally, the current request context is mapped to the above HTTP handler.
As a consequence, at the end of the ASP.NET pipeline the request is sent to this handler .
Web API integration
When hosting on ASP.NET, the Web API specific configuration is defined on a singleton HttpConfiguration object, accessible via the static GlobalConfiguration.Configuration property.
Web API also defines a couple of new RouteCollection extension methods, named MapHttpRoute, to register Web API specific routes. The following code excerpt contains an example configuration.
HttpConfiguration config = GlobalConfiguration.Configuration; config.Routes.MapHttpRoute("default", "{controller}/{id}", new {id = UrlParameter.Optional}); // other configuration settings
Notice:
- The static GlobalConfiguration.Configuration property, used to obtain the config reference. Internally, this configuration object points to the global RouteTable.Routes route collection.
- The usage of the MapHttpRoute extension method, when adding the route.
The routes added to the route collection by the MapHttpRoute extension methods use the new HttpControllerRouteHandler route handler . When a route added via MapHttpRoute is matched by a request, the associated route handler returns a new type of handler – the HttpControllerHandler – which implements the asynchronous IAsyncHttpHandler interface. This handler is initialized with the route data, containing the matching information.
When called, the HttpControllerHandler on its BeginProcessRequest method performs the following actions:
- Creates a HttpRequestMessage instance from the current HttpContext;
- Creates an HttpServer using the configuration referenced by GlobalConfiguration.Configuration and then pushes the new `HttpRequestMessage` into the server pipeline.
After the request is receive by the HttpServer instance, it enters the host independent phase of the processing (the Web API new pipeline).
The following diagram summarizes the route resolution process and the dispatch into the HttpServer instance (the message handler pipeline).
Thank you for the post.
So does HttpServer use routing configuration to pick the controller and its action? It must be otherwise
var config = new HttpConfiguration();
config.MapHttpRoute(…);
var server = new HttpServer(config);
var client = new HttpClient(server);
would not be picking the correct controller accordingly to the routes registered in ‘config’. But if it does use that routing information what’s the purpose of asp.net hosting environment to do something with routes? It could just create HttpServer, HttpRequestMessage and pass the message to the server. I must be missing something obvious here.
1) When “web hosting”, the HttpServer is created by the ASP.NET pipeline handler and not explicitly by the user’s code. In this case, the HttpServer receives the “global” configuration.
2) The controller is selected by the top-most message handler in the handler pipeline present inside the HttpServer.
Did this help?
Gotcha. I was under a false assumption that it’s asp.net pipeline who maps url to controller/action.
Thanks again. Looking forward to your future posts.
Pingback: KnowYourStack - What is ASP.NET WebAPI
Appreciate this and your previous post! Thanks!
Great article man. I am quite new to asp.net Web API. I have just implemented my first service. Now, i want to move on to address the security concerns. service usage dictates that i don’t have to go and fetch user name and password with each request so i am concerned about what security pattern should i adopt with asp.net Web API.