CheapASPNETHostingReview.com | Best and cheap ASP.NET MVC 6 hosting. If you create a new MVC 6 project from the default starter template, it will contain the following code in the Startup class, under ConfigureServices method:
1 2 3 | // Uncomment the following line to add Web API servcies which makes it easier to port Web API 2 controllers. // You need to add Microsoft.AspNet.Mvc.WebApiCompatShim package to project.json // services.AddWebApiConventions(); |
This pretty much explains it all – the Compatibility Shim is included in an external package, Microsoft.AspNet.Mvc.WebApiCompatShim and by default is switched off for new MVC projects. Once added and enabled, you can also have a look at the UseMvc method, under Configure. This is where central Web API routes can be defined:
1 2 3 4 5 6 7 8 9 | app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); // Uncomment the following line to add a route for porting Web API 2 controllers. // routes.MapWebApiRoute("DefaultApi", "api/{controller}/{id?}"); }); |
Inheriting from ApiController
Since the base class for Web API controllers was not Controller but ApiController, the shim introduces a type of the same name into MVC 6.
While it is obviously not 100% identical to the ApiController from Web API, it contains the majority of public proeprties and methods that you might have gotten used to – the Request property, the User property or a bunch of IHttpActionResult helpers.
Returning HttpResponseMessage
The shim introduces the ability to work with HttpResponseMessage in MVC 6 projects. How is this achieved? First of all, the Microsoft.AspNet.WebApi.Client package is referenced, and that brings in the familiar types – HttpResponseMessage and HttpRequestMessage.
On top of that, an extra formatter is injected into your application – HttpResponseMessageOutputFormatter. This allows you to return HttpResponseMessage from your actions, just like you were used to doing in Web API projects!
How does it work under the hood? Remember, in Web API, returning an instance of HttpResponseMessage bypassed content negotiation and simply forwarded the instance all the way to the hosting layer, which was responsible to convert it to a response that was relevant for a given host.
In the case of MVC 6, the new formatter will grab your HttpResponseMessage and copy its headers and contents onto the Microsoft.AspNet.Http.HttpResponse which is the new abstraction for HTTP response in ASP.NET 5.
As a result such type of an action as the one shown below, is possible in MVC 6, and as a consequence it should be much simpler to migrate your Web API 2 projects.
1 2 3 4 | public HttpResponseMessage Post() { return new HttpResponseMessage(HttpSattusCode.NoContent); } |
Binding HttpRequestMessage
In Web API it was possible to bind HttpRequestMessage in your actions. For example this was easily doable:
1 2 3 4 5 6 7 8 9 10 | [Route("test/{id:int}")] public string Get(int id, HttpRequestMessage req) { return id + " " + req.RequestUri; } [Route("testA")] public async Task<TestItem> Post(HttpRequestMessage req) { return await req.Content.ReadAsAsync<TestItem>(); } |
The shim introduces an HttpRequestMessageModelBinder which allows the same thing to be done under MVC 6. As a result, if you relied on HttpRequestMessage binding in Web API, your code will migrate to MVC 6 fine.
How does it work? The shim will use an intermediary type, HttpRequestMessageFeature, to create an instance of HttpRequestMessage from the ASP.NET 5 HttpContext.
HttpRequestMessage extensions
Since it was very common in the Web API world to use HttpResponseMessage as an action return type, there was a need for a mechanism that allowed easy creation of its instances. This was typically achieved by using the extension methods on the HttpRequestMessage, as they would perform content negotiation for you.
HttpError
If you use/used the CreateErrorResponse method mentioned above, you will end up relying on the HttpError class which is another ghost of the Web API past rejuvenated by the compatibility shim.
HttpError was traditionally used by Web API to serve up error information to the client in a (kind of) standardized way. It contained properties such as ModelState, MessageDetail or StackTrace.
It was used by not just the CreateErrorResponse extension method but also by a bunch of IHttpActionResults – InvalidModelStateResult, ExceptionResult and BadRequestErrorMessageResult. As a result, HttpError is back to facilitate all of these types.