Skip to main content

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.

Popular posts from this blog

Full-Text Search with PDF in Microsoft SQL Server

Last week I get interesting task to develop. The task was to search input text in PDF file stored in database as FileStream. The task implementation took me some time so I decided to share it with other developers. Here we are going to use SQL Server 2008 R2 (x64 Developers Edition), external driver from Adobe, Full-Text Search technology and FileStream technology.Because this sems a little bit comlicated let`s make this topic clear and do it step by step. 1) Enable FileStream - this part is pretty easy, just check wheter You already have enabled filestream on Your SQL Server instance - if no simply enable it as in the picture below. Picture 1. Enable filestream in SQL Server instance. 2) Create SQL table to store files  - mainly ther will be PDF file stored but some others is also be allright. Out table DocumentFile will be created in dbo schema and contain one column primary key with default value as sequential GUID. Important this is out table contains FileSt...

Persisting Enum in database with Entity Framework

Problem statement We all want to write clean code and follow best coding practices. This all engineers 'North Star' goal which in many cases can not be easily achievable because of many potential difficulties with converting our ideas/good practices into working solutions.  One of an example I recently came across was about using ASP.NET Core and Entity Framework 5 to store Enum values in a relational database (like Azure SQL). Why is this a problem you might ask... and my answer here is that you want to work with Enum types in your code but persist an integer in your databases. You can think about in that way. Why we use data types at all when everything could be just a string which is getting converted into a desirable type when needed. This 'all-string' approach is of course a huge anti-pattern and a bad practice for many reasons with few being: degraded performance, increased storage space, increased code duplication.  Pre-requirements 1. Status enum type definition...

Using Newtonsoft serializer in CosmosDB client

Problem In some scenarios engineers might want to use a custom JSON serializer for documents stored in CosmosDB.  Solution In CosmosDBV3 .NET Core API, when creating an instance of  CosmosClient one of optional setting in  CosmosClientOptions is to specify an instance of a Serializer . This serializer must be JSON based and be of  CosmosSerializer type. This means that if a custom serializer is needed this should inherit from CosmosSerializer abstract class and override its two methods for serializing and deserializing of an object. The challenge is that both methods from  CosmosSerializer are stream based and therefore might be not as easy to implement as engineers used to assume - still not super complex.  For demonstration purpose as or my custom serializer I'm going to use Netwonsoft.JSON library. Firstly a new type is needed and this must inherit from  CosmosSerializer.  using  Microsoft.Azure.Cosmos; using  Newtonsoft.Json; usin...