原文:http://www.codeproject.com/Articles/826359/Consuming-ASP-NET-WEB-API-using-ASP-NET-MVC-and-Re
相关文档:RestSharp====> https://github.com/restsharp/RestSharp/wiki
RestSharp用法小结:http://www.cnblogs.com/Mainz/p/3531243.html
使用RestSharp 库消费Restful Service:http://www.cnblogs.com/shanyou/archive/2012/01/27/RestSharp.html
Contents
- Introduction
- Background
- Pre-requisite
- Why RestSharp?
- What are we going to consume?
- Create the Web Project
- Add RestSharp support to project
- Add Rest client
- Create Model Class
- Describing model class
- Why all checks are at client side?
- Create controller
- Describing controller
- Create view
- Executing the project
- Points of Interest
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
andRestSharp
automatically serialize/deserialize complex objects like Models likeServerDataModel
in our demo project.Hide Copy Code//Do not forget while using complex types var request = new RestRequest("api/serverdata", Method.GET) {RequestFormat = DataFormat.Json};
- Get formatted result for complex types:
Hide Copy Code
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).
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.
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
It will install RestSharp current version for your project consumewebapi
.
Add Rest Client
- 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:Hide Copy Codepublic 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 interfaceIServerDataRestClient
:Hide Copy Codepublic 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.
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 usingServerDataModel
class.
In DEBUG mode, check _client
in Quick watch (Ctrl + D,Q), you will find all the things we set while creating ourRestClient
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 typeServerDataModel
. 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:
Initial Date
andEnd Date
should be ofDate
type and formatted asMM/dd/yyyy
:Hide Copy Code[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 unwantedstring
s).Hide Copy Code[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.Hide Copy Code[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.
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
- 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'.
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 ourview
. 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.
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:
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 hitF5
. Our Index
page will be rendered as:
Points of Interest
- 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.