Tim Cadieux
Tim Cadieux

Reputation: 455

Boostrap Modal, browse for photo and submit via ajax to controller with [FromForm] IFormFile file

I want to create a reusable upload feature for images and have created a partialView for this. On click, the partial is loaded via ajax call and the user can browse for an image, the chosen image is displayed and on submit the file should be passed to the controller but the url for submission is always a 404.

Load the Bootstrap Modal

<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="ajax-modal" data-target="#add-contact" data-url="@Url.Action("ShowModalUploadForm", new { Id= Model.Id })">
    Add contact
</button>

var placeholderElement = $('#modal-placeholder');
$(document).on('click', 'button[data-toggle="ajax-modal"]', function (event) {
    var url = $(this).data('url');
    $.get(url).done(function (data) {
        placeholderElement.html(data);
        placeholderElement.find('.modal').modal('show');
    });
});

This works...The issue is when I submit, the URL that is fored appears to not match what the controller is expecting

PartialView (omitted unnecessary portions)

<form id="UploadPhoto" asp-action="UploadPhoto" enctype="multipart/form-data" method="post">
    <input name="VolunteerId" id="VolunteerId" type="hidden" value="@Model" />
    <div class="col-md-12">
        <div class="form-group">
            <label>Upload Image</label>
            <div class="input-group">
                <span class="input-group-btn">
                    <span class="btn btn-default btn-file">
                        Browse… <input type="file" id="imgInp">
                    </span>
                </span>
                <input type="text" class="form-control" readonly>
            </div>
            <img id='img-upload' name='img-upload' />
        </div>
    </div>
</form>

$(document).on('click', '#btnSubmitUpload', function (event) {

    event.preventDefault();

    var form = $(this).parents('.modal').find('form');
    var dataToSend = new FormData(form.get(0));

    $.ajax({
        url: '@Url.Action("UploadPhoto", "Volunteer", new { Area = "Admin" })',
        method: 'post',
        data: dataToSend,
        processData: false,
        contentType: false
    }).done(function (data) {
          //Do stuff here
        }
    });
});

$(document).on('change', '.btn-file :file', function () {
    var input = $(this),
        label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
    input.trigger('fileselect', [label]);
});

$(document).on('fileselect', '.btn-file :file', function (event, label)  {

    var input = $(this).parents('.input-group').find(':text'),
        log = label;

    if (input.length) {
        input.val(log);
    } else {
        if (log) alert(log);
    }

});

$(document).on('change', '#imgInp', function () {
    readURL(this);
});

function readURL(input) {
    if (input.files && input.files[0]) {
        var reader = new FileReader();

        reader.onload = function (e) {
            $('#img-upload').attr('src', e.target.result);
        }

        reader.readAsDataURL(input.files[0]);
    }
}

VolunteerController

[HttpPost]
private async void UploadPhoto([FromForm] IFormFile file)
{
    //await _storage.SaveBlobAsync("volunteers", file, BlobType.Image);
}

Upvotes: 0

Views: 84

Answers (1)

Tupac
Tupac

Reputation: 2922

Open the F12 developer tools, where is your misalignment? Or we can also use the FormData object.

View:

@model ImageFileUpload.Models.Human

@{
    ViewBag.Title = "SaveData";
}

<h2>SaveData</h2>

<div>
    <a href="#" class="btn btn-primary" onclick="AddNewHuman()">Create New</a>
    <br /><br />
    <table class="table table-responsive">
        <thead>
            <tr style="background-color:#333;color:white;">
                <th>Human Name</th>
                <th>Human Image</th>
                <th>Human Phone</th>
                <th></th>
                <th></th>
            </tr>
        </thead>
        <tbody id="SetHumanList">
            <tr id="LoadingStatus"></tr>
        </tbody>
    </table>
</div>

@using (Html.BeginForm("SaveData", "Human", FormMethod.Post, new { id = "form", enctype = "multipart/form-data" }))
{
    <div class="modal fade" id="MyModal">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <a href="#" class="close" data-dismiss="modal">&times;</a>
                    <h4 id="ModalTitle"></h4>
                </div>

                <div class="modal-body">
                    <fieldset id="SubmitForm">
                        @Html.HiddenFor(a => a.HumanId, new { @id = "HumId" })
                        <div class="form-group">
                            @Html.TextBoxFor(a => a.HumanName, new { @id = "HumName", @class = "form-control", @placeholder = "Name" })
                        </div>
                        <div class="form-group">
                            <input type="file" id="UploadFile" name="Upload" class="form-control w" />
                        </div>
                        <div class="form-group">
                            @Html.TextBoxFor(a => a.HumanPhone, new { @id = "HumPhone", @class = "form-control", @placeholder = "Phone" })
                        </div>
                        <div class="form-group">
                            <button id="SaveRecord" type="button" class="btn btn-warning">Create</button>
                        </div>
                    </fieldset>
                </div>
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    <script src="~/Scripts/jquery.form.min.js"></script>

    @Scripts.Render("~/bundles/jqueryval")

    <script>
        function AddNewHuman() {
            $("#MyModal").modal("show")
        }

        $("#SaveRecord").click(function () {
            var formData = new FormData();

            formData.append("Upload", $('#UploadFile')[0].files[0]); //append the image file

            var other_data = $('form').serializeArray();
            $.each(other_data, function (key, input) { //append other input value
                formData.append(input.name, input.value);
            });

            $.ajax({
                type: "POST",
                url: "/Human/SaveData",
                data: formData,
                contentType: false, // Not to set any content header
                processData: false, // Not to process data
                success: function (result) {
                    alert("Success");
                    window.location.href = "/Human/index";
                    //$("#MyModal").modal("hide"); //this line is unnecessary because the user has been redirect
                }
            })
        });
    </script>
}

Result

Upvotes: 1

Related Questions