Using MS WebAPI to add API Support to Your Existing ASP.NET MVC Web Applications

Posted by: Sumit Maitra , on 2/28/2012, in Category ASP.NET MVC
Views: 119849
Abstract: In this article, we will see what it takes to use the newly launched WebAPI in an existing MVC 3 application by upgrading it to ASP.NET MVC 4 and extending it to provide http services using the WebAPI

Microsoft Recently released ASP.NET MVC 4 beta. However the Beta comes with a go live license, meaning you can use it in production systems. There are various articles on it starting with Scott Gu’s introduction to Scott Hanselman’s primer, describing all the features of MVC 4. In short, it’s a gold mine of new features and we could go on an on with them. But instead of talking about all the features, we are going to go piecemeal and take one feature at a time and approach it from various angles.

Today, we will see what it takes to use the newly launched WebAPI in an existing MVC 3 application by upgrading it to MVC 4 and extending it to provide http services using the WebAPI. (If you want to look at the WebAPI sample only you can jump here)

 

What is WebAPI

The WebAPI framework provides quite a few things making web based services development smoother. Its major claim to fame is it’s direct support for HTTP Verbs (GET, PUT, POST, DELETE) that helps you implement services directly over HTTP. This greatly opens up the different types of clients that can use your services. Let me clarify with an example:

Today a web solution is difficult to imagine without supporting multitude of clients apart from the browser. It could be a Windows client application; it definitely could be a mobile application, which could in turn be built on multiple platforms (WP7, iOS, Android, Blackberry etc. etc.) and with the popularity of Macs, who knows you even might want to support OSX clients. Previously the way to do it would be to implement XML SOAP based web services. XML Web Services though great (and better than proprietary RPC services), it always had a ‘bolt on’ feel with all the overhead involved to set Web Services to work on HTTP. In short, putting up web services was a non-trivial amount of work.

The WebAPI framework aims to simplify this, by providing easy mapping of HTTP verbs to services for your applications. So practically any client that supports HTTP can avail of your applications services. All they need to know is the correct HTTP URL.

Apart from supporting HTTP verbs directly, it supports HTTP content negotiation, support for cross cutting concerns (ala Action Filters in MVC) and self-hosting (meaning no compulsion of IIS/ASP.NET dependency).

A very good starting point for learning more is the official ASP.NET Web-API Site. We will go ahead now and see how to add WebAPI based service support to an existing MVC web application.

Update: Also see how the same WebAPI can be consumed from a Windows and WinRT Client Application

Installing ASP.NET MVC4

To start off with, you will need MVC4 Beta. You can install it from here. Remember it’s still a beta. So make sure you have a decent ‘rollback’ option (Windows Restore Point or VMWare Snapshot or your favorite backup strategy). However it does not ‘upgrade’/’overwrite’ MVC3, it installs side-by-side so you have both MVC3 and the MVC4 Beta.

Once the installer completes, reboot if required and we are all set.

Upgrading an existing MVC3 Application

We take our FunWithSignalRDI project from the Dependency Injection Article and ‘upgrade’ it. Upgrade path is not automatic, so we will do it manually, which basically means create a new project and add the existing files.

Note 1: Reading the previous article is not compulsory if you are okay with generic DI concepts and understand what Composition Root means.

Note 2: I picked the example because keeping DI in the mix helps demonstrate an additional WebAPI feature. Also SignalR is not the topic of discussion in this article today, though I expect that functionality to continue working.

Step 1: Open the FunWithSignalDI.sln

Step 2: Add a new Project, select ASP.NET MVC 4

adding-new-mvc4-web-project

Step 3: Select the Web API template

new-web-api-project-template

The new project looks very similar to an existing MVC 3 boilerplate, except for an additional controller called ValuesController. When we open the ValuesController class we see this class inherits from the new ApiController instead of the MVC Controller class.

Step 4: Copy the HomeController and BlogPostController from the RaBlog project to RaBlog.Web project.

Step 5: Next Copy the BlogPost folder from Views of the existing project to the new project.

Step 6: Copy the BlogControllerFactory and CompositionRoot classes

Step 7: Hook up the ControllerFactory in Global.asax

initial-application-start-changes

Step 8: Right Click on the solution and Select ‘Manage NuGet Packages for the Solution’. Lookup up the SignalR dependency and click on ‘Manage’.

Step 9: Select the FunWithSignalRDI.Web project so that the SignalR dependencies get added to the new project as well.

add-signalr-dependency

Step 10: Copy the diff_patch_match.js from the scripts folder, and the SignalR folder with the BlogHub class to the new Web project so that the SignalR sample continues to work

