Return a partial view with fetch API in ASP.NET Core Razor Pages
I finally parted ways with jquery unobtrusive ajax and started using the fetch api and I couldn't be happier with the results
Nothing complements a single page app like a response from the server without a page refresh. By adopting this workflow, you gain the advantage of working with strongly typed models. This is especially beneficial for forms that handle data with multiple properties, as demonstrated by our Blog Post model example.
// BlogPost.cs
public class BlogPost
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public string Tags { get; set; }
public string Category { get; set; }
}
// BlogPost.cshtml.cs - server side code
[BindProperty]
public BlogPost BlogPost { get; set; }
public IActionResult OnPostSaveBlog() {
return Partial("Partials/_blog_item",
new BlogPost() {
Title = BlogPost.Title
, Author = BlogPost.Author
, Content = BlogPost.Content
});
}
Two **HUGELY** important things to look out for in the code above. First is the `[BindProperty]` attribute above the BlogPost property we're binding to. Without this, the model simply doesn't bind.\
Second, notice the naming convention of the method. "OnPostSaveBlog". You'll see on the clientside code the method is referenced without the OnPost portion (ie: `asp-page-handler="SaveBlog"` The OnPost, OnGet, OnPut are examples of the preferred method naming convention in Razor Pages
<!-- BlogPost.csthml -->
<form method="post" asp-page-handler="SaveBlog" id="blogForm">
<label>Title</label>
<input class="form-control" asp-for="BlogPost.Title" />
<label>Author</label>
<input class="form-control" asp-for="BlogPost.Author" />
<label>Content</label>
<textarea asp-for="BlogPost.Content" rows="2"></textarea>
<input class="form-control" type="hidden" asp-for="BlogPost.Id" id="BlogPostId" />
<button type="button" class="btn btn-primary" id="buttonSubmit">Send to server</button>
</form>
<div id="resultContainer"></div>
<script>
var blogForm = document.getElementById('blogForm');
document.getElementById('buttonSubmit').addEventListener('click',function () {
submitFetch(blogForm,completeCallback)
});
function completeCallback(data) {
document.getElementById("resultContainer").innerHTML = data;
}
function submitFetch(form, fn) {
const formData = new FormData(form);
fetch(form.getAttribute('action'), {
method: 'POST',
body: formData
})
.then(response => response.text())
.then(data => fn(data))
.catch(error => console.error('Error:', error));
}
</script>
As you can see above the fetch api code is easily implemented with a few lines of code. The only things to be mindful of are the few quirks with the naming convention and the form-data encoded format of the posted data. I've seen code samples of razor endpoints accepting json data as well. I'll vist that in another post. If you have any other solutions for using fetch you'd like to share please send them my way. I'd love to see them.\
https://github.com/tet-web-dev
- ASP.NET Core
- Single Page App
- Razor Pages
- JavaScript