Learn to fetch() resources in ASP.NET Core

Making Ajax requests from the client side JavaScript code to the server side resources is extremely common requirement in web applications. Traditionally developers used XMLHttpRequest (XHR) object to accomplish this task. Although you can continue to use XHR there is a better alternative - Fetch API.

All the modern browsers support what is known as Fetch API. The Fetch API provides a global fetch() method that you can call in your JavaScript code to fetch resources from the server. Fetch API uses JavaScript Promises and is simpler to use than XHR.

ASP.NET Core developes will find the fetch() method quite useful to invoke Web APIs or any Ajax operations that involve MVC actions, Razor Pages page handlers, or Blazor.

Before we go into the details of using fetch() with MVC, Razor Pages, Blazor, and Web API it's worthwhile to understand the basics of the fetch() method and its working.

So, let's get going by building a simple app that demonstrates the usage of fetch() to fetch HTML page from the server. I am going to assume that you are comfortable working with ASP.NET Core projects and Visual Studio.

Begin by creating a new ASP.NET Core MVC application named FetchApiDemo. You can also create an empty web application and configure it to use MVC.

Once the app is created add a new HTML page named Greetings.html to the wwwroot folder. Add the following markup in Greetings.html file.

<h2>Hello World!</h2>
<h2>Hello Galaxy!!</h2>
<h2>Hello Universe!!!</h2>

Then open Index.cshtml view file and add the following markup to it:

<h1>Using fetch() from MVC</h1>
<button id="fetchButton">
    Fetch Greetings
</button>
<div id="messages"></div>

As you can see, there is a button for invoking the fetch() operation and there is a <div> to display the response once the operation is complete.

Next, we need to wire the click event handler of the button. We do that as shown below:

document.addEventListener
("DOMContentLoaded", function () {
var btn = document.getElementById
("fetchButton");
btn.addEventListener('click', function(){
    // code here
});

We write this code inside DOMContentLoaded handler to ensure that the HTML DOM is loaded and the button is accessible to wire its click event handler. Then we get the button element reference using getElementById() method. We then attach click event handler to the button using addEventListener() method. The event handler function is currently empty but this is where your fetch() operation will happen.

There are a few variations of calling the fetch() method. We will see them one-by-one. Firstly, let's use the simplest form of fetch(). Write the following code inside the empty click event handler function shown above.

var div = document.getElementById("messages");
div.innerHTML = "";
fetch('/greetings.html')
.then(function(response) {
    if(!response.ok)
    {
        div.innerHTML = 
        `<h2>{response.status} 
        - {response.statusTest}</h2>`;
    }
    return response.text();
}).then(function(html){
    div.innerHTML= html;
});

In this code we first clear the contents of the <div> element so that the newly fetched content can be displayed. We then call the fetch() method by passing the URL of the HTML file to fetch. The fetch() method returns a JavaScript Promise that is handled using chained then() methods.

The first then() receives a Response object as its parameter. Inside we check whether the ok property of Response is true or false. If it is false we display an error message in the form of error status code and status text. Otherwise, we call text() method of Response. The text() method wraps the response text in a Promise. The Promise returned by the text() method is handled by the second then().

The second then() receives the response text. In this case it is going to an HTML fragment we put inside Greetings.html file. We display this HTML in the <div> element.

If you run this application and hit the Fetch Greetings button you will see this output:

In this example we used the simplest way of calling the fetch() method. The fetch() method can also take two parameters - a Request object and an options object. The Request object wraps the URL of the resource to be fetched. And the options object wraps the settings for fetching the resource such as HTTP method, headers, and authentication details.

In the above example the code assumed the default HTTP method of GET. Now, let's modify the same code to use Request and options object. Take a look below:

var div = document.getElementById("messages");
div.innerHTML = "";

const request = new Request('/greetings.html');
const options = { method:"GET" };

fetch(request, options)

.then(function(response) {
    if(!response.ok)
    {
        div.innerHTML = 
        `<h2>{response.status} 
        - {response.statusTest}</h2>`;
    }
    return response.text();
}).then(function(html){
    div.innerHTML= html;
});

Notice the code shown in bold letters. We create a Request object that wraps the URL of Greetings.html. We also create a JS object for holding the HTTP method to use for making the request (GET in this case). The fetch() call now accepts this Request object and options object. The final output remains identical to the previous run.

In the preceding example we used JavaScript traditional function syntax to wire the then() handlers. You can also use lambda functions (arrow functions) as shown below:

fetch(request, options).then((response) => {
    if (!response.ok) {
        div.innerHTML = 
        `<h2>{response.status} 
        - {response.statusTest}</h2>`;
    }
    return response.text();
}).then((html) => {
    div.innerHTML = html;
});

Of course, you can use lambda functions / arrow functions in the addEventListener() callbacks also.

Modern JavaScript also has async / await keywords for invoking asynchronous code. The following code shows the same fetch() operation written using async / await pattern.

btn.addEventListener('click', async function(){
    var div = document.getElementById("messages");
    div.innerHTML = "";
    const request = new Request('/greetings.html');
    const options = {
        method:"GET"
    };
    const response = await fetch(request,options);
    if (!response.ok) {
        div.innerHTML = 
        `<h2>{response.status} 
        - {response.statusTest}</h2>`;
        return;
    }
    const html = await response.text();
    div.innerHTML = html;
});
});

Notice the code shown in bold letters. The click event handler function passed to the addEventListener() method is now decorated with async keyword because inside we want to use await keyword.

Then note the changes to the fetch() call. We call fetch() using await keyword and get the Response. Similar change is done to the text() call to get the response HTML text.

I hope this article gave you good idea about what the fetch() API is and how to use it from JavaScript code. In this example we returned HTML markup from the server. The fetch() method can be used to fetch JSON or any other kind of response from the server. In the subsequent parts of this series we will discuss how fetch() can be used in combination with MVC actions, Razor Pages, Web API, and minimal API.

That's it for now! Keep coding!!


Bipin Joshi is an independent software consultant and trainer by profession specializing in Microsoft web development technologies. Having embraced the Yoga way of life he is also a meditation teacher and spiritual guide to his students. He is a prolific author and writes regularly about software development and yoga on his websites. He is programming, meditating, writing, and teaching for over 27 years. To know more about his ASP.NET online courses go here. More details about his Kriya and Meditation online course are available here.

Posted On : 15 January 2023