Using the Fetch API in conjunction with ASP.NET Core Razor Pages offers a host of advantages that can significantly enhance the development and performance of web applications. One of the primary benefits is the ability to make asynchronous HTTP requests to servers, which allows for dynamic and interactive web pages. This means that you can fetch data from a server and update the content of your web page without requiring a full page reload, leading to a more seamless and responsive user experience. The Fetch API is also simple to use and provides a cleaner, more intuitive syntax compared to older XMLHttpRequest methods, making your JavaScript code more readable and maintainable.
Furthermore, integrating the Fetch API with ASP.NET Core Razor Pages leverages the robust capabilities of both technologies. Razor Pages simplify server-side logic and view management in ASP.NET Core, allowing for clear separation of concerns and a more organized codebase. When combined with the Fetch API, developers can easily implement efficient client-server communication patterns. This setup is ideal for creating Single Page Applications (SPAs) or enhancing existing multi-page applications with dynamic features. Additionally, the Fetch API’s support for modern JavaScript features such as Promises and async/await enables developers to handle asynchronous operations gracefully, resulting in more reliable and performant web applications. Overall, the Fetch API enhances the power and flexibility of ASP.NET Core Razor Pages, enabling developers to build more interactive, efficient, and user-friendly web applications.
Examples
To illustrate these advantages, I’ll be working through two examples using the Fetch API. These examples will be based in the same solution and will utilize a custom PostInfo
object. Specifically, I’ll be using a List<PostInfo>
to keep track of each post I make, storing details such as the date, page, and action associated with my posts. This consistent approach will demonstrate how seamlessly the Fetch API can be integrated into ASP.NET Core Razor Pages, highlighting its practical benefits and ease of use in real-world scenarios. I’m only going to go over the pertinent code here, but the full solution can be found on GitHub.
public class PostInfo
{
public int Id { get; set; } = -1;
public DateTime PostDate { get; set; } = DateTime.Now;
public string PostPage { get; set; }
public string Action { get; set; }
}
Post – No Data
At some point you may want to make a Post and not send any data or you may not have a form to pull data from to post.
function postWithFetch() {
var url = "@Href("~/PostWithFetchAPI?handler=AddPost")";
var options = {
method: 'POST',
headers: {'Content-Type': 'application/json'}
};
fetch(url, options)
.then(function (response) {
// When the page is loaded convert it to text
return response.text();
})
.then(function (html) {
// You can now even select part of that html as you would in the regular DOM
document.getElementById('divPostContainer').innerHTML = html;
})
.catch(function (err) {
console.log('Failed to fetch page: ', err);
});
} // end function postWithFetch()
The key to your post working in this scenario is getting your server side code to accept your request. Normally you would be posting a form, and each form includes an antiforgery token to validate that it’s receiving a valid request. In this case no such token exists so your page model class needs to configured to ignore those tokens, and that can be accomplished with the [IgnoreAntiforgeryToken] attribute. As of this writing this has to be done at the class level and cannot be applied to specific functions within the class.
Post – With Data
This scenario presents the opposite problem of the prior one; now you have to include the antiforgery token in the post request. In the example look at the variable named token, this is where we store the token’s value. Keep in mind if you have multiple forms in your own scenario you may have to use a more specific selector to find the correct input.
Along with finding the token we’re also filling a JavaScript object named data that resembles our PostInfo object we outlined earlier. This resemblance is not coincidence, the object we post back will need to be able to be converted to the PostInfo object.
The last piece is including the token and object information in the request. This can be done inside the request options. The token is included as a RequestVerificationToken header, and the object is converted to JSON and added to the request body.
function postFormWithFetch() {
var rowCount = document.getElementById('tblPosts').tBodies[0].rows.length;
var token = document.querySelector('input[name="__RequestVerificationToken"]').getAttribute("value");
var url = '@Href("~/PostFormDataWithFetchAPI?handler=FormWithFetch")';
var data = {
Id: rowCount + 1,
Action: document.getElementById('CustomAction').value,
PostPage: '@nameof(FetchTutorial.Pages.PostFormDataWithFetchAPIModel)'
};
var options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'RequestVerificationToken': token
},
body: JSON.stringify(data)
};
console.log(data);
fetch(url, options)
.then(function (response) {
// When the page is loaded convert it to text
return response.text();
})
.then(function (html) {
// You can now even select part of that html as you would in the regular DOM
document.getElementById('divPostContainer').innerHTML = html;
})
.catch(function (err) {
console.log('Failed to fetch page: ', err);
});
}
On the server side all we do is let our post function know what type of object to expect and where to get it from. To do this we use the [FromBody] attribute. This lets the function know where to look for the parameter’s value. If for some reason you have not configured your object correctly in JavaScript your request will still go through, but your object will be null.
Hope this helps.
Resources
- https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
- https://www.learnrazorpages.com/razor-pages/ajax#fetch-api
- https://learn.microsoft.com/en-us/aspnet/core/security/anti-request-forgery?view=aspnetcore-8.0#antiforgery-in-aspnet-core
- https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.ignoreantiforgerytokenattribute?view=aspnetcore-8.0
- https://learn.microsoft.com/en-us/aspnet/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api#using-frombody
Leave a Reply