Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Consuming ASP.NET WEB API using ASP.NET MVC4 and RestSharp

0.00/5 (No votes)
6 Oct 2014 4  
In this article, we will learn how to consume ASP.NET WEB API hosted on another server (as a REST services only) using ASP.NET MVC4 (as a client) with RESTSHARP.

Snapshot of demo project

Contents

Introduction

In most scenarios, we develop an application of ASP.NET MVC4 using ASP.NET WEB API. But as a RESTFul service like ASP.NET WEB API, we meant to use by different clients. In this article, we will see how to consume simple ASP.NET WEB API using ASP.NET MVC4 (as a client) with RestSharp (simple Rest and HTTP client for .NET).

Background

Before going through this article, I recommend you read my earlier article, where I defined how to create an ASP.NET WEB API (Crud Operations using Fluent NHibernate).

Pre-requisite

To implement and play with the source code, one should have:

  • Visual Studio 2013 express or later
  • ASP.NET MVC4 or later
  • ASP.NET WEB API2 or later
  • Basic knowledge of RestFul Services
  • Basic knowledge of ASP.NET WEB API
  • Basic knowledge of ASP.NET MVC4 or later

Why RestSharp?

As we are going to use RestSharp to call our ASP.NET WEB API URIs, so, first of all, let's discuss "RestSharp". This is nothing but a Simple REST and HTTP API Client for .NET. It provides us with a simple way by which we can just initialize a RestClient, pass a Request, define a Method (GET, POST, PUT, DELETE) and get a response.

Following are commonly used snippets:

//Create a restclient
RestClient restClient = new RestClient("url");

//Create request with GET
var request = new RestRequest("api/serverdata", Method.GET);
  • Do not forget to provide RequestFormat and RestSharp automatically serialize/deserialize complex objects like Models like ServerDataModel in our demo project.
    //Do not forget while using complex types
    var request = new RestRequest("api/serverdata", Method.GET)
     {RequestFormat = DataFormat.Json};
  • Get formatted result for complex types:
    var response = restClient.Execute<List<ServerDataModel>>(request);

There are many more features that we are not covering in this article. Please refer to RestSharp Wiki.

What Are We Going to Consume?

As mentioned earlier, in this article, we will consume an existing ASP.NET WEB API URIs (hosted on server), below is the table mentioning all URIs:

Action HTTP method Relative URI
Get a list of serverdata GET /api/serverdata
Get a serverdata by ID GET /api/serverdata/id
Get serverdata by datatype GET /api/serverdata/type/datatype
Get serverdata by machine IP GET /api/serverdata/ip/ip
Create a fresh serverdata POST /api/serverdata
Update an existing serverdata PUT /api/serverdata/id
Delete an existing serverdata DELETE /api/serverdata/id

Refer to the demo app: Demo ASP.NET WEB API.

Create the Web Project

Let's start creation of our new ASP.NET project (client project) by following the below mentioned step(s):

Start Visual Studio and select File->New->Project (or enter Ctrl + Shift + N).

Create new asp.net mvc4 web project

In the Templates dialog, select Installed Templates and then expand the Visual C# node. Under Visual C#, select Web. In the list of project templates, select ASP.NET MVC4 Web Application, name the project and click 'ok'.

I named my project as consumewebapi, you can choose whatever you want. :)

From Project Template, select Internet Application and Razor from View Engine dropdown list and click 'ok'.

Select new project template of asp.net mvc4

You can also check Create unit test project checkbox, if are doing Test driven development and I highly recommend the same. In this article, we are not covering this part.

Now, after the above step(s), we have default ASP.NET MVC4 project template with us, later on we will add our stuff.

Default folder structure of asp.net mvc4 project template

Add RestSharp Support to Project

We are going to use RestSharp to consume our ASP.NET WEB API, follow these steps:

Goto Tools->NuGet Package Manager->Package Manager Console.

From Package Manager Console, run the following command:

Install-Package RestSharp

