Reputation: 18869
I have a page where you can edit a client. On this page, you can also upload files for a client. You click a button, a jQuery dialog opens, you upload a file, and click Save.
Here's my /Clients/Edit view:
<script type="text/javascript" language="javascript">
$(document).ready(function () {
// add file click event
$("a#addFile").click(function () {
$.ajax({
url: '@Url.Content("/ClientFiles/Create/")' + @Model.ClientId,
context: document.body,
success: function (data) {
// open dialog with Create partial view data
$("#dialog-add").html(data).dialog("open");
}
});
return false;
});
// add file dialog settings
$("#dialog-add").dialog({
modal: true,
buttons: {
"Save": function () {
$.validator.unobtrusive.parse("#AddFileForm");
if ($("#AddFileForm").valid()) {
$.post("/ClientFiles/Create", $("#AddFileForm").serialize(),
function (data) {
$("#dialog-add").dialog("close"); // close dialog
});
}
}
}
});
});
</script>
@using (Html.BeginForm("Edit", "Clients", FormMethod.Post))
{
@Html.HiddenFor(m => m.ClientId)
<a id="addFile">Add a new file</a>
<div id="dialog-add" title="" style="display:none"></div>
<input type="submit" value="Save" />
}
Here is my /ClientFiles/Create partial view:
@model Models.ClientFileViewModel
@using (Html.BeginForm("Create", "ClientFiles", FormMethod.Post, new { @id = "AddFileForm", enctype = "multipart/form-data" }))
{
@Html.ValidationSummary(true)
@Html.HiddenFor(model => model.ClientId)
@Html.TextBoxFor(model => model.ModelFile, new { type = "file" })
@Html.ValidationSummary()
}
Here's my ClientFileViewModel:
public class ClientFileViewModel
{
[ScaffoldColumn(false)]
public int ClientFileId { get; set; }
public int ClientId { get; set; }
public HttpPostedFile ModelFile { get; set; }
}
And finally, my ClientFilesController methods:
public ActionResult Create(int id)
{
return PartialView(new ClientFileViewModel { ClientId = id } );
}
public JsonResult Create(ClientFileViewModel viewModel)
{
if (ModelState.IsValid)
{
if (viewModel.ModelFile != null)
{
// upload file here
}
}
return Json(new { success = true });
}
So everything works up until I post to Create(ClientFileViewModel viewModel)
. When I go through the debugger, the view model contains ClientId
, but ModelFile
is null.
Am I doing something wrong that is causing the file to not be passed with the view model?
Upvotes: 2
Views: 2582
Reputation: 1039130
You should use the base class (HttpPostedFileBase
), i.e. replace:
public HttpPostedFile ModelFile { get; set; }
with:
public HttpPostedFileBase ModelFile { get; set; }
in your view model.
This being said, that's only half of your issues. You seem to be using an AJAX request to submit the form:
$.post("/ClientFiles/Create", $("#AddFileForm").serialize(),
You cannot use AJAX to upload files to the server. You could use some plugin such as jquery.form which supports file input fields and generates a hidden iframe to circumvent this limitation. So if you decide to use the plugin you could do the following to AJAXify it:
"Save": function () {
$.validator.unobtrusive.parse("#AddFileForm");
if ($("#AddFileForm").valid()) {
$("#AddFileForm").ajaxSubmit(function() {
$("#dialog-add").dialog("close");
});
}
}
Other popular plugins that allow you to upload files are Uploadify, Blueimp File Upload, Ajax Upload, ...
Upvotes: 5