System.web How to Read the Response From Call

On my previous tutorial called How to Create Web APIs in ASP.NET Core [RESTful pattern] I created a Web API. Now I volition call this API (i.eastward. eat the API) in another project known as client.

What is an API?

API stands for (Application Programming Interface) is an interface which allows multiple applications to communicate with one another. Nosotros utilise multiple APIs daily for getting the current weather update of our expanse on our phone, current stock prices of a company we invested in, then on.

The Operating system (Bone) of our computer constitutes a large number of APIs. For example, on double clicking a folder, the Bone calls a specific API which displays the content of the folder.

The APIs which can be called or accessed by a URL are known every bit Spider web APIs.

What are some API examples?

The most pop API are the ones which the people use daily, 3 of such APIs are:

  • i. Skyscanner which is travel site which lets people inquiry and book travel options for their trips. On their website, when you perform a search, the website calls a agglomeration of external APIs to fetch the current country of flights, hotels, etc. This is then displayed to you on the browser.
  • two. OpenWeatherMap which provides global weather condition data via API.
  • 3. Yahoo Finance provides electric current stock prices and marketplace news.

What is an API call?

We call an API and then that information technology performs the work for which it is designed. When API completes the work it will ship back the status of the completed work, in example of an error the appropriate mistake code and message is returned dorsum.

The question arises is How to call an API? – We tin can call an API past using the appropriate software which is designed to piece of work with the API, example an Operating System, a browser or an APP in your iPhone. If the API has a URL and then this URL can be called with HTTP protocols.

The Web APIs works with methods which are called by HTTP protocols. They are commonly called equally Verbs, Go, PUT, Postal service, and DELETE are the nigh common ones.

Consume (Call) Web API in ASP.Net Core

So create a new empty project past using the ASP.Cyberspace Core Web Application (.NET Core) template, and name the project as APIConsume.

Recall to select the framework as .Cyberspace Core and version as ASP.NET Core v.0. I have shown this in the below image

.NET 5.0 version

Models

Create Models binder in your project root folder and add a form called Reservation.cs to it. The class code is shown below.

using Organisation; using System.Collections.Generic; using System.Linq; using Organization.Threading.Tasks;  namespace APIConsume.Models {     public class Reservation     {         public int Id { get; set; }         public cord Name { go; prepare; }         public string StartLocation { get; prepare; }         public string EndLocation { become; set; }     } }          

This class contains 4 properties for dealing with a reservation object. In a moment I will beginning using it and you volition understand it'southward working clearly.

Bootstrap Package

I will demand Bootstrap package for giving the HTML of the View some proper layout. For this add together this package inside the wwwroot ➤ lib folder. I have written a dissever article o it so do cheque it – How to Install Bootstrap Package in ASP.Net Core Awarding in Visual Studio.

Layout

Create Views folder on the root of the application and create Shared folder within the Views folder.

Side by side inside the Shared folder create _Layout.cshtml file that will contain a common layout for all the Views. The _Layout.cshtml file'due south code is shown beneath.

<!DOCTYPE html>  <html> <head>     <meta proper noun="viewport" content="width=device-width" />     <title>@ViewBag.Championship</title>     <link href="~/lib/twitter-bootstrap/css/bootstrap.css" rel="stylesheet" /> </head> <trunk>     <div course="container-fluid">         @RenderBody()     </div> </body> </html>          

View Imports

Next, create _ViewImports.cshtml file inside the Views folder and apply it to setup the Built-in Tag Helpers and import the Model namespace.

          @using APIConsume.Models @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers        

Startup Grade

Brand sure to add the necessary Configuration for the MVC to work. To do it add together the post-obit code to the Startup.cs grade of your project:

