1

I am attempting to manually POST a form in ASP.NET Core using jQuery AJAX as soon as the user finishes selecting multiple files. The Uploader I am using has an "selected" event where I would like to POST the form to the server using jQueryAJAX.

This exact same form posts perfectly to the server when adding a submit button to the form and clicking it on the UI. The Files are bound and the ProductId is bound. However, I am trying to avoid the page flicker. As an alternative solution I am submitting the form by calling: $("#form").submit(); in the onSelect function rather than the AJAX request.

Model looks like the following:

public int ProductId { get; set; }
public IList<IFormFile> Files { get; set; }

Form looks like the following:

<form method="post" enctype="multipart/form-data">
     <ejs-uploader id="Files" showFileList="false" autoUpload="false" multiple="true" selected="onSelected" success="onSuccess" allowedExtensions=".doc, .docx, .pdf, .jpg, .jpeg, .png"></ejs-uploader>
     <input asp-for="ProductId" type="hidden" />
</form>

Here is the JavaScript that I have been trying which is not working:

    function onSelected(args) {
        var files = args.filesData;
        var formData = new FormData();

        for (var i = 0; i != files.length; i++) {
            formData.append("files[]", files[i]);
        }

        $.ajax({
            type: "POST",
            contentType: false,
            url: '?handler=FileUpload',
            data: formData,
            processData: false,
            headers: {
                RequestVerificationToken:
                    $('input:hidden[name="__RequestVerificationToken"]').val()
            },
            success: function (data) {

            },
        });

        //$("#form").submit();
    }

I am using razer pages so the action method is:

[BindProperty]
public int MessageId { get; set; }

[BindProperty]
public IList<IFormFile> Files { get; set; }

public async Task<ActionResult> OnPostAsync()
{
}

I have also tried creating a view model: FileUploadViewModel with the same 2 properties in it.

public async Task<ActionResult> OnPostAsync(FileUploadViewModel vm)
{
}
4
  • Please show your Action method Commented Jan 26, 2019 at 21:35
  • @CamiloTerevinto I uploaded some additional info about the Action method. I am using razor pages which works slightly different than MVC. The page itself has the properties on it so the View Model can be eliminated. However, I was trying by also have a ViewModel as a param as well. Nothing is binding. This post is the closest thing I found to what I am trying to do, but he only does it for a single file. Additionally, I can't even get this working. learnrazorpages.com/razor-pages/ajax/upload-files Commented Jan 26, 2019 at 22:19
  • Hmmm, I'm not sure about Razor Pages, but in MVC that would be wrong. You'd need a [FromForm] FileUploadViewModel vm, that might be the default though Commented Jan 26, 2019 at 22:22
  • Thinking a little more about it, you should be using formData.append("Files", files[i]); Commented Jan 26, 2019 at 22:26

3 Answers 3

1

I maybe a little late to the party, however I was having the exact same issue were I wanted to manually post my request using ajax along with whatever form values the user had entered as well as any selected files for upload.

Because I was calling the controller manually with ajax the files were not being included.
Here is my ajax post request.

 $.ajax({
        type: 'POST',
        url: '/home/createorder',
        data: new FormData(document.forms[0]),
        contentType: false,
        processData: false,
        crossDomain: true,
        success: function (data) {
               console.log(data);
               window.location.replace(data.redirectUrl);
        },
        error: function (data) {
                console.log(data);
                alert(data.responseJSON.error);
        },
 })

Here is my Model's property.

public IReadOnlyCollection<IFormFile> AttachmentCollection { get; set; }

And Finally here is my cshtml page makeup

 <div class="card card-5">
        <div class="card-heading">
            <h2 class="title">Attachments</h2>
        </div>
        <div class="card-body">
            <div class="form-row">
                <div class="custom-file">
                    <input asp-for="AttachmentCollection" class="form-control custom-file-input" multiple>
                    <label class="custom-file-label">Choose File...</label>
                </div>
            </div>
        </div>
    </div>

Note: Make sure you include this enctype="multipart/form-data" in your <form>

Sign up to request clarification or add additional context in comments.

Comments

-1

According to FormData.append(), I think you have to use

formData.append("files[]", files[i]);

Instead of

formData.append("files", files[i]);

To append multiple files...

4 Comments

I tried this and still end up with a list of 0 files. Any idea if there is anything else wrong with my ajax request? I am not even sure if processData and contentType should both be false. I saw this in another post.
Are you kidding? The documentation says and being compatible with PHP's naming conventions. Where do you see PHP here?
As with regular form data, you can append multiple values with the same name. and in parentheses they points to PHP to... change your glasses man
It's only a variable name, is that so hard to understand? This is like saying that changing int myName = "asd"; for int someInt = "asd" will suddenly make it work, those [] are useless there
-1

you can receive the attached file as a separate controller parameter of type IEnumerable` note that in order for the mapping to be done correctly you have to choose the right naming for the html input file controls , for example if your controller will have the following signature

public ActionResult SaveProduct(Product newproduct , IEnumerable<HttpPostedFileBase> files) 

then the html input controls must be named :

<input type='file' name='files[0]'/>
<input type='file' name='files[1]'/>
<input type='file' name='files[2]'/>

and so on

don't know if there is an option to bind controls directly to the model without creating custom model binder but i have always used this option , fairly simple and easy

3 Comments

I need multiple files uploaded from a single file input.
HttpPostedFIleBase is not ASP.NET Core. ASP.NET Core uses IFormFile
then you can create one input control and map it to one action parameter of type <input type='file' name='files' multiple /> IEnumerable<HttpPostedFileBase> or as blake suggested IFormFile

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.