Call ASP.NET Core Web API and Minimal API using fetch() -- Part 2
In the previous article we created a Web API controller and minimal APIs that perform CRUD operations on the Customers table. Now it's time to call our APIs from our UI. We could have used a plain HTML page for housing the UI elements but we will use the same MVC view that we have created in the previous examples of this series.
By now you are familiar with the fetch() method and how to perform CRUD operations using fetch(). If you observe the MVC and Razor Pages examples we created earlier, you will find that certain parts of the code were repeated at multiple places. That was done for easy understanding and learning purposes. In this example. we will isolate the repetitive code into a JavaScript function and call that function in various event handlers.
The following code shows the callApi() JavaScript function that will be used to invoke the Web API and minimal API.
async function callApi(url, verb, data)
{
const request = new Request(url);
let options = {
method: verb,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
};
if(data !== undefined) {
options.body = JSON.stringify(data);
}
const response = await fetch(request, options);
if (!response.ok) {
message.innerHTML = "Error : " +
response.status;
}
else{
message.innerHTML = "Success";
}
if(verb == "GET") {
const json = await response.json();
return json;
}
}
Let's discuss this function in more details.
The callApi() function is an async JS function and takes three parameters namely url, verb, and data. The url parameter is used to supply the Web API or minimal API endpoint address that we want to call. The verb parameter indicates the HTTP verb to be used such as GET, POST, PUT, and DELETE. The data parameter is an optional parameter and is intended to pass the data that accompanies the request.
Inside, we create a Request object that wraps the url passed to the function. Then we create options object and set method and headers properties. The body property of the options object is assigned a value only if data parameter is passed. This is because not all requests will have body. For example, GET and DELETE requests won't have any data accompanying them whereas POST and PUT requests will have customer data accompanying them.
We then initiate the fetch() request by passing the Request and options objects. If the response contains some error we display the error code to the user; otherwise a success message is displayed.
The callApi() function returns the data sent by the server only for GET requests. This is done by calling json() on the response object and then returning the JSON data.
Now that the callApi() is ready, you can use in various event handlers. Let's see the DOMContentLoaded handler first.
document.addEventListener("DOMContentLoaded",
async function () {
var customerid = document.
getElementById("customerid");
var newcustomerid = document.
getElementById("newcustomerid");
var companyname = document.
getElementById("companyname");
var contactname = document.
getElementById("contactname");
var country = document.
getElementById("country");
var insert = document.
getElementById("insert");
var update = document.
getElementById("update");
var del = document.
getElementById("delete");
var message = document.getElementById("message");
const json = await callApi("/api/Customers", "GET");
json.forEach(function(customer){
const option = document.
createElement('option');
option.value = customer.customerID;
option.innerHTML = customer.customerID;
customerid.appendChild(option);
});
message.innerHTML =
"Customers fetched successfully.";
})
Notice the line shown in bold letters. This is how the callApi() function can be used to make GET requests to the Web API. Notice that the url points to the Web API controller -- /api/Customers. The other code should look familiar to you because we used it in the previous examples also.
Next, we will add change event handler of the customerid dropdown list. Have a look at the following code:
customerid.addEventListener
('change', async function(){
const json = await callApi
("/api/Customers/" + customerid.value, "GET");
companyname.value = json.companyName;
contactname.value = json.contactName;
country.value = json.country;
message.innerHTML =
"Customer fetched successfully.";
});
This time we call the callApi() function by passing the selected customerid appended in the URL -- /api/Customers/<customerid>. The HTTP verb is GET but this time it will return just one Customer matching the CustomerID.
Now take a look at the click event handler of the insert button.
insert.addEventListener('click',
async function(){
let data = {};
data.customerID = newcustomerid.value;
data.companyName = companyname.value;
data.contactName = contactname.value;
data.country = country.value;
await callApi("/api/Customers", "POST", data);
message.innerHTML =
"Customer Inserted Successfully!";
});
This time we make a POST request to /api/Customes and also pass a customer to be added in the form of data object.
The click event handler of the update button is as follows:
update.addEventListener('click',
async function(){
let data = {};
data.customerID = customerid.value;
data.companyName = companyname.value;
data.contactName = contactname.value;
data.country = country.value;
await callApi("/api/Customers/" +
customerid.value, "PUT", data);
message.innerHTML =
"Customer Modified Successfully!";
});
In the above code we make a PUT request to the Web API along with the data object. We also pass customerid in the URL.
The click event handler of the delete button is shown below:
del.addEventListener('click', async function () {
await callApi("/api/Customers/"
+ customerid.value, "DELETE");
const json = await
callApi("/api/Customers", "GET");
customerid.innerHTML = "";
json.forEach(function(customer){
const option = document.createElement('option');
option.value = customer.customerID;
option.innerHTML = customer.customerID;
customerid.appendChild(option);
});
message.innerHTML =
"Customer Deleted Successfully!";
});
There are two calls toe callApi() function in the above code. The first call makes a DELETE request to the Web API by passing the customerid to be deleted. The second call retrieves all the customers again using a GET request and refills the customerid dropdown list. We could have easily avoided the second call by removing the CustomerID entry from the dropdown list without making an API call. But just to confirm that the customer has really got deleted we hit the Web API again.
This completes the client side code. Run the application and check all the CRUD operations. You can also set breakpoints in the Web API actions to understand the API calls.
How do we call minimal API using the callApi() function created above? Simple. Just replace the URLs to match the minimal API endpoint URLs. All the callApi() calls that make use of minimal API are given below:
// DOMContentLoaded handler
const json =
await callApi("/minapi/Customers", "GET");
// dropdown list change event handler
const json =
await callApi("/minapi/Customers/" +
customerid.value, "GET");
// click event handler of insert button
await callApi("/minapi/Customers", "POST", data);
// click event handler of update button
await callApi("/minapi/Customers/" +
customerid.value, "PUT", data);
// click event handler of delete button
await callApi("/minapi/Customers/" +
customerid.value, "DELETE");
Substitute Web API with minimal API and run the application again.
That's it for now! Keep coding!!