Saturday, 22 March 2014

Create a Rest Service in MVC 4 Web API

In this article we are going to see what is an Rest API and how we can build the Rest API in MVC Web API. an API  is used to communicate between the applications, normally it is used in call a API for searching a Records using Ajax in web applications, but most of the time it is used to communicate  the developed applications for the Third party developers and customers to share there data. There is already Rest service is present in WCF , now it is present in MVC Web API to create REST  API.

What is a REST API ?

         The REST API is used to develop a service using HTTP Protocol like GET, POST, PUT, DELETE etc.an Http request contains the parameters in the Query string and some in the Body as payload with standard headers, Rest API is used to create a services which can be consumed from various applications running in various devices like desktop, laptop, mobile devices etc.

How to create a Rest API in .Net ?

        In Simple words we have to create a project with API Controller template in MVC. Each and every method in that is mapped to the keyword of the preceding in the method signature like GET, POST, DELETE, PUT etc.  maximum no of parameters can be used is one, which is specify in the WebApiConfig.cs file under the app_start folder. If you want to send many parameters then we have to use the complex objects as a single parameter (or) configure in WebApiConfig.cs file or pass the parameters as query string with the same as parameter.

1. Launch the visual studio and create a new project 
2. Select MVC web application as Template.
3. Then choose the API Controller 

Now you can see a application with default structured.

Expand the App_Start folder under the folder hierarchy you can find the file WebApiConfig.cs which is specify the Routing concepts for the  API controller.

public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{action}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable<T> return type.
            // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
            // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
            //config.EnableQuerySupport();

            // To disable tracing in your application, please comment out or remove the following line of code
            // For more information, refer to: http://www.asp.net/web-api
            config.EnableSystemDiagnosticsTracing();
        }

    }

In the Above code you can see that  "api/{controller}/{action}/{id}" line which i modified from the line "api/{controller}/{id}"  to add the action based call from the user, now user can specify the action name when they call the API instead of default mapping of the method based on routing it is mapped , by checking the existence of routing format in the Routing Table.

Now let we some examples in GET, POST methods in the REST API.

using ESample.Models;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Xml.Linq;

namespace ESample.Controllers
{
    public class SampleController : ApiController
    {

        [HttpGet]
        [ActionName("Send")]
        public string Send(UpdateModel id)
        {
            return string.Format("\"{0}\" : \"{1}\"", id, "name");
        }

       [HttpPost]
        [ActionName("Send")]
        public UpdateModel Add(UpdateModel id)
        {
            id.Name = "Rajesh G";
            return id;
        }


        [HttpPost]
        [ActionName("Test")]
        public HttpResponseMessage Add([FromBody]string data)
        {
            if (!string.IsNullOrEmpty(data))
                return Request.CreateResponse(HttpStatusCode.OK, 
                    Guid.NewGuid().ToString(), "application/json");
            else
                return Request.CreateResponse(HttpStatusCode.BadRequest, "application/json");
        }

        [HttpPost]
        [ActionName("Test2")]
        public HttpResponseMessage Test([FromBody] string data,int id)
        {
            return Request.CreateResponse(HttpStatusCode.OK, 
                    Guid.NewGuid().ToString(), "application/json");
        }


        [NonAction]
        public string Data()
        {
            return "";
        }

    }
}



From the Above code you can see that the three POST Methods and one Get method along with parameter and one non action method which is not REST API method.

HttpPost,HttpGet are the HTTP Methods format by which user can called that particular methods from the API from any device.

 ActionName attribute is used to specify the explicit name for each methods when you want to create a two different action for same method signature based on the HTTP method call then it is very handful to use.

Now we can see one by one methods.

       [HttpGet]
        [ActionName("Send")]
        public string Send(UpdateModel id)
        {
            return string.Format("\"{0}\" : \"{1}\"", id, "name");
        }

       [HttpPost]
        [ActionName("Send")]
        public UpdateModel Add(UpdateModel id)
        {
            id.Name = "Rajesh G";
            return id;
        }


In the Above two methods actual signature is different but we are specify the same action name with different Http method call, i.e if user call a API call of send with GET Request then the First method will trigger, if user calls with POST method then the second method will trigger.

    public class UpdateModel
    {
        public int Id { set; get; }
        public string Name { set; get; }
        public byte[]  Data { set; get; }
    }


