Contents
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).
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).
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
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:
RestClient restClient = new RestClient("url");
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.
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.
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.
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).
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'.
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.
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
It will install RestSharp current version for your project consumewebapi
.
- 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).
- 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);
}
- Add new class under Helper folder and named it as
ServerDataRestClient
and implement interface IServerDataRestClient
:
public class ServerDataRestClient : IServerDataRestClient
{
}
We need to create a RestClient
, create a variable private readonly RestClient _client;
in the class and initialize the same in the constructor.
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.
private readonly string _url = ConfigurationManager.AppSettings["webapibaseurl"];
Now, we required a request it is nothing but contains a resource and a 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.
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.
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);
}
}
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; }
}
Here are some points we should notice in our model
class:
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; }
- Here, we are using Data annotations.
- We set
ApplyFormatInEditMode = true
so, during edit mode, user shouldn't forget to supply the required format.
- Our date fields should contain
calendar
control on the browsers which obeys HTML5 rules.
IP
should be formatted in the actual IP format (to avoid entering unwanted string
s).
[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; }
- Here, we used
RegularExpression
, the app will throw an error if it doesn't match.
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; }
- If expression does not match, it will throw an error message.
Record identifier
should be between 0-9.
- If expression does not match, it will throw an error message.
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).
- Under Solution Explorer, right click on Controllers folder and click Controller.
- From Add controller dialog, enter Controller name
ServerDataController
and select MVC controller with empty read/write actions from Template dropdown, click on 'Add'.
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.
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.
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'.
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:
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:
- 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.
- 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