Install restsharp from nuget command line

It will install RestSharp current version for your project consumewebapi.

Add Rest Client

  1. From Solution Explorer, create a new folder and named it Helper - this folder will contain all our helper classes required for RestSharp client (these classes will play an interface between our client and services).
  2. Add an interface and name it IServerDataRestClient.

    Complete code of IServerDataRestClient looks like:

    public interface IServerDataRestClient
    {
        void Add(ServerDataModel serverDataModel);
        void Delete(int id);
        IEnumerable<serverdatamodel> GetAll();
        ServerDataModel GetById(int id);
        ServerDataModel GetByIP(int ip);
        ServerDataModel GetByType(int type);
        void Update(ServerDataModel serverDataModel);
    }
  3. Add new class under Helper folder and named it as ServerDataRestClient and implement interface IServerDataRestClient:
    public class ServerDataRestClient : IServerDataRestClient
    {
     //implementation
    }

We need to create a RestClient, create a variable private readonly RestClient _client; in the class and initialize the same in the constructor.

//initializing RestClient
public ServerDataRestClient()
{
 _client = new RestClient(_url);
}

In the above, while we are initializing RestClient object, we are providing BaseUrl nothing just a complete name of url like http://myexample.com/.

We can also do this:

_client = new RestClient {BaseUrl = _url};

We are fetching base URL from our config files, why it is in config files. It is recommended for large projects where we have different environments like Dev, Staging,QA, Prod, etc.

//getting base url from config
private readonly string _url = ConfigurationManager.AppSettings["webapibaseurl"];

Now, we required a request it is nothing but contains a resource and a method.

Resource and Method

By providing {RequestFormat = DataFormat.Json}; we are telling RestClient to provide us an output in the form of Json. This is required while you are working with complex classes, like here we are using ServerDataModel class.

In DEBUG mode, check _client in Quick watch (Ctrl + D,Q), you will find all the things we set while creating our RestClient object.

Internal of RestClient

Our client is ready to convey our request and get the response.

var response = _client.Execute<List<ServerDataModel>>(request);

The above will give us the output in a list of our ServerDataModel class.

Open Quick watch for response, you will get two nodes [RestSharp.RestResponse<System.Collections.Generic.List<ConsumeWebAPI.Models.ServerDataModel>>] {RestSharp.RestResponse<System.Collections.Generic.List<ConsumeWebAPI.Models.ServerDataModel>>} RestSharp.RestResponse<System.Collections.Generic.List<ConsumeWebAPI.Models.ServerDataModel>> and Data.

Showing internal of Response using RestClient

First node contains our actual content in JSON format with other information, e.g., ContentLength, ContentType, Cookies, ErrorMessage, Header, Request, ResponseStatus, StatusCode, etc.

Data, node contains our formatted data as we requested and required. In our case, it is a list of type ServerDataModel. We will use this model and our view will show later.

We can also request for a specific resource like if we need record by id, then we can do:

var request = new RestRequest("api/serverdata/{id}", Method.GET) {RequestFormat = DataFormat.Json};

request.AddParameter("id", id, ParameterType.UrlSegment);

Below will give us output of type ServerDataModel:

var response = _client.Execute<serverdatamodel>(request);

Here, is our complete ServerDataRestClient helper class:

public class ServerDataRestClient : IServerDataRestClient
    {
        private readonly RestClient _client;
        private readonly string _url = ConfigurationManager.AppSettings["webapibaseurl"];

        public ServerDataRestClient()
        {
            _client = new RestClient {BaseUrl = _url};
        }

        public IEnumerable<serverdatamodel> GetAll()
        {
            var request = new RestRequest
            ("api/serverdata", Method.GET) {RequestFormat = DataFormat.Json};

            var response = _client.Execute<list<serverdatamodel>>(request);

            if (response.Data == null)
                throw new Exception(response.ErrorMessage);

            return response.Data;
        }

        public ServerDataModel GetById(int id)
        {
            var request = new RestRequest
            ("api/serverdata/{id}", Method.GET) {RequestFormat = DataFormat.Json};

            request.AddParameter("id", id, ParameterType.UrlSegment);

            var response = _client.Execute<serverdatamodel>(request);

            if (response.Data == null)
                throw new Exception(response.ErrorMessage);

            return response.Data;
        }

        public ServerDataModel GetByType(int type)
        {
            var request = new RestRequest("api/serverdata/type/{datatype}", Method.GET)
            {
                RequestFormat = DataFormat.Json
            };

            request.AddParameter("datatype", type, ParameterType.UrlSegment);

            var response = _client.Execute<serverdatamodel>(request);

            return response.Data;
        }

        public ServerDataModel GetByIP(int ip)
        {
            var request = new RestRequest
            ("api/serverdata/ip/{ip}", Method.GET) {RequestFormat = DataFormat.Json};
            request.AddParameter("ip", ip, ParameterType.UrlSegment);

            var response = _client.Execute<serverdatamodel>(request);

            return response.Data;
        }

        public void Add(ServerDataModel serverData)
        {
            var request = new RestRequest
            ("api/serverdata", Method.POST) {RequestFormat = DataFormat.Json};
            request.AddBody(serverData);

            var response = _client.Execute<serverdatamodel>(request);

            if (response.StatusCode != HttpStatusCode.Created)
                throw new Exception(response.ErrorMessage);
        }

        public void Update(ServerDataModel serverData)
        {
            var request = new RestRequest
            ("api/serverdata/{id}", Method.PUT) {RequestFormat = DataFormat.Json};
            request.AddParameter("id", serverData.Id, ParameterType.UrlSegment);
            request.AddBody(serverData);

            var response = _client.Execute<serverdatamodel>(request);

            if (response.StatusCode == HttpStatusCode.NotFound)
                throw new Exception(response.ErrorMessage);
        }

        public void Delete(int id)
        {
            var request = new RestRequest("api/serverdata/{id}", Method.DELETE);
            request.AddParameter("id", id, ParameterType.UrlSegment);

            var response = _client.Execute<serverdatamodel>(request);

            if (response.StatusCode == HttpStatusCode.NotFound)
                throw new Exception(response.ErrorMessage);
        }
    }

Create Model Class

Under Solution Explorer, right click on Models folder and Add -> New Item (or hit Ctrl + Shift + A). Choose class and name it ServerDataModel and click 'Add'. It will add an empty Model class.

Here is our complete model class:

public class ServerDataModel
   {
       public int Id { get; set; }
       [Required]
       [Display(Name = "Initial date")]
       [DataType(DataType.Date)]
       [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
       public DateTime InitialDate { get; set; }
       [Required]
       [Display(Name = "End date")]
       [DataType(DataType.Date)]
       [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
       public DateTime EndDate { get; set; }

       [Required]
       [Display(Name = "Order number")]
       public int OrderNumber { get; set; }
       [Required]
       [Display(Name = "Is dirty")]
       public bool IsDirty { get; set; }
       [Required, StringLength(15)]
       [Display(Name = "Data Server IP")]
       [RegularExpression(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)
       {3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$",
       ErrorMessage = "Data Server IP should be in the form of 255.255.255")]
       public string IP { get; set; }

       [Required]
       [Display(Name = "Record data type")]
       [RegularExpression(@"^([1-2])$",
       ErrorMessage = "Record Data Type should be 1 or 2")]
       public int Type { get; set; }

       [Display(Name = "Record identifier")]
       [RegularExpression(@"^([0-9])$",
       ErrorMessage = "Record identifier should be between 0 to 9")]
       public int RecordIdentifier { get; set; }
   }

Describing Model Class

Here are some points we should notice in our model class:

  1. Initial Date and End Date should be of Date type and formatted as MM/dd/yyyy:
    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
    public DateTime InitialDate { get; set; }
    
  2. Here, we are using Data annotations.
  3. We set ApplyFormatInEditMode = true so, during edit mode, user shouldn't forget to supply the required format.
  4. Our date fields should contain calendar control on the browsers which obeys HTML5 rules.

    Rendring Date type fields

  5. IP should be formatted in the actual IP format (to avoid entering unwanted strings).
    [Display(Name = "Data Server IP")]
    [RegularExpression(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.)
    {3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$",
    ErrorMessage = "Data Server IP should be in the form of 255.255.255")]
    public string IP { get; set; }
  6. Here, we used RegularExpression, the app will throw an error if it doesn't match.

    Rendring Date type fields

  7. Record data type should be 1 or 2.
    [Required]
    [Display(Name = "Record data type")]
    [RegularExpression(@"^([1-2])$", ErrorMessage = "Record Data Type should be 1 or 2")]
    public int Type { get; set; }
  8. If expression does not match, it will throw an error message.

    Rendring Date type fields

  9. Record identifier should be between 0-9.
  10. If expression does not match, it will throw an error message.

    Rendring Date type fields

Why All Checks Are At Client Side?

In this article, we are implementing ASP.NET WEB API in our client project which is in ASP.NET MVC4, here we want to make sure that each and every request should be verified and error-free. Three are lot of debates on this approach whether we implement are client-side or at Services-side. In my view, services is the centralized process and it would be calling from multiple clients, so, it's the responsibility of each and every client that incoming request should be verified and error-free (here incoming request does not contain any security logic, here I meant to say only about normal validation data checks).

Create Controller

  1. Under Solution Explorer, right click on Controllers folder and click Controller.

    Add new controller

  2. From Add controller dialog, enter Controller name ServerDataController and select MVC controller with empty read/write actions from Template dropdown, click on 'Add'.

    Add new controller

Describing Controller

Our ServerDataController is going to consume ASP.NET WEB API using RestSharp (we'll use our helper class, created above).

static readonly IServerDataRestClient RestClient = new ServerDataRestClient();

Above, we simply initialized our ServerDataRestClient.

private IServerDataRestClient _restClient;

public ServerDataController(IServerDataRestClient  restClient)
{
   _restClient = restClient;
}

Above is another flavor, where we need to use inversion of control (IOC).

public ActionResult Index()
{
   return View(RestClient.GetAll());
}

In the above, our Index ActionResult method will get all ServerData records from services and render our view. We need to add views at this point.

Create View

At this point, we need a UI, where we can show output or provide an interface to our user to interact with the application. So, we need to add a view.

The direct/rough way to add a view, from Solution Explorer, add a new folder ServerData and right click on it, then click on Add View.

Add new controller

From Add View dialog, name your view like Index, select Razor as ViewEngine, create strongly typed view and select ServerDataModel as a Model class, I use Scaffold Template of List (you can ignore if do not want to use), use your master layout and click on 'Add'.

Add new view

It will add a new view to project.

@model IEnumerable<consumewebapi.models.serverdatamodel>

@{
    ViewBag.Title = "Manipulate Server Data";
    Layout = "~/Views/Shared/_Layout.cshtml";
}</consumewebapi.models.serverdatamodel>

We did a little bit of manipulation to get the output:

@string.Format(item.IsDirty ? "Yes" : "No")

It will give us Yes or No showing our Record is dirty or not.

Following same step(s) add other views, here is the structure:

Views of project

Executing the Project

Finally, we are done with all of our customizations, changes, now it's time to run our project. Just click run or hit F5. Our Index page will be rendered as:

Get all records

Points of Interest

  1. Ah! ASP.NET MVC4 is not providing direct implementation to use RestSharp. There is a good way to add RestSharp supports to our project and then we can use this awesome framework.
  2. I have created a demo app here, you can use this and adapt the code as a part or whole. I will be glad to hear from you, if you find any issues or other things you need to handle.

History

  • 6th October, 2014: Initial version
  • 13th August, 2015: Source code updated

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here