AJAX is a technique used for making asynchronous requests from the browser to the server for various purposes including posting form values. This section covers asynchronous form submission from a Razor Page using both the jQuery AJAX capability and the Fetch API.
The Razor Page
The PageModel for this example includes a property called UploadedFile
, which represents the file that gets uploaded when the form is posted. The IFormFile
type is located in the Microsoft.AspNetCore.Http
namespace:
public class IndexModel : PageModel
{
[BindProperty, Display(Name="File")]
public IFormFile UploadedFile { get; set; }
public void OnPost()
{
}
}
The UploadedFile
property make use of attributes to control the output of tag helpers, specifically the label and input tag helpers.
Here is the content page, styled using BootStrap 4:
<form method="post" class="col-sm-6">
<div class="form-group row">
<label asp-for="UploadedFile" class="col-sm-3 col-form-label"></label>
<div class="col-sm-7">
<input asp-for="UploadedFile" class="form-control">
</div>
</div>
<div class="form-group row">
<div class="col-sm-7 offset-sm-3">
<button class="btn btn-primary" id="submit">Submit</button>
</div>
</div>
</form>
The input tag helper automatically ensures that the type
property on the input is rendered as file
, based on the data type of the property passed to the asp-for
attribute.
Using jQuery
The first example looks at using jQuery to post the form content asynchronously. The actual script is included using a Razor section, but can just as easily be included in a separate file:
@section scripts{
<script>
$(function () {
$('#submit').on('click', function (evt) {
evt.preventDefault();
$.ajax({
url: '',
data: new FormData(document.forms[0]),
contentType: false,
processData: false,
type: 'post',
success: function () {
alert('Uploaded by jQuery');
}
});
});
});
</script>
}
The jQuery library includes a number of wrapper functions that result in a minimal amount of code required to make an AJAX request e.g. $.post
, $.get
. However, for uploading files, the full $.ajax
version is needed because some settings need to be changed. The contenttype
needs to be set to false
along with the processData
option. Otherwise jQuery will not see this as a file upload, and will set the encoding of the request body to application/x-www-form-urlencoded
, which is fine for simple text, but not for files.
When the form is posted, the file is automatically bound to the IFormFile
property on the PageModel:
Using Fetch
The Fetch API is supported by all modern browsers except Internet Explorer. It is supported by the new Edge browser from Microsoft, which is available on Windows 10. This example makes no use of the jQuery library at all, relying on pure JavaScript:
@section scripts{
<script>
document.getElementById('submit').addEventListener("click", (evt) => {
evt.preventDefault();
let data = new FormData(document.forms[0]);
fetch('', {
method: 'post',
body: data
})
.then(() => {
alert('Posted using Fetch');
});
});
</script>
}
This example uses the FormData API to construct a set of key/value pairs representing the form fields and their values. The FormData constructor will accepts an HTML form
element and then use the name property of each element in the form for the keys and their submitted value for the values.
When using FormData, the encoding type of the request body defaults to multipart/form-data
, which is the correct encoding for posting binary data.
Using XMLHttpRequest
Finally, this is how it is achieved using the XMLHttpRequest object:
section scripts{
<script>
document.forms[0].onsubmit = () => {
let formData = new FormData(document.forms[0]);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
alert('Posted using XMLHttpRequest');
}
};
xhr.open('post', '', true);
xhr.send(formData);
return false;
};
</script>
}