We can't pass more than one parameter , so we are creating a complex object to UpdateModel send multiple parameters , if we really needs the multiple parameters then we have to configure in the Route or we have to pass the data as Query string with same name.

 [HttpPost]
        [ActionName("Test")]
        public HttpResponseMessage Add([FromBody]string data)
        {
            if (!string.IsNullOrEmpty(data))
                return Request.CreateResponse(HttpStatusCode.OK, 
                    Guid.NewGuid().ToString(), "application/json");
            else
                return Request.CreateResponse(HttpStatusCode.BadRequest, "application/json");
        }

        [HttpPost]
        [ActionName("Test2")]
        public HttpResponseMessage Test([FromBodystring data,int id)
        {
            return Request.CreateResponse(HttpStatusCode.OK, 
                    Guid.NewGuid().ToString(), "application/json");
        }


HttpResponseMessage  is a response for the request send along with data in json format.

[FromBody] is an attribute to map the value for that parameter from the body, in a method call only one parameter should be FromBody other parameters are should send as query strings


How to call The REST API from the controller. use the HttpClient which is very flexible class to call the HTTP Methods.

Create a Console Application and call the REST SERVICE.

  static void TestAsync()
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://localhost:60133/");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new                                                            MediaTypeWithQualityHeaderValue("application/json"));
                try
                {
                    string jdata = "{\"data\":\"rajesh\",\"id\":\"2\"}";
                    dynamic s = new ExpandoObject();
                    s.data = "1";

                    var d = JsonConvert.SerializeObject(s);
                    var content = new StringContent(d, Encoding.UTF8, "application/json");

                    //   HttpResponseMessage response =                                                               client.PostAsJsonAsync("api/Sample/Test","Rajesh").Result;
                    HttpResponseMessage response = client.PostAsJsonAsync("api/Sample/Test2", content).Result;
#if DEBUG
                    Console.WriteLine(response.StatusCode);
#endif
                    if (response.IsSuccessStatusCode)
                    {
                        string result = response.Content.ReadAsAsync<string>().Result;
                    }
                }
                catch (Exception ex)
                {

                }
            }
        }



        static void RunAsync()
        {
            using (var client = new HttpClient())
            {
                client.BaseAddress = new Uri("http://localhost:60133/");
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                byte[] value = File.ReadAllBytes(@"E:\rajesh\meeting\WP_000692.jpg");
                var data = new UpdateModel() { Id = 2, Name = "Rajesh", Data = value };
                try
                {
                    HttpResponseMessage response = client.PostAsJsonAsync("api/Sample/Send",                                                   data).Result;
                   #if DEBUG
                    Console.WriteLine(response.StatusCode);
                   #endif

                    if (response.IsSuccessStatusCode)
                    {
                        UpdateModel val = response.Content.ReadAsAsync<UpdateModel>().Result;
                        Console.WriteLine(val.Name);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        static void Main(string[] args)
        {
            TestAsync();
            RunAsync();

            Console.Read();

        }

In this POST method create a client object and call the PostAsJsonAsync with API route along with data and get the result as HttpResponseMessage in which you can read the response for the request in Content Parameter by calling the ReadAsAsync method with Type parameter to cast the data of the Result.

response.Content.ReadAsAsync<UpdateModel>().Result;

For call the GET METHOD We can call the service by specify the url itself along with values in the query string. for simple type we can specify the values in the url with the name .

But for the complex object how we can pass the parameters from the query string for this we have to pass the all data in the query string with corresponding parameter name , then how method can map the value with the object for that we have to specify an attribute [FromUri] which can used to map the values for the object from the query string.


        [HttpGet]
        [ActionName("Send")]
        public string Send( [FromUri]UpdateModel id)
        {
            return string.Format("\"{0}\" : \"{1}\"", id, "name");
        }

        [HttpGet]
        [ActionName("GetSimple")]
        public string Send(int name)
        {
            return string.Format("\"{0}\"",name);

        }

Above two Get methods one have simple parameter another with complex one, then call for each Get Method should be like.

For First one Complex Parameter passing the variable in Query string it is automatically mapped with the obejct by using FromUri attribute

              using (var client = new HttpClient())
                    {
                        client.BaseAddress = new Uri("http://localhost:60133/");
                        client.DefaultRequestHeaders.Accept.Clear();
                        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                       var  getresponse  = client.GetAsync("api/Sample/Send?                                                            Id=2&Name=Rajesh");
                        if(getresponse.IsSuccessStatusCode)
                        {
                            var result = getresponse.Content.ReadAsAsync<string>().Result;
                        }

                    }


For the second one simple Get Method

              using (var client = new HttpClient())
                    {
                        client.BaseAddress = new Uri("http://localhost:60133/");
                        client.DefaultRequestHeaders.Accept.Clear();
                        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                     var  getresponse  = client.GetAsync("api/Sample/GetSimple?                                                         name=Rajesh").Result;

                        if(getresponse.IsSuccessStatusCode)
                        {
                            var result = getresponse.Content.ReadAsAsync<string>().Result;
                        }

                    }



From this article I Hope you can learn how to create a REST Service in MVC Web API.



No comments:

Post a Comment