Step 11: Add reference to the RaBlog.Domain project. Copy the ‘BlogPostRepositoryType’ AppSetting and the ‘FunWithSignalR’ connection string from the original Web.Config to the new Web.Config.

web-config-setup

Step 12: Copy the Post-Build event from the FunWithSignalR project to the FunWithSignalR.Web project. This ensures the Data dll is available at runtime.

update-post-build-event

That should be it. Build and Run. The SignalR app is now using MVC 4!

Adding WebAPI Support to our MVC Application

The Web Api project template already added a default ValuesController. Now let’s say we want to develop our WebAPI to enable end clients List, Read and Update Posts into our app. This would be for developers who want to create third part client apps.

Step 1: We will rename the ApiController to DevController. As a result our WebAPI methods will be available at

http://<server>:<port>/api/dev/

Based on whether you are using, the GET, POST or PUT verb appropriate methods will be called.

Step 2: Add a constructor that takes a single parameter of type IBlogPostRepository and save it locally

Step 3: Implement the Get(), Get(id), Post(…) and Put(…) methods as follows.

dev-controller

For the Post, Put and Delete methods we have a return type of HttpResponseMessage. Each of the responses has appropriate HTTP statuses so that the calling client can easily identify the outcome of the action. No special parsing required. As we can see above we don’t want users to be able to Delete any of our posts using the API so we are sending back status code Forbidden (HTTP status code 403) telling users they cannot Delete using this API.

The Get method returns a Generic HttpResponseMessage<T> where T is the type of object you want to return. In the above implementation we have checked if the id being passed fetches us some value, if yes, we send HTTP status code 200 (Ok), if not we send back HTTP status code 404 (Not Found).

Step 4: With the ApiController setup we could run the application but on trying to access the Api we would get an error. Any guesses? Yes, just like MVC’s default controller factory, WebAPI by default, doesn’t accept controllers with parameterized constructors. As a result we will need to leverage WebAPI’s extensibility framework to inject our repository into the DevController.

WebAPI Extensibility and Dependency Resolution

The WebAPI team thought through most of the scenarios in which it would be used in and one of the most common ways to do it would be in DI scenarios where either we could be using an IoC container or use our hand built CompositionRoot. Enter the built in Service Locator aka GlobalConfiguration.Configuration.ServicerResolver and the SystemWeb.Http.Services.IDependencyResolver.

The ServiceResolver class is an implementation of the Service Locator pattern whose sole aim is to find dependent services. In our case we can use the SetResolver method and pass an Instance of a class that implements IDependencyResolver.

The WebApiDependencyResolver

- We add a class WebApiDependencyResolver to the FunWithSignalRDI.Web application and implement it as follows:

web-api-dependency-resolver

- IDependency Resolver has two methods, GetService and GetServices both of which pass the serviceType it is looking for.

- We pass the repository instance via the constructor.

- In the GetService method we check if the type the service locator is looking for is DevController and if it is, instantiate it using the repository and return it. If not, return null so that the Service Locator can continue looking for that type in other registered service providers.

- The GetServices method just returns a default list of objects.

Updating the CompositionRoot

We have the WebApiDependencyResolver, but going by our DI principles we shouldn’t be ‘new-ing’ it up randomly. We would like the CompositionRoot class doing the creation for us. So we update the CompositionRoot class as follows:

changes-to-composition-root

- We declare a second readonly variable for the dependency resolver.

- We split the repository instantiation and the dependency instantiation.

- The InitializeRepository() method returns us the instance of IBlogRepository implementation. It uses the BlogRepositoryType app setting to get the Type name and then generate it using Reflection.

- We then instantiate the BlogControllerFactory and the WebApiDependencyResolver using the repository object.

Hooking up the Dependency Resolver

The dependency resolver only needs to be hooked up when the application starts. So we update the Global.asax as follows:

register-dependencies-in-global-asax

- We add a method RegisterDependencies() and instantiate the CompositionRoot.

- Call ServiceResolver.SetResolver(…) method with instance of the DependencyResolver from CompositionRoot.

- Similarly set the MVC ControllerFactory using the ControllerFactory from the CompositionRoot.

- Call RegisterDependencies() from Application_Start()

This completes our implementation and we can now expect WebAPI framework to do it’s magic when we hit the URLs of our application.

To try it out

- Launch the application and create a couple of posts

new-posts

- Now Hit F12 to bring up the Developer Tools in IE or any of your favorite Browser Dev tool. For IE, go to the Network Tab and click Start Capturing

