0

I've a user profile form having basic Name, Contacts fields with an option of Attachments (Images/ Files etc.). This form is bind with a custome viewModel that is working perfectly for all fields except input type=file

Here is my html code;

<div class="form-group">
                    <label>First Name*</label>

                    <input asp-for="systemUser.FirstName" class="form-control" />
                </div>

                <div class="form-group">
                    <label>Middle Name*</label>
                    <input asp-for="systemUser.MiddleName" class="form-control" />
                </div>

                <div class="form-group">
                    <label>Last Name*</label>
                    <input asp-for="systemUser.LastName" class="form-control" />
                </div>

   <div class="panel panel-default">
            <div class="panel-heading">
                <i class="fa fa-edit"></i>
                <b class="panel-title"> Contact Info. </b>
            </div>
            <div class="panel-body">
                <div class="form-group">
                    <label>Description</label>
                    <input asp-for="userContactDetail.ContactDescription" class="form-control" />
                </div>

                <div class="form-group">
                    <label>Type</label>
                    <select class="form-control" asp-for="userContactDetail.ContactTypeId" asp-items="@(new SelectList(Model.contactTypes, "Id", "Name"))"><option value="-1"></option></select>
                </div>
                <div class="form-group">
                    <label>Contact Number</label>
                    <input asp-for="userContactDetail.ContactNumber" class="form-control" />
                </div>
                <div class="form-group">
                    <label>Extension</label>
                    <input asp-for="userContactDetail.ContactExtension" class="form-control" />
                </div>
                <div class="row">
                    <label class="col-sm-6 form-group">
                        <input type="checkbox" asp-for="userContactDetail.PrimaryContact" />
                        Primary
                    </label>
                    <label class="col-sm-6 form-group">
                        <input type="checkbox" asp-for="userContactDetail.PrivateContact" />
                        Private
                    </label>
                </div>
                <div class="form-group">

                </div>
                <div class="form-group pull-right">
                    <button id="btnAddContact" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Add</button>
                    <button id="btnCancelContact" class="btn btn-sm btn-danger"><i class="fa fa-ban"></i> Cancel</button>
                </div>
            </div>
            <div class="form-group panel-body">
                <div class="table-responsive">
                    <table class="table table-striped table-bordered table-hover" id="tblContacts" name="tblContacts">
                        <thead class="bg-primary">
                            <tr>
                                <th>Description</th>
                                <th>Type</th>
                                <th>Contact Number</th>
                                <th>Extension</th>
                                <th>Primary</th>
                                <th>Private</th>
                                <th></th>
                                <th hidden></th>
                            </tr>
                        </thead>
                        <tbody>


                            @for (int i = 0; i < Model.lstContacts.Count; i++)
                            {
                                <tr>
                                    <td hidden>@Html.HiddenFor(con => Model.lstContacts[i].UserContactDetailId)</td>
                                    <td hidden>@Html.HiddenFor(con => Model.lstContacts[i].ContactDescription)</td>
                                    <td>@Html.DisplayFor(con => Model.lstContacts[i].ContactDescription)</td>
                                    <td hidden> @Html.HiddenFor(con => Model.lstContacts[i].ContactTypeId) </td>
                                    <td> @Html.DisplayFor(con => Model.lstContacts[i].ContactTypeName) </td>
                                    <td hidden> @Html.HiddenFor(con => Model.lstContacts[i].ContactNumber)</td>
                                    <td> @Html.DisplayFor(con => Model.lstContacts[i].ContactNumber)</td>

                                    <td hidden> @Html.HiddenFor(con => Model.lstContacts[i].ContactExtension) </td>
                                    <td> @Html.DisplayFor(con => Model.lstContacts[i].ContactExtension) </td>
                                    <td hidden> @Html.HiddenFor(con => Model.lstContacts[i].PrimaryContact)</td>
                                    <td> @Html.DisplayFor(con => Model.lstContacts[i].PrimaryContact)</td>
                                    <td hidden> @Html.HiddenFor(con => Model.lstContacts[i].PrivateContact)</td>
                                    <td> @Html.DisplayFor(con => Model.lstContacts[i].PrivateContact)</td>

                                    <td>
                                        <a onclick="EditUserContact(this)" class="btn-sm btn-primary" style="margin:2px;">
                                            <i class="fa fa-folder-open"></i> Edit
                                        </a>
                                        <a onclick="DeleteUserContact(this)" class="btn-sm btn-danger" style="margin:2px;">
                                            <i class="fa fa-ban"></i> Delete
                                        </a>
                                    </td>
                                    <td hidden>@Html.HiddenFor(con => Model.lstContacts[i].IsDeleted)</td>
                                </tr>

                            }
                        </tbody>
                    </table>
                </div>
            </div>
        </div>

 <div class="panel panel-default">
                <div class="panel-heading">
                    <i class="fa fa-edit"></i>
                    <b class="panel-title"> Attachment </b>
                </div>
                <div class="panel-body">
                        <input type="file" name="file" asp-for="lstAttachments" accept="application/pdf,application" multiple/>

                </div>
            </div>

 <button type="submit" id="btnUpdateProfile" class="btn btn-success">Update Profile</button>

this is how I'm submitting my form

$('#btnUpdateProfile').click(function (e) {
    e.preventDefault();
var formData = $("#formUpdateProfile").serialize();

$.ajax({
        url: "/Admin/UpdateProfile",
        type: "POST",
        data: formData,
        processData : false,
        contentType: false,//'application/x-www-form-urlencoded; charset=utf-8',
        dataType: "json",
        success: function (data) {
            toastr.clear();

            if (data.status == "Success")
            {
                toastr.success("User updated sucessfully.");
                return;

            }
            else
            {
                toastr.error(data.message);
                return;

            }

        },
        error: function () {
            toastr.clear();
            toastr.error("Something went wrong. Please try again.");
            return;
        }
    });

When I submit my form, I always get lstAttachments empty in my controller while other data is perfectly correct. I've tried many solutions like

Added a for loop and changed .serialize() to .serializeArray() for object reference in a .each() to append to the FormData. but it didn't work for me. Then i tried this way;

var fd = new FormData();

var file_data = object.get(0).files[i]; //get file data
var other_data = $('form').serialize();  // get form data

fd.append("file", file_data);

but again, no help to resolve my issue... Can someone explain what I'm missing? Any Kind of help will be appreciated.

Update

This is my form tag

<form asp-action="UpdateProfile" method="post" id="formUpdateProfile" enctype="multipart/form-data">
7
  • 1
    You need to use FormData - refer how to append whole set of model to formdata and obtain it in MVC - var formdata = new FormData($('#formUpdateProfile').get(0)); Commented Apr 20, 2017 at 18:20
  • I've also tried with FormData but it does not pass any single value on submit Commented Apr 20, 2017 at 18:24
  • Read the dupe ! Commented Apr 20, 2017 at 18:26
  • My bad. I was missing # sign with form name. but problem is still there. I'm getting all data except lstAttachments. Its always null. Commented Apr 20, 2017 at 18:31
  • 1
    Then what is property lstAttachments and why have you given it a different name attribute? (and why in the world are you generating all those hidden inputs for properties of lstContacts) Commented Apr 20, 2017 at 18:36

1 Answer 1

2

You need to use FormData, but each individual name/value needs to be added to FormData. You can simply use

var formdata = new FormData($('#formUpdateProfile').get(0));

which will serialize all your form controls, including the file input, and then you ajax call is

$.ajax({
    url: "/Admin/UpdateProfile", // recommend you use '@Url.Action("UpdateProfile", "Admin")'
    type: "POST",
    data: formData,
    processData : false,
    contentType: false,
    dataType: "json",
    success: function (data) {

However, your giving your file input a name attribute which does not relate to your model property. Change the html to remove the name="file" attribute so that the correct attribute (name="lstAttachments") is generated for model binding

<input type="file" asp-for="lstAttachments" accept="application/pdf,application" multiple/>
Sign up to request clarification or add additional context in comments.

Comments

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.