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