- Type this URL in the browser window http://localhost:<port number>/api/dev. IE’s ‘download bar’ will come up at the bottom of the screen. Click on the ‘Go To Detailed View’ button. Select the Response Body. You will see the JSON equivalent of the posts, that looking something like the follows:

web-api-response-body

- By default our browsers do a http GET when we hit a URL and since there were no further parameters WebAPI mapped it to the Get method call without parameters that gets all the Posts available

- To get a particular Post append /<id> to the above URL like the following

web-api-get-by-id

- So there you have it, we just used WebAPI to expose our little application’s Create, Read, Update and List functionalities, while preventing people from calling Delete. Now we can go ahead and create any type of client that can do HTTP Get/Post/Put etc. and manipulate content in our web app.

Conclusion

In Web 2.0 public facing web apps are ever increasingly interconnected through web-based services. The WebAPI now enables ASP.NET applications to provide a cross platform lightweight framework that help developers easily setup such services.

In an enterprise world, inter-app communication just got a whole lot easier.

This concludes our introductory article for ASP.NET MVC4 Beta covering some features of the WebAPI. We will be following up with more discovering more features as we go.

The entire source code of this article can be downloaded over here

Give a +1 to this article if you think it was well written. Thanks!
Recommended Articles
Sumit is a .NET consultant and has been working on Microsoft Technologies since his college days. He edits, he codes and he manages content when at work. C# is his first love, but he is often seen flirting with Java and Objective C. You can follow him on twitter at @sumitkm or email him at sumitkm [at] gmail


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by Syed on Wednesday, February 29, 2012 8:32 AM
It is really a great article with right amount of details. Why you need to declare BlogPost in two places FunWithSignalR.Data.Model.BlogPost and FunWithSignalR.Domain.Model.BlogPost? What are drawback if you refer FunWithSignalR.Data.Model.BlogPost in your data layer, e.g when using ORM (NHibernate)? These questions are to clear myself:)
Comment posted by Sumit on Wednesday, February 29, 2012 12:25 PM
@Syed,
If you got a chance to check out the Dependency Injection article I wrote earlier, I explained why we have a Domain object apart from a Data object.
Basically, using the data object in your Business layer and UI layer would mean strongly coupling your entire application to the existing data layer. So in future, changing data access would mean touching all parts of the application.
So keeping OR/M entities out of Business and UI layers help in decoupling an application.
In this example of course it's a purely academic exercise.
Comment posted by vsdev on Friday, March 2, 2012 11:52 PM
Thanks for this fantastic article. Have you tried this with SSL? The soln gives a nasty error when used with HttpConfiguration.
Comment posted by Sumit on Saturday, March 3, 2012 1:21 PM
@vsdev I have not tried it with SSL yet. I'll set it up on SSL and see what updates are required for it. Thanks for pointing it out.

In General:
The only change required in the Solution (for non-ssl) is updating the SQL Server connection. I have SQLEXPRESS installed as SQLEXPRESSR2 so just that change should work.
Comment posted by Sumit on Saturday, March 3, 2012 2:19 PM
@vsdev I enabled SSL in Visual Studio and ran it using IIS Express, I did not get any exceptions. Can you expand on the details of the exception you are getting? Maybe a stack trace?

Thanks.
Comment posted by vsdev on Saturday, March 3, 2012 8:10 PM
Thanks for your help. Nailed it - http://forums.asp.net/t/1776070.aspx/1?SSL+and+Web+API
Comment posted by Sumit on Monday, March 5, 2012 3:48 AM
Note for all readers: If you want to try out the Web API I have put the application live at http://apps.sumitmaitra.com/funwithsignalr/. The WebAPI is available at http://apps.sumitmaitra.com/funwithsignalr/api/dev
Comment posted by Kasim on Monday, March 12, 2012 2:51 PM
the article is much more difficult to understand and follow than it supposed to be.
Comment posted by Sumit on Tuesday, March 13, 2012 2:32 AM
@Kasim concern duly noted. Can you suggest the parts where I may trim things down? Was migration + WebAPI the problem? Would it be better to just do a WebAPI only article?
Comment posted by dfdf on Sunday, March 25, 2012 1:46 PM
fdfdf
Comment posted by Rahul rana on Monday, September 17, 2012 6:43 AM
Best article

thanks
Comment posted by cv writing help on Saturday, September 22, 2012 11:58 PM
Can you suggest the parts where I may trim things down? Was migration + WebAPI the problem? Would it be better to just do a WebAPI only article?

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel