czwartek, 20 czerwca 2013

Creating API with MVC ApiController part 1 (with introducing to MVC design pattern)

Introduction to MVC

In the last few years a software architecture changed very heavily. From desktop (forms) application which were very popular in Windows XP users move to SOA and now completely start using web based solution hosting in a cloud. Of course such evolution is not something bad, just the opposite in my opinion because web based application are highly scalable, better secured and available from each place in the Earth where user has an Internet connection. Such a big changes in software architecture cause that also programming model has to change. As response for this need, IT companies start working for on new technologies and improving existing ones. APIs became very popular tool  in a developer hands and whole communication became much more lightweight (by switching from XML to JSON) - mainly because the emerging market of mobile devices.

In a new MVC version 4 also Microsoft introduce some improvements which allow developers creating web services (APIs) in well known MVC environment - let`s start the with an ApiController.

Many of ASP.NET developers are familiar with MVC  pattern because it`s very popular and also very easy to understand. The key thing/process (Picture 1.) which need to be understand is that based on URL an controller process user request and fill a model properties (optional) and then generate a view (with model data). After rendering HTML (view) its time for user interaction which will be finish when user send new request (synchronous or asynchronous) to the server - such request will be handle by a proper controller.To understand how URL address is translated into controller action please take a look here. Let`s take a look  at he each component general definition:
  • A Model  - represents the underlying, logical structure of data in a software application and the high-level class associated with it. This object model doesn`t contain any information about the user interface and also doesn`t contains any business logic.
  • A View - is a collection of HTML tags representing the elements in the user interface.
  • A Controller - represents the classes connecting the model and the view, and is used to communicate between classes in the model and view.


Picture 1. General schema o MVC pattern model.
MVC design pattern looks very easy, don`t you think? So why not extend this website technology to handle API for any kind of solution. To achieve this goal first of all we need to create a simple MVC project.First of all open Visual Studio 2012 and add new project of type ASP.NET MVC 4 Application (type some details like project name) and then select Basic application (Picture 2.).

Picture 2. Choosing proper MVC project template for API.
After creating a new project we should top for a while to understand project architecture (Picture 3.) which in details becomes from MVC architecture. There is a few folder which need to be described:
  • App_Start: store files with classes which logic will be executed on application start (not for session start). The file which is the most important from API creation point of view is WebApiConfig.cs .  Inside it, in Register function default configuration for routing exists. By default all our API calls will be located at URL template like http://website_address/api/controller_name/optional_id for example http://foo.com/api/user/1 will return details  for user with ID = 1 if we send a GET request.
Code Snippet
  1. public static void Register(HttpConfiguration config)
  2.      {
  3.          config.Routes.MapHttpRoute(
  4.              name: "DefaultApi",
  5.              routeTemplate: "api/{controller}/{id}",
  6.              defaults: new { id = RouteParameter.Optional }
  7.          );
  8.      }


  • Controllers: stores files with all controllers in the project. It`s very important to be familiar with controllers naming convention. By default controller name consist with two parts: prefix and 'Controller' sufix and in the URL we pass only prefix name (case insensitive). So if our controller has name like UserContoller we should use  api/user/  instead api/usercontroller/ in request URL.
  • Models: this folder stores inforrmation about custom classes which will be used for passing data to the views.
  • Views: stores all views but in pure API approach are useless.

Picture 3. Default project architecture.

Creating first RESTfull service

Now, we are more or less familiar with the project structure now we are on good way to start creating our REST API. First thing in all process is adding a new Controller (Picture 4.) to our project - it can be done by selecting Add -> Controllers and in new windows selecting ''API controller with empty read/write actions".

Picture 4. Adding new ApiController to Controllers folder.

By default a new empty controller is a simple class which derives from ApiContoller base class. Inside this class we create several test functions, which manipulate on simple generic Dictionary<string,string>, as follow:

  • Dictionary<stringstring> Get(): [HttpGet] returns whole dictionary from fake DB context.
  • string Get(string id): [HttpGet] returns single value basen on dictionary key.
  • void Post(string id, string value):[HttpPost] create a new key-value pair.
  • void Put(string id, string value): [HttpPut] updates existing key-value pair.
  • void Delete(string id): [HttpDelete] removes existing key-value pair based on a key.

Code Snippet
  1. /// <summary>
  2.   /// Unsecured, very simple API for manipulating directory.
  3.   /// </summary>
  4.   public class SimpleController : ApiController
  5.   {
  6.       // GET api/simple
  7.       public Dictionary<string, string> Get()
  8.       {
  9.           return FakeDbContext.Instance.Dictionary;
  10.       }
  11.  
  12.       // GET api/simple/5
  13.       public string Get(string id)
  14.       {
  15.           return FakeDbContext.Instance.Dictionary.FirstOrDefault(c => c.Key == id).Value;
  16.       }
  17.  
  18.       // POST http://localhost:38828/api/simple?id=1&value=5
  19.       public void Post(string id, string value)
  20.       {
  21.           FakeDbContext.Instance.Dictionary.Add(id, value);
  22.       }
  23.  
  24.       // PUT api/simple?id=1&value=5
  25.       public void Put(string id, string value)
  26.       {
  27.           FakeDbContext.Instance.Dictionary.Remove(id);
  28.           FakeDbContext.Instance.Dictionary.Add(id, value);
  29.       }
  30.  
  31.       // DELETE api/simple/5
  32.       public void Delete(string id)
  33.       {
  34.           FakeDbContext.Instance.Dictionary.Remove(id);
  35.       }
  36.   }

As you can see in this example I have non descriptive function name (Get, Post, etc.). I decide to do that to show you easy you can create own API service. One thing you need to be aware of is HTTP method which you are using to send a request - and there is only a few in common usage. Those methods are automatically mapped to the function name as I presented in the example, above but in a real world scenario you need to create much more descriptive function names. However if we change default function names we need to 'show' framework which method is suitable to handle specific type of method. We can do that by specifying one of the following function attributes:
Now it`s worth to test out solution - this is very easy and all you need to do is run the solution and send request using one of the HTTP methods to following URL template:
{Method}  http://{local_address}:{local_port}/api/simple
for example

POST http://localhost:38828/api/simple?id=1&value=5

If someone of you is not familiar with sending HTTP requests by using other than GET (you send a GET request when you type some URL  into browser address window) I can recommend very easy in use HTTP client (extension for Chrome) called Postman.

One more interesting thing is, as we can see on example presented below (Picture 3.), we are also able to modify result format just by manipulating value of the Accept header parameter. By passing response Accept header with value application/xml  or application/json we are changing whole response format.


Picture 3. Testing simple API with results formatted as XML and JSON.
Whole source code of the project is available here.

Thank you.