Uploading Files via AJAX in Razor Pages

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.

AJAX File Upload in Razor Pages

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:

Upload Files using AJAX

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>
}

Further reading

Last updated: 5/8/2019 2:29:05 PM

© 2018 - 2024 - Mike Brind.
All rights reserved.
Contact me at Mike dot Brind at Outlook.com