MVC 3文件上传和模型绑定

我有一个形式上传的工作,但我想传递我的数据库模型信息,以保存文件与不同的名称当然。

以下是我对 Razor 的看法:

@model CertispecWeb.Models.Container


@{
ViewBag.Title = "AddDocuments";
}


<h2>AddDocuments</h2>


@Model.ContainerNo


@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
<input type='file' name='file' id='file' />
<input type="submit" value="submit" />
}

这是我的主管:

[HttpPost]
public ActionResult Uploadfile(Container containers, HttpPostedFileBase file)
{
if (file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/App_Data/Uploads"),
containers.ContainerNo);
file.SaveAs(path);
}


return RedirectToAction("Index");
}

模型信息不会传递给控制器。我读到我可能需要更新模型,我该怎么做呢?

106432 次浏览

Your form doesn't contain any input tag other than the file so in your controller action you cannot expect to get anything else than the uploaded file (that's all that's being sent to the server). One way to achieve this would be to include a hidden tag containing the id of the model which will allow you to retrieve it from your datastore inside the controller action you are posting to (use this if the user is not supposed to modify the model but simply attach a file):

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.HiddenFor(x => x.Id)
<input type="file" name="file" id="file" />
<input type="submit" value="submit" />
}

and then in your controller action:

[HttpPost]
public ActionResult Uploadfile(int id, HttpPostedFileBase file)
{
Containers containers = Repository.GetContainers(id);
...
}

On the other hand if you wanted to allow the user to modify this model then you will need to include the proper input fields for each field of your model that you want to be sent to the server:

@using (Html.BeginForm("Uploadfile", "Containers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.TextBoxFor(x => x.Prop1)
@Html.TextBoxFor(x => x.Prop2)
@Html.TextBoxFor(x => x.Prop3)
<input type="file" name="file" id="file" />
<input type="submit" value="submit" />
}

and then you will have the default model binder reconstruct this model from the request:

[HttpPost]
public ActionResult Uploadfile(Container containers, HttpPostedFileBase file)
{
...
}

If you won't always have images posting to your action, you can do something like this:

[HttpPost]
public ActionResult Uploadfile(Container container, HttpPostedFileBase file)
{
//do container stuff


if (Request.Files != null)
{
foreach (string requestFile in Request.Files)
{
HttpPostedFileBase file = Request.Files[requestFile];
if (file.ContentLength > 0)
{
string fileName = Path.GetFileName(file.FileName);
string directory = Server.MapPath("~/App_Data/uploads/");
if (!Directory.Exists(directory))
{
Directory.CreateDirectory(directory);
}
string path = Path.Combine(directory, fileName);
file.SaveAs(path);
}
}
}


}

Solved

Model

public class Book
{
public string Title {get;set;}
public string Author {get;set;}
}

Controller

public class BookController : Controller
{
[HttpPost]
public ActionResult Create(Book model, IEnumerable<HttpPostedFileBase> fileUpload)
{
throw new NotImplementedException();
}
}

And View

@using (Html.BeginForm("Create", "Book", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
@Html.EditorFor(m => m)


<input type="file" name="fileUpload[0]" /><br />
<input type="file" name="fileUpload[1]" /><br />
<input type="file" name="fileUpload[2]" /><br />


<input type="submit" name="Submit" id="SubmitMultiply" value="Upload" />
}

Note title of parameter from controller action must match with name of input elements IEnumerable<HttpPostedFileBase> fileUpload -> name="fileUpload[0]"

fileUpload must match

For multiple files; note the newer "multiple" attribute for input:

Form:

@using (Html.BeginForm("FileImport","Import",FormMethod.Post, new {enctype = "multipart/form-data"}))
{
<label for="files">Filename:</label>
<input type="file" name="files" multiple="true" id="files" />
<input type="submit"  />
}

Controller:

[HttpPost]
public ActionResult FileImport(IEnumerable<HttpPostedFileBase> files)
{
return View();
}

1st download jquery.form.js file from below url

http://plugins.jquery.com/form/

Write below code in cshtml

@using (Html.BeginForm("Upload", "Home", FormMethod.Post, new { enctype = "multipart/form-data", id = "frmTemplateUpload" }))
{
<div id="uploadTemplate">


<input type="text" value="Asif" id="txtname" name="txtName" />




<div id="dvAddTemplate">
Add Template
<br />
<input type="file" name="file" id="file" tabindex="2" />
<br />
<input type="submit" value="Submit" />
<input type="button" id="btnAttachFileCancel" tabindex="3" value="Cancel" />
</div>


<div id="TemplateTree" style="overflow-x: auto;"></div>
</div>


<div id="progressBarDiv" style="display: none;">
<img id="loading-image" src="~/Images/progress-loader.gif" />
</div>


}




<script type="text/javascript">


$(document).ready(function () {
debugger;
alert('sample');
var status = $('#status');
$('#frmTemplateUpload').ajaxForm({
beforeSend: function () {
if ($("#file").val() != "") {
//$("#uploadTemplate").hide();
$("#btnAction").hide();
$("#progressBarDiv").show();
//progress_run_id = setInterval(progress, 300);
}
status.empty();
},
success: function () {
showTemplateManager();
},
complete: function (xhr) {
if ($("#file").val() != "") {
var millisecondsToWait = 500;
setTimeout(function () {
//clearInterval(progress_run_id);
$("#uploadTemplate").show();
$("#btnAction").show();
$("#progressBarDiv").hide();
}, millisecondsToWait);
}
status.html(xhr.responseText);
}
});


});




</script>

Action method :-

 public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";


return View();
}


public void Upload(HttpPostedFileBase file, string txtname )
{


try
{
string attachmentFilePath = file.FileName;
string fileName = attachmentFilePath.Substring(attachmentFilePath.LastIndexOf("\\") + 1);


}
catch (Exception ex)
{


}
}