using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting;  namespace APIConsume {     public class Startup     {         public void ConfigureServices(IServiceCollection services)         {             services.AddControllersWithViews();         }          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)         {             if (env.IsDevelopment())             {                 app.UseDeveloperExceptionPage();             }             else             {                 app.UseExceptionHandler("/Domicile/Error");                 // The default HSTS value is 30 days. Y'all may desire to alter this for production scenarios, run across https://aka.ms/aspnetcore-hsts.                 app.UseHsts();             }              app.UseHttpsRedirection();             app.UseStaticFiles();             app.UseRouting();             app.UseAuthorization();              app.UseEndpoints(endpoints =>             {                 endpoints.MapControllerRoute(                     proper name: "default",                     blueprint: "{controller=Home}/{action=Index}/{id?}");             });         }     } }          

Controller

Create Controllers folder on the root of your project and add a controller file called HomeController.cs to information technology. This controller will have action methods to invoke methods of the Web API.

HttpClient to Call API

In order to Swallow the Web API in this project, make sure your Web API project should exist in running style i.e. just press F5 primal in Visual Studio to bring it to running style. I fabricated this Web API project in my previous tutorial and it's link is given on the meridian of this commodity.

To phone call Web API nosotros will be using a very popular HttpClient() class. To Deserialize JSON to Reservation object I will utilise Newtonsoft.Json package. I take shown this package in the below screenshot.

Newtonsoft.Json package

The HttpClient has some very important method to telephone call Web API. These should be noted.

Method Description
GetAsync Send a GET asking to the specified Uri as an asynchronous performance.
PostAsync Send a Mail service asking to the specified Uri as an asynchronous operation.
PutAsync Send a PUT request to the specified Uri as an asynchronous performance.
SendAsync Ship an HTTP request as an asynchronous operation.
PatchAsync Sends a PATCH asking with a cancellation token equally an asynchronous operation.
DeleteAsync Send a DELETE request to the specified Uri as an asynchronous operation.

Now let us bargain with each of these methods i past one.

Read Records from Web API

The Web API has a HttpGet method that returns all reservation records in JSON. This method's code is.

          [HttpGet] public IEnumerable<Reservation> Get() => repository.Reservations;        

To read all these reservation records I accept to brand an HTTP GET Type of Request to this method of the Web API. And then create a new controller inside the Controllers folder and name information technology HomeController.cs. Replace information technology'south Index activity with the following version shown below.

using Organisation.Collections.Generic; using System.Cyberspace.Http; using System.Threading.Tasks; using APIConsume.Models; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json;  namespace APIConsume.Controllers {     public class HomeController : Controller     {         public async Job<IActionResult> Index()         {             List<Reservation> reservationList = new List<Reservation>();             using (var httpClient = new HttpClient())             {                 using (var response = look httpClient.GetAsync("https://localhost:44324/api/Reservation"))                 {                     string apiResponse = await response.Content.ReadAsStringAsync();                     reservationList = JsonConvert.DeserializeObject<Listing<Reservation>>(apiResponse);                 }             }             return View(reservationList);         }     } }          

I used the HttpClient grade of the Organisation.Net.Http namespace to brand an API request. You will notice that the Alphabetize Activeness is an asynchronous blazon that returns a Task. This is considering the HttpClient form makes just asynchronous request which tin just happen from an asynchronous action method.

I fabricated the an HTTP GET request to the API in the line – var response = expect httpClient.GetAsync("https://localhost:44324/api/Reservation"). Notice the URL of the API'due south action is supplied to the GetAsync() method.

The Web API Response i.e. the data returned by the API is fetched from the lawmaking – await response.Content.ReadAsStringAsync(), and stored in the variable called apiResponse.

You already know that the API response is a JSON type of all the Reservation objects. So I can easily Deserialize the JSON to a List type object past using the Newtonsoft.Json package. The Code that does this work is shown beneath.

          reservationList = JsonConvert.DeserializeObject<Listing<Reservation>>(apiResponse);        

Finally the List of Reservation objects which are stored in the variable called reservationList is returned to the View equally the Model.

Now you lot need to create the Index View within the Views ➤ Home folder so every bit to show all the reservations on an HTML tabular array. The Index View lawmaking is given below:

@model IEnumerable<Reservation> @{ Layout = "_Layout"; ViewBag.Championship = "All Reservations";}  <h2>All Reservations</h2> <a asp-activity="AddReservation" grade="btn btn-sm btn-principal">Add Reservation</a> <a asp-action="GetReservation" class="btn btn-sm btn-secondary">Become Reservation</a>  <table class="tabular array tabular array-sm table-striped table-bordered m-2">     <thead>         <tr>             <th>ID</th>             <th>Name</thursday>             <th>Start Location</thursday>             <th>End Location</th>             <th>Update</th>             <th>Delete</th>         </tr>     </thead>     <tbody>         @foreach (var r in Model)         {             <tr>                 <td>@r.Id</td>                 <td>@r.Proper name</td>                 <td>@r.StartLocation</td>                 <td>@r.EndLocation</td>                 <td>                     <a asp-action="UpdateReservation" asp-route-id="@r.Id">                         <img src="/icon/edit.png" />                     </a>                 </td>                 <td>                     <form asp-action="DeleteReservation" method="mail">                         <input type="hidden" value="@r.Id" name="ReservationId" />                         <input blazon="image" src="/icon/close.png" />                     </grade>                 </td>             </tr>         }     </tbody> </table>          

This view is a strongly typed receiving an IEnumerable type as it's model. In that location is a foreach loop to populate a table with all the reservations.

Now run your APIConsume project also brand sure the APIControllers project is running. Y'all volition notice a new browser window opens up and shows all the Reservations that are fetched from the Web API. The paradigm below shows all the Reservations.

all reservations fetched from web api

Ignore the

Add Reservation

and

Get Reservation

links, and the

Update

and

Delete

columns. I will be adding their functionalities in a moment. The edit & delete icons will be provided inside the

wwwroot/icon

folder of the project.

Reading a Reservation Record by it'south Id by calling the Web API

If I send an Id of a Reservation to the Spider web API then the API will send me back the reservation details of that Id. The Web API, which I have already created on my previous tutorial, has a HttpGet method with an id parameter. It's work is to read a records whose id is provided to it. This method's lawmaking is shown below.

          [HttpGet("{id}")] public ActionResult<Reservation> Get(int id) {     if (id == 0)         return BadRequest("Value must be passed in the asking body.");     return Ok(repository[id]); }        

Now I will telephone call this method of the API from my client project. Do you lot remember that in the Index View I have created a link to Get Reservation, now I will add together it's functionality. So go to the Abode Controller and add together a new action called GetReservation to information technology. I have highlighted it'due south lawmaking, see beneath.

using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using APIConsume.Models; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json;  namespace APIConsume.Controllers {     public class HomeController : Controller     {         public async Task<IActionResult> Index()         {             List<Reservation> reservationList = new List<Reservation>();             using (var httpClient = new HttpClient())             {                 using (var response = look httpClient.GetAsync("https://localhost:44324/api/Reservation"))                 {                     cord apiResponse = wait response.Content.ReadAsStringAsync();                     reservationList = JsonConvert.DeserializeObject<List<Reservation>>(apiResponse);                 }             }             return View(reservationList);         }          public ViewResult GetReservation() => View();          [HttpPost]         public async Task<IActionResult> GetReservation(int id)         {             Reservation reservation = new Reservation();             using (var httpClient = new HttpClient())             {                 using (var response = look httpClient.GetAsync("https://localhost:44324/api/Reservation/" + id))                 {                     if (response.StatusCode == System.Net.HttpStatusCode.OK)                     {                         cord apiResponse = expect response.Content.ReadAsStringAsync();                         reservation = JsonConvert.DeserializeObject<Reservation>(apiResponse);                     }                     else                         ViewBag.StatusCode = response.StatusCode;                 }             }             render View(reservation);         }     } }          

I take added ii GetReservation actions – HTTP GET & HTTP POST. The HTTP GET version simply returns the default view while the HTTP Postal service one has the chore to Call the Web API and provide it with the reservation id. The API in turn volition return the reservation details of that id.

The API Call is made by HttpClient class and the response, which is the Reservation object in JSON, is deserialized into the Reservation class object. The Reservation class object is then returned to the default view every bit Model.

Adjacent, add the GetReservation.cshtml view file within the Views ➤ Habitation folder. It's full code is shown below.

@model Reservation @{ Layout = "_Layout"; ViewBag.Title = "Become Reservation past Id";}  <h2>Become Reservation by Id <a asp-activeness="Index" class="btn btn-sm btn-primary">Back</a></h2> <h3>@ViewBag.StatusCode</h3> <grade method="mail">     <div grade="form-group">         <label for="id">Id:</label>         <input grade="form-command" proper noun="id" />     </div>     <div class="text-center console-trunk">         <push button blazon="submit" class="btn btn-sm btn-primary">Become Reservation</button>     </div> </form>  @if (Model != null) {     <h2>Reservation</h2>     <table grade="tabular array table-sm tabular array-striped table-bordered m-two">         <thead>             <tr>                 <th>ID</th>                 <th>Proper name</th>                 <th>Start Location</th>                 <th>End Location</th>             </tr>         </thead>         <tbody>             <tr>                 <td>@Model.Id</td>                 <td>@Model.Name</td>                 <td>@Model.StartLocation</td>                 <td>@Model.EndLocation</td>             </tr>         </tbody>     </table> }          

The view contains a grade, in this form the Reservation Id is added, and on clicking the button the Spider web API request is made.

The expression – @if (Model != cypher) checks if the model is not null. In that case the Model data, which is Reservation information fetched from the API, is shown.

Now run your project and on the chief folio click the Get Reservation link. Add the Id as 3 and click the button. You will see the 3rd Reservation'due south details shown on the view, see the prototype beneath:

3rd reservation from api

Create a Reservation Record past Calling the Spider web API

The Web API has a [HttpPost] method that creates a new reservation. This method is shown below.

          [HttpPost] public Reservation Mail([FromBody] Reservation res) => repository.AddReservation(new Reservation {     Proper name = res.Name,     StartLocation = res.StartLocation,     EndLocation = res.EndLocation });        

To add a new Reservation I take to brand a HTTP Postal service asking to this method of the spider web API. I volition make utilise of the PostAsync() method of the HttpClient class to brand a phone call to this method. So add a new action method called AddReservation to the Home controller as highlighted by the below lawmaking.

using System.Collections.Generic; using System.Cyberspace.Http; using System.Threading.Tasks; using APIConsume.Models; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Organisation.Text;  namespace APIConsume.Controllers {     public class HomeController : Controller     {         // other methods          public ViewResult AddReservation() => View();          [HttpPost]         public async Task<IActionResult> AddReservation(Reservation reservation)         {             Reservation receivedReservation = new Reservation();             using (var httpClient = new HttpClient())             {                 StringContent content = new StringContent(JsonConvert.SerializeObject(reservation), Encoding.UTF8, "application/json");                  using (var response = await httpClient.PostAsync("https://localhost:44324/api/Reservation", content))                 {                     string apiResponse = wait response.Content.ReadAsStringAsync();                     receivedReservation = JsonConvert.DeserializeObject<Reservation>(apiResponse);                 }             }             return View(receivedReservation);         }     } }          

This Web API method needs the new reservation information in JSON format therefore I am serializing the reservation data into JSON and then converting it to a StringContent class blazon. Check the beneath lawmaking.

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

Side by side, this StringContent type object is added to the Web API asking lawmaking by adding it to the 2nd parameter of the PostAsync() method. Check cod below.

          using (var response = await httpClient.PostAsync("https://localhost:44324/api/Reservation", content)) { }        

The Web API method will add the new reservation to it's repository and sends back the newly added reservation object every bit the API Response. This also contains the id of the created reservation.

The Response is Deserialized into the reservation type and in the end is transferred to the View as a model.

Now create the view called AddReservation view within the Views ➤ Home folder with the post-obit code:

@model Reservation @{ Layout = "_Layout"; ViewBag.Title = "Add together a Reservation";}  <h2>Add a Reservation <a asp-activity="Index" class="btn btn-sm btn-secondary">Back</a></h2> <form asp-action="AddReservation" method="post">     <div class="class-group">         <label for="Name">Proper noun:</label>         <input class="grade-command" name="Name" />     </div>     <div grade="class-group">         <label for="StartLocation">Outset Location:</characterization>         <input form="form-control" name="StartLocation" />     </div>     <div grade="class-group">         <label for="EndLocation">End Location:</label>         <input class="form-command" proper noun="EndLocation" />     </div>     <div class="text-heart panel-body">         <button type="submit" class="btn btn-sm btn-primary">Add</button>     </div> </course>  @if (Model != null) {     <h2>Reservation</h2>     <table class="table tabular array-sm table-striped table-bordered m-2">         <thead>             <tr>                 <th>ID</th>                 <thursday>Proper noun</thursday>                 <thursday>Offset Location</th>                 <th>End Location</th>             </tr>         </thead>         <tbody>             <tr>                 <td>@Model.Id</td>                 <td>@Model.Name</td>                 <td>@Model.StartLocation</td>                 <td>@Model.EndLocation</td>             </tr>         </tbody>     </tabular array> }          

The view has a HTML form for calculation a new reservation while information technology's model is of a type Reservation. In one case the API response is received the controller sends information technology to the view as a Model, the view and so checks if the Model is non zip from the code – @if (Model != cipher).

If the model contains the newly created reservation data then it is shown on the HTML tabular array.

Now run your project and go to the add together reservation page whose URL in my case is https://localhost:44334/Home/AddReservation. Fill the form and click the add push button. The reservation will be created and it's details will be shown on a tabular array. Bank check beneath epitome.

creating a new reservation by calling the api

Update a Reservation Records through the Web API

The page that shows all the reservations has an Update Column (a pen icon). If you click on this icon (see the below paradigm) then you can update the corresponding reservation record.

update icon in reservation table

Now I will create the Update Reservation functionality. Do you recall the Web API has a HttpPut method which has a task to update a reservation. See information technology'southward lawmaking below.

          [HttpPut] public Reservation Put([FromForm] Reservation res) => repository.UpdateReservation(res);        

I will now phone call this method of the Spider web API in guild to update any of the previously created reservation. For this add together new actions called UpdateReservation to the

Home controller

whose codes are given below.

using System.Collections.Generic; using System.Internet.Http; using System.Threading.Tasks; using APIConsume.Models; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System.Text;  namespace APIConsume.Controllers {     public course HomeController : Controller     {         // other methods          public async Chore<IActionResult> UpdateReservation(int id)         {             Reservation reservation = new Reservation();             using (var httpClient = new HttpClient())             {                 using (var response = await httpClient.GetAsync("https://localhost:44324/api/Reservation/" + id))                 {                     string apiResponse = look response.Content.ReadAsStringAsync();                     reservation = JsonConvert.DeserializeObject<Reservation>(apiResponse);                 }             }             render View(reservation);         }          [HttpPost]         public async Chore<IActionResult> UpdateReservation(Reservation reservation)         {             Reservation receivedReservation = new Reservation();             using (var httpClient = new HttpClient())             {                 var content = new MultipartFormDataContent();                 content.Add(new StringContent(reservation.Id.ToString()), "Id");                 content.Add together(new StringContent(reservation.Name), "Name");                 content.Add(new StringContent(reservation.StartLocation), "StartLocation");                 content.Add(new StringContent(reservation.EndLocation), "EndLocation");                  using (var response = await httpClient.PutAsync("https://localhost:44324/api/Reservation", content))                 {                     string apiResponse = await response.Content.ReadAsStringAsync();                     ViewBag.Result = "Success";                     receivedReservation = JsonConvert.DeserializeObject<Reservation>(apiResponse);                 }             }             render View(receivedReservation);         }     } }          

The HTTP Go version of the UpdateReservation action just makes a GET blazon of asking to the Spider web API. Information technology provides the API with the Id of a reservation. The API volition send it dorsum the reservation record whose Id was provided to it. The reservation record is and so shown on the default view.

The HTTP Mail service version of this activeness does the Update of the Reservation.

Since the PUT method of the API has [FromForm] attribute in it's statement therefore I am creating a form information by using the MultipartFormDataContent. This class data will be sent to the API as:

var content = new MultipartFormDataContent(); content.Add(new StringContent(reservation.Id.ToString()), "Id"); content.Add(new StringContent(reservation.Name), "Proper name"); content.Add(new StringContent(reservation.StartLocation), "StartLocation"); content.Add(new StringContent(reservation.EndLocation), "EndLocation");          

Notice I am sending the id, name, first location & stop location of the reservation record to be updated in the Form data.

After updating the record the Web API will send back the response which is the updated reservation record, and this is shown on the view.

At present add together the view called UpdateReservation inside the Views ➤ Home binder with the post-obit code:

@model Reservation @{ Layout = "_Layout"; ViewBag.Title = "Update a Reservation";}  <h2>Update a Reservation <a asp-action="Index" grade="btn btn-sm btn-secondary">Back</a></h2> <form method="mail">     <div class="form-group">         <label asp-for="Id"></label>         <input class="class-control" asp-for="Id" readonly />     </div>     <div grade="class-group">         <label asp-for="Proper name"></characterization>         <input class="class-control" asp-for="Name" />     </div>     <div class="form-grouping">         <label asp-for="StartLocation"></label>         <input course="grade-command" asp-for="StartLocation" />     </div>     <div course="form-grouping">         <label asp-for="EndLocation"></label>         <input grade="form-control" asp-for="EndLocation" />     </div>     <div grade="text-center panel-body">         <button type="submit" class="btn btn-sm btn-primary">Update</button>     </div> </grade>  @if (ViewBag.Effect == "Success") {     <h2>Reservation</h2>     <table class="tabular array table-sm table-striped tabular array-bordered m-2">         <thead>             <tr>                 <th>ID</th>                 <th>Proper noun</th>                 <th>Start Location</th>                 <th>Stop Location</th>             </tr>         </thead>         <tbody>             <tr>                 <td>@Model.Id</td>                 <td>@Model.Name</td>                 <td>@Model.StartLocation</td>                 <td>@Model.EndLocation</td>             </tr>         </tbody>     </table> }          

The view has a form where new values of the reservation are put, and on clicking the Update push button the reservation is updated.

The API response is shown within an HTML table which is also provided on the view.

Now it's time to check the update functionality, then run your projection and on the reservation table click on the pen icon confronting any of the reservation.

The reservation will be shown in a class which yous can and then update.

The below image shows that I accept updated the start location to New York and end location to Barcelona of the second reservation record.

update record through api

Update a Reservation Record with "HTTP PATCH" through the Web API

The Web API has a HTTP PATCH method whose task is to update a reservation record. This method is shown below.

          [HttpPatch("{id}")] public StatusCodeResult Patch(int id, [FromBody]JsonPatchDocument<Reservation> patch) {     Reservation res = Become(id).Value;     if (res != nothing)     {         patch.ApplyTo(res);         return Ok();     }     render NotFound(); }        

To invoke this PATCH method of the Spider web API, I volition have to use the HttpRequestMessage course to initialize three properties. These properties are:

  • 1. RequestUri – the URL to brand the PATCH asking.
  • ii. Method – for specifying the HTTP method equally PATCH.
  • 3. Content – to specify the JSON, Encoding and media type.

The

PATCH

method has a wonderful advantage. I don't accept to send all the Reservation fields to it, it but needs the fields that demand to change along with their new values. This makes the PATCH request light weight and more than secure.

The Patch method volition need a JSON sent from the client. This JSON contains the performance to be performed along with fields and their new values. Encounter this JSON format given beneath.

          [     { "op": "replace", "path": "Name", "value": "Ram"},     { "op": "supercede", "path": "StartLocation", "value": "Moscow"} ]        

I take used supersede for the op argument, and this specifies that I will be doing the update for the record. I have also specified the Name and the StartLocation fields will be updated along with their new values.

Now information technology'due south time to Consume this method of the Web API from my client project. And then get to the Dwelling house Controller and add the 2 deportment called UpdateReservationPatch to it. See the beneath code.

using System.Collections.Generic; using Organisation.Internet.Http; using System.Threading.Tasks; using APIConsume.Models; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Arrangement.Text; using System;  namespace APIConsume.Controllers {     public class HomeController : Controller     {         // other methods          public async Job<IActionResult> UpdateReservationPatch(int id)         {             Reservation reservation = new Reservation();             using (var httpClient = new HttpClient())             {                 using (var response = await httpClient.GetAsync("https://localhost:44324/api/Reservation/" + id))                 {                     string apiResponse = expect response.Content.ReadAsStringAsync();                     reservation = JsonConvert.DeserializeObject<Reservation>(apiResponse);                 }             }             return View(reservation);         }          [HttpPost]         public async Chore<IActionResult> UpdateReservationPatch(int id, Reservation reservation)         {             using (var httpClient = new HttpClient())             {                 var asking = new HttpRequestMessage                 {                     RequestUri = new Uri("https://localhost:44324/api/Reservation/" + id),                     Method = new HttpMethod("Patch"),                     Content = new StringContent("[{ \"op\": \"replace\", \"path\": \"Name\", \"value\": \"" + reservation.Proper name + "\"},{ \"op\": \"replace\", \"path\": \"StartLocation\", \"value\": \"" + reservation.StartLocation + "\"}]", Encoding.UTF8, "application/json")                 };                  var response = await httpClient.SendAsync(asking);             }             return RedirectToAction("Alphabetize");         }     } }          

The UpdateReservationPatch has 2 actions – HTTP Get & HTTP POST. The GET action will but fetch the reservation object who's Id it supplied to it. The POST activity will make the PATCH asking.

Note that to make the HTTP PATCH request I will use the SendAsync() method of the HttpClient class. The JSON, which is provided to the StringContent class, contains the new values of the proper name and start location fields and are added past using the reservation.Name and reservation.StartLocation. In the end the activity redirects to the Index View.

Now, add the view called UpdateReservationPatch inside the Views ➤ Abode folder with the following code:

@model Reservation @{ Layout = "_Layout"; ViewBag.Title = "Update a Reservation from PATCH request";}   <h2>Update a Reservation from Patch request<a asp-action="Index" class="btn btn-sm btn-secondary">Back</a></h2> <class method="mail">     <div grade="class-group">         <label asp-for="Proper noun"></characterization>         <input form="course-command" asp-for="Name" />     </div>     <div class="class-group">         <label asp-for="StartLocation"></label>         <input course="grade-command" asp-for="StartLocation" />     </div>     <div class="text-center panel-body">         <button type="submit" class="btn btn-sm btn-main">Update</push button>     </div> </grade>          

The view contains a form where I am but binding the Name and the StartLocation fields so that the user tin can update their values to a new i.

I also need to create a link to the UpdateReservationPatch action from the Index view. I tin can do this thing by changing the asp-activeness attribute given on the Index view from UpdateReservation to UpdateReservationPatch. I accept shown this in the below code.

... <tbody>     @foreach (var r in Model)     {         <tr>             ...             <td>                 <a asp-action="UpdateReservationPatch" asp-route-id="@r.Id">                     <img src="/icon/edit.png" />                 </a>             </td>             ...         </tr>     } ...   </tbody>          

At present it'southward time to test the Patch functionality. So run your project and click any of the update icon against any of the reservation. You will be taken to a new folio where the Proper noun and StartLocation fields will show the values of the reservation which was clicked. Now change the Name and StartLocation field's values and click the Update push button to update the records by PATCH request. Cheque the beneath image.

update reservation patch view

Delete a Reservation past calling the Spider web API

The Web API has a HttpDelete type method that volition delete whatsoever record whose id is provided to it. This method is shown beneath.

          [HttpDelete("{id}")] public void Delete(int id) => repository.DeleteReservation(id);        

From the customer project I will telephone call this method of the API and perform the delete performance. So add a new action method called DeleteReservation to the Home Controller of the customer project. This activeness volition delete a reservation tape by calling the Spider web API's delete method. It'due south code is given below.

using System.Collections.Generic; using Organization.Net.Http; using System.Threading.Tasks; using APIConsume.Models; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using Arrangement.Text; using System;  namespace APIConsume.Controllers {     public class HomeController : Controller     {         // other action          [HttpPost]         public async Task<IActionResult> DeleteReservation(int ReservationId)         {             using (var httpClient = new HttpClient())             {                 using (var response = await httpClient.DeleteAsync("https://localhost:44324/api/Reservation/" + ReservationId))                 {                     string apiResponse = await response.Content.ReadAsStringAsync();                 }             }              return RedirectToAction("Index");         }     } }          

This activeness has an argument called ReservationId which contains the id of the reservation to exist deleted.

The reservation is deleted by making the HTTP DELETE asking to the Web API's method. I used the DeleteAsync method to make this request.

Notice the Delete column on the Index View ( which is a cross icon). If you lot click on this icon then yous can delete the respective reservation record through the API.

delete icon in reservation table

The Index View has a grade which invokes the DeleteReservation action method. Come across beneath code.

<form asp-activeness="DeleteReservation" method="post">     <input type="hidden" value="@r.Id" name="ReservationId" />     <input blazon="image" src="/icon/close.png" /> </form>          

Inside the form there is an image button and a subconscious field which contains the reservation id for the particular tape.

You can delete a reservation past clicking on the cantankerous icon confronting it.

The below images shows the third reservation deleted from the repository:

delete reservation with api

Telephone call Web API with PowerShell

You lot tin can Call Web API with PowerShell in guild to test them. PowerShell makes it easy to create HTTP requests using command line. PowerShell commands can be executed using Visual Studio Package Manager Console, open it from Tools ➤ NuGet Parcel Manager ➤ Package Director Console.

In Package Manager Panel window execute the commands listed below:

PowerShell: HTTP GET Asking to Web API

The PowerShell command for calling HTTP Become method of Web API is:

          PM> Invoke-RestMethod https://localhost:44324/api/reservation -Method GET        

The command will show all the reservations returned from the Spider web API every bit shown past the prototype given beneath:

powershell http get request

The command that makes HTTP Get Request to fetch the 2nd reservation is:

          PM> Invoke-RestMethod https://localhost:44324/api/reservation/2 -Method Become        

It volition show the 2nd reservation. See the below image:

powershell http get request by reservation id

PowerShell: HTTP POST Asking to Web API

To telephone call the HTTP POST method of Web API with PowerShell run the post-obit command:

PM> Invoke-RestMethod https://localhost:44324/api/Reservation -Method POST -Body (@{Proper noun="Jenny"; StartLocation="Moscow"; EndLocation="New Delhi"} | ConvertTo-Json) -ContentType "application/json"          

The command adds a new reservation to the repository.

powershell http post request

The -Body statement specifies the body for the request which is encoded to JSON past using the ConvertTo-Json statement.

The -ContentType argument is used to set the Content-Type header for the asking, which in my case is 'application/json'.

PowerShell: HTTP PUT Request to Web API

The command to make HTTP PUT request with PowerShello is like to the HTTP Postal service command and is given beneath:

PM> Invoke-RestMethod https://localhost:44324/api/Reservation -Method PUT -Torso (@{Id="5"; Proper name="Mary"; StartLocation="Tokyo"; EndLocation="Abu Dhabi"}) -ContentType "awarding/x-www-form-urlencoded"          

Since I have to transport the reservation object in Form Data therefore I accept removed the ConvertTo-Json argument from the command. Also, I have gear up the –ContentType to application/x-www-grade-urlencoded.

Once the control executes the 5th reservation record is updated with values as Mary for proper name, Tokyo for start location and Abu Dhabi for end location.

The beneath paradigm illustrates this:

powershell http put request

PowerShell: HTTP PATCH Request to Web API

Here I am making a HTTP PATCH request with PowerShell to update a reservation record. So in the JSON I will send the op statement with supervene upon value.

The below PATCH command will update the 2nd reservation'south name field to Bob and first location field to San Francisco.

          PM> Invoke-RestMethod https://localhost:44324/api/Reservation/2 -Method PATCH -Body (@{ op="replace"; path="Proper name"; value="Bob"},@{ op="replace"; path="StartLocation";value="San Francisco"} | ConvertTo-Json) -ContentType "application/json"        

The image below illustrates the change made to the 2nd reservation by the command:

powershell http patch request

PowerShell: HTTP DELETE Request to Spider web API

To Powershell command to call DELETE type method of Spider web API is:

          PM> Invoke-RestMethod https://localhost:44324/api/Reservation/iii -Method DELETE        

The higher up command will delete the 3rd reservation by invoking the Spider web API's Delete Action method.

Securing Web APIs by KEYS

Yous do not want to allow Web API'due south access to everyone. Then you volition need to secure Web APIs with Keys. The clients volition take to send the API Keys along with the asking, the keys are checked past the APIs and if they are correct then merely the response is sent to the clients.

The all-time style to send the API Keys is through the Http Request Header.

To sympathize this thing, I create a situation where but authorized clients can add a reservation by calling the Spider web API. I have to change the HTTP Post action of the Web API Controller to create a manual check for the Keys which are provided in the header.

If the keys are right just then the Reservation is added, else unauthorized result 401 response is send back.

And then modify the HTTP POST action of the Web API as shown below:

[HttpPost] public IActionResult Post([FromBody] Reservation res) {     if (!Authenticate())         return Unauthorized();     return Ok(repository.AddReservation(new Reservation     {         Proper noun = res.Name,         StartLocation = res.StartLocation,         EndLocation = res.EndLocation     })); }          

Detect I changed the return blazon to IActionResult since it will be returning both a HTTP Status Code and a reservation object.

Unauthorized Status code 401 is returned if Authenticate() method returns false, else Success 200 Status Code is returned forth with the newly created reservation object.

Also note that I take used the Ok() method to send both HTTP 200 Status Code with the reservation object.

Yous too need to add an Authenticate() function to the API controller which checks for the keys placed on the header of the Http requests fabricated past the clients.

bool Authenticate() {     var allowedKeys = new[] { "[email protected]", "Hole-and-corner#12", "SecretABC" };     StringValues key = Request.Headers["Primal"];     int count = (from t in allowedKeys where t == key select t).Count();     return count == 0 ? false : true; }          

There are 3 valid keys provided in the allowedKeys variable. Then I check if the Cardinal in the header matches from these three keys, only then true value is returned by this office.

At present go to the APIConsume projection (i.e. the customer project), then inside the AddReservation action method of the HomeController, you add a key in the Header of the HTTP request with this code – httpClient.DefaultRequestHeaders.Add together("Key", "[electronic mail protected]").

Also add a try grab cake to deserialize the response to a reservation object. If the deserialization fails so information technology is because the API Response does not contain the reservation object. This is a case when the cardinal is invalid and 401 condition code is returned by the API.

I have placed the ViewBag.Result variable, inside the catch block, to contain this 401 response sent by the API.

The updated AddReservation action method's code is given below.

[HttpPost] public async Chore<IActionResult> AddReservation(Reservation reservation) {     Reservation receivedReservation = new Reservation();     using (var httpClient = new HttpClient())     {         httpClient.DefaultRequestHeaders.Add("Key", "[email protected]");         StringContent content = new StringContent(JsonConvert.SerializeObject(reservation), Encoding.UTF8, "application/json");          using (var response = expect httpClient.PostAsync("https://localhost:44324/api/Reservation", content))         {             string apiResponse = await response.Content.ReadAsStringAsync();                          if (response.StatusCode == Arrangement.Net.HttpStatusCode.OK)                 receivedReservation = JsonConvert.DeserializeObject<Reservation>(apiResponse);             else if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)             {                 ViewBag.Consequence = apiResponse;                 return View();             }         }     }     return View(receivedReservation); }          

Now run your APIConsume project and add a new reservation from the URL https://localhost:44334/Home/AddReservation. You volition be able to add the new reservation because the primal which you provide is right.

Now Change the key to a incorrect 1 similar – httpClient.DefaultRequestHeaders.Add("Key", "wrongkey"). And then endeavor again to add a new reservation. This fourth dimension you volition fail to practice so and will come across a JSON message:

          {"blazon":"https://tools.ietf.org/html/rfc7235#section-three.1","title":"Unauthorized","status":401,"traceId":"|cccb5daa-43da21f99ce83682.ane.f7315d9e_"}        

This is shown by the paradigm given below:

401 status message received for wrong key

This JSON contains the title & condition nodes containing the texts – Unauthorized & 401. Y'all can just extract these texts past using Newtonsoft.Json and prove them on the view.

Here I have shown only a simple way of securing Web APIs. In professional person websites of big corporations the Web APIs are secured by JWT Token based authentication. I have also written a tutorial on this topic – How to secure APIs with JWT in ASP.NET Core [with source codes]

File Upload Web API

You can also upload files to remote servers through Web API. This can be done past using the IFormFile form as the parameter of the Web API'south action method. The IFormFile course represents the file sends through the HttpRequest.

Let united states of america create this file upload characteristic. First add Images folder inside the wwwroot folder of the APIControllers project. In that folder files sent by the client will be uploaded.

The beneath image illustrates the images folder location:

images folder location

For saving files I volition need the information virtually the web hosting surroundings. The best mode is to employ the ASP.Cyberspace Core Dependency Injection feature to inject IWebHostEnvironment of the Microsoft.AspNetCore.Hosting namespace into the controller'due south constructor. So update the Reservation Controller of the APIControllers project as shown below.

using System; using Arrangement.Collections.Generic; using APIControllers.Models; using Microsoft.AspNetCore.JsonPatch; using Microsoft.AspNetCore.Mvc; using System.Linq; using Microsoft.Extensions.Primitives; using Microsoft.AspNetCore.Hosting;  namespace APIControllers.Controllers {     [ApiController]     [Route("api/[controller]")]     public class ReservationController : ControllerBase     {         individual IRepository repository;                  private IWebHostEnvironment webHostEnvironment;          public ReservationController(IRepository repo, IWebHostEnvironment environment)         {             repository = repo;             webHostEnvironment = environment;         }                 // other methods     } }          

Now yous are ready to use the webHostEnvironment variable which contains the hosting surroundings details.

Next, add a new action method called UploadFile to the Reservation Controller of the APIControllers project as shown beneath:

using Arrangement; using Organization.Collections.Generic; using APIControllers.Models; using Microsoft.AspNetCore.JsonPatch; using Microsoft.AspNetCore.Mvc; using Organisation.Linq; using Microsoft.Extensions.Primitives; using Microsoft.AspNetCore.Hosting; using System.Threading.Tasks; using System.IO; using Microsoft.AspNetCore.Http;  namespace APIControllers.Controllers {     [ApiController]     [Route("api/[controller]")]     public class ReservationController : ControllerBase     {         private IRepository repository;                  individual IWebHostEnvironment webHostEnvironment;          public ReservationController(IRepository repo, IWebHostEnvironment surroundings)         {             repository = repo;             webHostEnvironment = environment;         }                  [HttpPost("UploadFile")]         public async Chore<string> UploadFile([FromForm] IFormFile file)         {             string path = Path.Combine(webHostEnvironment.WebRootPath, "Images/" + file.FileName);             using (var stream = new FileStream(path, FileMode.Create))             {                 look file.CopyToAsync(stream);             }             render "https://localhost:44324/Images/" + file.FileName;         }     } }          

This activeness contains the [HttpPost("UploadFile")] attribute that specifies this action method volition be invoked from the URL – /api/Reservation/UploadFile.

The Client will exist sending the file from HttpRequest and the file volition be saved to the wwwroot/Images folder of the Spider web API project.

The WebRootPath() method of the IWebHostEnvironment course gives the absolute path of the application's wwwroot binder.

So I can utilize the Path.Combine() method of the Organisation.IO namespace to create an absolute path where the file will be saved. I have also added the file name to this path by using the file.FileName property of the IFormFile class.

The FileStream class code which saves the file is given below:

          using (var stream = new FileStream(path, FileMode.Create)) {     expect file.CopyToAsync(stream); }        

In the finish my action method is returning back the full path of the saved file to the client equally a response.

At present going on the customer side, which is the APIConsume projection, where I will add a new action method that will upload the file by calling the Web API.

This action method is given below:

public ViewResult AddFile() => View();  [HttpPost] public async Task<IActionResult> AddFile(IFormFile file) {     string apiResponse = "";     using (var httpClient = new HttpClient())     {         var class = new MultipartFormDataContent();         using (var fileStream = file.OpenReadStream())         {             form.Add(new StreamContent(fileStream), "file", file.FileName);             using (var response = await httpClient.PostAsync("https://localhost:44324/api/Reservation/UploadFile", course))             {                 response.EnsureSuccessStatusCode();                 apiResponse = expect response.Content.ReadAsStringAsync();             }         }     }     render View((object)apiResponse); }          

This activeness method, whose proper noun is AddFile, has a parameter of blazon IFormFile. This means I tin get the file which is uploaded from the input command of file blazon, in the View through the ASP.Internet Core Model Binding feature.

Next I am reading the file from the OpenReadStream() method, and adding it to the form data by using the MultipartFormDataContent class. The reason for adding the file to form data is considering the Web API activeness method has the [FromForm] attribute.

Finally, I am making the API call to the URL – https://localhost:44324/api/Reservation/UploadFile with the HTTP Post request and the Spider web API response is returned to the View as Model.

The API returns a string which contains the full location of the uploaded file. At the concluding I casted this string to an object – (object)apiResponse and provided information technology to the default view.

Now create the View called AddFile inside the Views ➤ Home folder with the code given below:

@model cord @{ Layout = "_Layout"; ViewBag.Championship = "Add File";}   <h2>Add together File</h2> <a asp-action="Alphabetize" course="btn btn-sm btn-primary">Back</a> <course method="mail" enctype="multipart/class-information">     <input type="file" name="file" />     <div class="text-heart panel-body">         <push type="submit" form="btn btn-sm btn-chief">Add</push>     </div> </form>   @if (Model != aught) {     <h2>Uploaded File</h2>     <img src="@Model" /> }          

The course should take the aspect – enctype="multipart/grade-data" whenever you are uploading files.

The view has a model of type string so that I tin can testify the API response within an img tag.

Now let us test it by uploading an paradigm file. So run the awarding and become to the URL – https://localhost:44334/Domicile/AddFile. Click the file command and select an image then click the Add push. Yous will run across the prototype gets uploaded within a affair of seconds and will be displayed on the View.

The image below illustrates this:

file upload through web api

You lot tin can now find this file uploaded in the Images folder of the API Controllers projection:

file uploaded

Returning Data from Web API in XML instead of JSON – [Produces] attribute

I told earlier that ASP.NET Core returns data in JSON by default if the action method has the return type of annihilation other than a cord.

You may take noticed that if you lot run your APIControllers project and go to the URL – /api/Reservation, then you lot will go a JSON information containing all the reservations.

Check the Response Headers in your Network department of Chrome browser's Developers Tools. You will find the Content-Type as application/json. This is shown in the beneath image:

API response in json

You can change this and make the Web API to render the data in XML rather than in JSON. For this you will take to add together the AddXmlDataContractSerializerFormatters() method in the ConfigureServices method of the Startup.cs.

public void ConfigureServices(IServiceCollection services) {     services.AddSingleton<IRepository, Repository>();     services.AddControllersWithViews()         .AddNewtonsoftJson()         .AddXmlDataContractSerializerFormatters(); }          

Also add together the attribute called [Produces("application/xml")] which forces the format used by the API response to XML.

See the below code where I have used this aspect on the Get action method:

[HttpGet] [Produces("awarding/xml")] public IEnumerable<Reservation> Get() {     Cosign();     render repository.Reservations; }          

Now re-run your application and go to the same URL over again. This time yous will come across the data in XML format and the Content-Type set as application/xml. Meet the below epitome:

Web API response in xml

Web APIs accepting XML [Consumes("application/xml")]

The [Consumes] attribute specifies data types that an activeness/controller accepts. Some Web APIs accepts only XML data then have [Consumes("awarding/xml")] aspect on them. Let us see how to deal with information technology.

Go to the APIControllers app and add a new action method chosen PostXml with the Swallow attribute to accept only XML data. See information technology's code below.

[HttpPost("PostXml")] [Consumes("application/xml")] public Reservation PostXml([FromBody] System.Xml.Linq.XElement res) {     return repository.AddReservation(new Reservation     {         Proper noun = res.Element("Proper name").Value,         StartLocation = res.Element("StartLocation").Value,         EndLocation = res.Element("EndLocation").Value     }); }          

Ii things to note hither.

  • ane. It has the swallow attribute – [Consumes("application/xml")].
  • 2. It'due south parameter is of blazon XElement.

The [Consume] aspect examines the Content-Type header in the HTTP Request made from the clients and decides whether the action method tin can process the request or not.

Now to invoke this Web API'due south method from your customer project you add an action method called AddReservationByXml having the lawmaking shown beneath.

public ViewResult AddReservationByXml() => View();  [HttpPost] public async Task<IActionResult> AddReservationByXml(Reservation reservation) {     Reservation receivedReservation = new Reservation();      using (var httpClient = new HttpClient())     {         StringContent content = new StringContent(ConvertObjectToXMLString(reservation), Encoding.UTF8, "application/xml");          using (var response = await httpClient.PostAsync("https://localhost:44324/api/Reservation/PostXml", content))         {             cord apiResponse = look response.Content.ReadAsStringAsync();             receivedReservation = JsonConvert.DeserializeObject<Reservation>(apiResponse);         }     }     return View(receivedReservation); }  string ConvertObjectToXMLString(object classObject) {     string xmlString = null;     XmlSerializer xmlSerializer = new XmlSerializer(classObject.GetType());     using (MemoryStream memoryStream = new MemoryStream())     {         xmlSerializer.Serialize(memoryStream, classObject);         memoryStream.Position = 0;         xmlString = new StreamReader(memoryStream).ReadToEnd();     }     render xmlString; }          

Important things to annotation here are:

  • one. You accept to specify application/xml for the 3rd parameter (media type) of the StringContent form.
  • 2. The ConvertObjectToXMLString is a custom function to create XML from any course object.

Finally add the View called AddReservationByXml inside the Views ➤ Home folder (see below).

@model Reservation @{ Layout = "_Layout"; ViewBag.Championship = "Add a Reservation by XML";}  <h2>Add together a Reservation by XML <a asp-activity="Index" class="btn btn-sm btn-secondary">Back</a></h2> <form asp-activity="AddReservationByXml" method="post">     <div class="form-group">         <label for="Name">Name:</label>         <input form="form-command" name="Name" />     </div>     <div form="form-group">         <characterization for="StartLocation">Outset Location:</characterization>         <input course="form-command" proper name="StartLocation" />     </div>     <div class="form-group">         <label for="EndLocation">Cease Location:</label>         <input grade="form-control" name="EndLocation" />     </div>     <div course="text-center panel-trunk">         <button type="submit" form="btn btn-sm btn-primary">Add</button>     </div> </form>  <h3 grade="alert">@ViewBag.Result</h3>  @if (Model != null) {     <h2>Reservation</h2>     <tabular array class="table table-sm tabular array-striped table-bordered m-2">         <thead>             <tr>                 <th>ID</thursday>                 <th>Name</thursday>                 <th>Beginning Location</th>                 <th>End Location</thursday>             </tr>         </thead>         <tbody>             <tr>                 <td>@Model.Id</td>                 <td>@Model.Proper noun</td>                 <td>@Model.StartLocation</td>                 <td>@Model.EndLocation</td>             </tr>         </tbody>     </tabular array> }          
Important:

Once you publish your Web API you accept to make sure that you Enable Cross-Origin Requests (CORS) otherwise the clients will receive mistake chosen No 'Admission-Control-Let-Origin' header is nowadays on the requested resources . You can check my tutorial How to Enable Cantankerous-Origin Requests (CORS) in ASP.Cyberspace Core. Past the mode, on the source codes, I take already enabled CORS (meet Setup.cs file of APIControllers projection).

Web APIs "Format-specific" Methods

A single method of the Web API can produce both JSON & XML consequence. For this you have to utilize the FormatFilter attribute.

Add the below method to your Web API.

[HttpGet("ShowReservation.{format}"), FormatFilter] public IEnumerable<Reservation> ShowReservation() => repository.Reservations;          

See I accept applied the format filter similar – [HttpGet("ShowReservation.{format}"), FormatFilter]. And so this method can now send the reservation in both XML & JSON. This will reduce your code in a large way.

The URL to invoke the XML version:

https://localhost:44324/api/Reservation/ShowReservation.xml

The URL to invoke the JSON version:

https://localhost:44324/api/Reservation/ShowReservation.json

I have shown the working in the beneath video.

formatfilter attribute video

The link to download the full source code of this tutorial is given below:

Download

Conclusion

In this tutorial I explained everything dealing with Web APIs in ASP.NET Cadre MVC. I hope you find it useful, please share this article that will assist the website. Likewise check the next tutorial – How to Calll Web APIs from jQuery.

brownecoustim.blogspot.com

Source: https://www.yogihosting.com/aspnet-core-consume-api/

0 Response to "System.web How to Read the Response From Call"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel