Consume ASP.NET Core Web API using HttpClient
In the
previous article you learnt to consume a Web API created in ASP.NET Core
using jQuery client. Although local clients are quite common in Ajax rich
applications, many real-world situations require that you call a Web API from a
different application. Thus the client application and the Web API application
are different and you can't use JavaScript to call the Web API (due to default
browser settings). Moreover, if you wish to call a Web API from a desktop
application JavaScript is not an option. In such cases you can use HttpClient to
call the Web API. This article tells you how.
I assume that you have the Web API we developed in the earlier parts of this
series ready with you. Add a new ASP.NET Core project to the same solution and
configure it to use ASP.NET Core MVC. We won't go into the details of that
configuration here since that's the basic step for creating any web application
under ASP.NET Core.
Once you have the new project configured, open Project.json and add the two
dependencies:
"System.Net.Http": "4.3.0-preview1-24530-04",
"Newtonsoft.Json": "9.0.2-beta1"
Notice the System.Net.Http entry. This is a NuGet package that supplies us
the HttpClient component. The Json.Net component comes from the Newtonsoft.Json
NuGet package and does the trick of JSON serialization and deserialization for
us.
Now add a new controller - HomeController - to the project (remember now you
are coding in the client application's project, not the Web API project). The
HomeController will have seven actions as outlined below:
- Index() : Returns a view displaying a list of existing
customers.
- Insert() and Insert(obj) : Handle the insert operation
by adding a new customer.
- Update(id) and Update(obj) : Handle the update
operation by modifying an existing customer.
- ConfirmDelete() and Delete() : Handle delete
confirmation and delete operations by removing a customer.
In the section that follow I won't discuss the views and their markup in
detail. They are quite straightforward and similar to ASP.NET MVC views. Our
main interest is the actions that make use of HttpClient component to call the
Web API.
Displaying a list of customers
The Index view that displays a list of all the customers looks like this:
The Index() action behind this view is shown below:
public ActionResult Index()
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri
("http://localhost:49387");
MediaTypeWithQualityHeaderValue contentType =
new MediaTypeWithQualityHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(contentType);
HttpResponseMessage response = client.GetAsync
("/api/customerservice").Result;
string stringData = response.Content.
ReadAsStringAsync().Result;
List<Customer> data = JsonConvert.DeserializeObject
<List<Customer>>(stringData);
return View(data);
}
}
The Index() action creates a new instance of HttpClient and sets its
BaseAddress and accept header accordingly. Make sure to change the base address
as per your setup. The code then calls the GetAsync() method of HttpClient to
invoke the Get() action of the Web API. Since the content type is set to JSON,
the Web API will its data in JSON format. This data is unpacked from the
HttpResponseMessage object using the ReadAsStringAsync() method. The JSON string
is then deserialized into a List of Customer objects using Json.Net component's
JsonConvert class.
Adding a new customer
The Insert view that allows you to add a new customer is shown below:
The GET and POST versions of the Insert() action are shown below:
public ActionResult Insert()
{
return View();
}
[HttpPost]
public ActionResult Insert(Customer obj)
{
....
string stringData = JsonConvert.
SerializeObject(obj);
var contentData = new StringContent
(stringData, System.Text.Encoding.UTF8,
"application/json");
HttpResponseMessage response = client.PostAsync
("/api/customerservice", contentData).Result;
ViewBag.Message = response.Content.
ReadAsStringAsync().Result;
return View(obj);
....
}
The GET version of Insert() simply returns the Insert view to the browser.
The POST version of Insert() first serializes the Customer object received
through the model binding into a JSON string. This is necessary because we want
to POST data in JSON format. The code then wraps this JSON string into a
StringContent object. Notice that the StringContent constructor sets the
encoding to UTF8 and media type to JSON. The code then calls the PostAsync()
method of HttpClient and submits the JSON data to the Web API using POST verb.
The string message returned by the Web API is unwrapped from HttpResponseMessage
object using its ReadAsStringAsync() method.
Modify a customer
The Update view looks like this:
And the two Update() actions responsible for the relevant functionality are
as shown below:
public ActionResult Update(string id)
{
HttpResponseMessage response =
client.GetAsync("/api/customerservice/" + id).Result;
string stringData = response.Content.
ReadAsStringAsync().Result;
Customer data = JsonConvert.
DeserializeObject<Customer>(stringData);
return View(data);
}
[HttpPost]
public ActionResult Update(Customer obj)
{
string stringData = JsonConvert.SerializeObject(obj);
var contentData = new StringContent(stringData,
System.Text.Encoding.UTF8,"application/json");
HttpResponseMessage response = client.PutAsync
("/api/customerservice/" + obj.CustomerID,
contentData).Result;
ViewBag.Message = response.Content.
ReadAsStringAsync().Result;
return View(obj);
}
The GET version of Update() action invokes Get(id) of Web API using the
GetAsync() method of HttpClient. Notice that this time CustomerID is appended in
the URL. The returned Customer object is unpacked using the ReadAsStringAsync()
method and the stringified JSON is collected in a string variable. This JSON
string is then deserialized into a Customer object using Deserialize() method if
JsonConvert.
The POST version of Update() is quite similar to the POST version of Insert()
we discussed earlier. However, this time we use PutAsync() method by passing the
CustoemrID and the stringified JSON data. The string message is then read using
ReadAsStringAsync() as before.
Deleting a customer
Clicking the Delete links from the Index view takes you to a
confirmation page as shown below:
The ConfirmDelete() action behind this view is shown below:
public ActionResult ConfirmDelete(string id)
{
HttpResponseMessage response =
client.GetAsync("/api/customerservice/" + id).Result;
string stringData = response.
Content.ReadAsStringAsync().Result;
Customer data = JsonConvert.
DeserializeObject<Customer>(stringData);
return View(data);
}
This action is same as the GET version of Update() action.
When you click on the Delete button to delete the selected customer, the page
is POSTed to Delete() action:
[HttpPost]
public ActionResult Delete(string customerid)
{
HttpResponseMessage response =
client.DeleteAsync("/api/customerservice/"
+ customerid).Result;
TempData["Message"] =
response.Content.ReadAsStringAsync().Result;
return RedirectToAction("Index");
}
The Delete() action receives the CustomerID through model binding. Remember
to emit this value on the ConfirmDelete view using a hidden field (or any other
technique of your choice). The code then calls the DeleteAsync() method if the
HttpClient to invoke the Delete() action of Web API. The string message returned
from the Web API is stored in a TempData entry so that it can be outputted on
the Index view.
That's it! This complete the remote client for the Web API. Run the Index
view and test all the CRUD operations.