Tappas
Tappas

Reputation: 87

Dropzone doesn't bind other fields to Asp.Net Core viewmodel

I am using the following html to render a dropzone. And my controller is accepting IFormFile and FileViewModel. However dropzone does not bind my input tag which accepts a persons name to the viewModel on form submit.

I have also come to the resolution that Dropzone.js is a very old Ajax control primmed for single page applications.

HTML :

@model Dropzone.Models.FileViewModel
    <form action="/Account/Create" enctype="multipart/form-data" method="POST">
        <input type="text" id ="Username" name ="Username" asp-for="Model.Name" />
        <div class="dropzone" id="my-dropzone" name="mainFileUploader">
            <div class="fallback">
                <input name="file" type="file" multiple />
            </div>
        </div>
    </form>
    <div>
        <button type="submit" id="submit-all"> upload </button>
    </div>

JQuery:

<script>
    Dropzone.options.myDropzone = {
        url: "/Account/Create",
        autoProcessQueue: false,
        uploadMultiple: true,
        parallelUploads: 100,
        maxFiles: 100,
        acceptedFiles: "image/*",

        init: function () {

            var submitButton = document.querySelector("#submit-all");
            var wrapperThis = this;

            submitButton.addEventListener("click", function () {
                wrapperThis.processQueue();
            });

            this.on("addedfile", function (file) {

                // Create the remove button
                var removeButton = Dropzone.createElement("<button class='btn btn-lg dark'>Remove File</button>");

                // Listen to the click event
                removeButton.addEventListener("click", function (e) {
                    // Make sure the button click doesn't submit the form:
                    e.preventDefault();
                    e.stopPropagation();

                    // Remove the file preview.
                    wrapperThis.removeFile(file);
                    // If you want to the delete the file on the server as well,
                    // you can do the AJAX request here.
                });

                // Add the button to the file preview element.
                file.previewElement.appendChild(removeButton);
            });

            this.on('sendingmultiple', function (data, xhr, formData) {
                formData.append("Username", $("#Username").val());
            });
        }
    };
</script>

Upvotes: 2

Views: 1783

Answers (1)

Zhi Lv
Zhi Lv

Reputation: 21581

Dropzone doesn't bind other fields to Asp.Net Core viewmodel

To add other fields with the upload files, you could use the sending event to add the field's value in the formData objects, instead of the sendingmultiple event.

Check the following sample:

public class FileViewModel
{
    public string Name { get; set; }
    public IFormFile File { get; set; }
    public List<IFormFile> Files { get; set; }
}

Controller:

    public IActionResult UploadFile()
    {
        FileViewModel model = new FileViewModel() { Name = "new File" };
        return View(model);
    }

    [HttpPost]
    public IActionResult UploadFile(FileViewModel fileViewModel, List<IFormFile> files)
    {
        try
        {
            if (files.Count > 0)
            {
                //string folderRoot = Path.Combine(_environment.ContentRootPath, "Uploads");
                //string filePath = Guid.NewGuid() + Path.GetExtension(file.FileName);
                //filePath = Path.Combine(folderRoot, filePath);
                //using (var stream = new FileStream(filePath, FileMode.Create))
                //{
                //    await file.CopyToAsync(stream);
                //}
            }
            return Ok(new { success = true, message = "File Uploaded" });
        }
        catch (Exception)
        {
            return BadRequest(new { success = false, message = "Error file failed to upload" });
        }
    }

View Page:

@model WebApplication6.Models.FileViewModel

@{
    ViewData["Title"] = "UploadFile";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>UploadFile</h1>
  
<form asp-action="UploadFile" enctype="multipart/form-data" method="POST">
    <div class="form-group">
        @*<label asp-for="Name" class="control-label"></label>
            <input asp-for="Name" class="form-control" />
            <span asp-validation-for="Name" class="text-danger"></span>*@
        <input type="text" asp-for="Name" />
        <div class="dropzone" id="dropzone-form" name="mainFileUploader">
            <div class="fallback">
                <input asp-for="File" type="file" multiple />
            </div>
        </div>
    </div>
    <div class="form-group">
        <button type="button" id="submit-all"> upload </button>
    </div>
</form>
  

Add the following JQuery scripts:

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    <link rel="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/dropzone.css" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.5.1/dropzone.js"></script>

    <script type="text/javascript">
        Dropzone.options.dropzoneForm = {
            url: "/Test/UploadFile",
            paramName: "file", 
            autoProcessQueue: false,
            uploadMultiple: true,
            parallelUploads: 100,
            maxFiles: 100,
            acceptedFiles: "image/*",
            init: function () {

                var submitButton = document.querySelector("#submit-all");
                var wrapperThis = this;

                submitButton.addEventListener("click", function () {
                    wrapperThis.processQueue();
                });

                this.on("addedfile", function (file) {

                    // Create the remove button
                    var removeButton = Dropzone.createElement("<button class='btn btn-lg dark'>Remove File</button>");

                    // Listen to the click event
                    removeButton.addEventListener("click", function (e) {
                        // Make sure the button click doesn't submit the form:
                        e.preventDefault();
                        e.stopPropagation();

                        // Remove the file preview.
                        wrapperThis.removeFile(file);
                        // If you want to the delete the file on the server as well,
                        // you can do the AJAX request here.
                    });

                    // Add the button to the file preview element.
                    file.previewElement.appendChild(removeButton);
                });
                this.on("sending", function (file, response, formData) {
                    formData.append("Name", $("#Name").val());
                    formData.append("Files", file); 
                });
                //this.on('sendingmultiple', function (data, xhr, formData) {
                //    formData.append("Name", $("#Name").val());
                //});
            }
        };
    </script>
}

The result like this:

enter image description here

Upvotes: 1

Related Questions