带模型的mvc上传文件 - 第二个参数发布文件为空

时间:2014-02-10 12:18:31

标签: c# asp.net asp.net-mvc asp.net-mvc-3 razor

我有一个带有1个字符串属性的简单模型,我在一个简单的视图上渲染。

视图如下所示:

@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { encType="multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.FirstName)
    <br /><br />

    <input type="file" name="fileUpload" /><br /><br />
    <input type="submit" value="submit me" name="submitme" id="submitme" />
}

控制器就是这样:

[HttpPost]
public ActionResult UploadFile(UploadFileModel model, HttpPostedFileBase file)
{
   // DO Stuff
   return View(model);
}

现在,当我提交时,模型DOES会被填充,但第二个参数是HttpPostedFileBase为null。但是,当执行Request.Files时 - 它似乎表明在发布的请求中有一个文件。 我怎么能真正得到第二个参数绑定?

4 个答案:

答案 0 :(得分:34)

为什么不将上传的文件添加到您的模型中,如下所示:

public class UploadFileModel 
{
    public UploadFileModel()
    {
        Files = new List<HttpPostedFileBase>();
    }

    public List<HttpPostedFileBase> Files { get; set; }
    public string FirstName { get; set; }
    // Rest of model details
}

然后将您的观点更改为:

@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { encType="multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.FirstName)
    <br /><br />

    @Html.TextBoxFor(m => m.Files, new { type = "file", name = "Files" })<br /><br />
    <input type="submit" value="submit me" name="submitme" id="submitme" />
}

然后您的文件将按如下方式发回:

public ActionResult UploadFile(UploadFileModel model)
{
    var file = model.Files[0];
    return View(model);
}

答案 1 :(得分:6)

将您的姓名file更改为fileUploadenctype将其更改为

@using (Html.BeginForm("UploadFile", "Home", FormMethod.Post, new { enctype="multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.FirstName)
    <br /><br />

    <input type="file" name="fileUpload" /><br /><br />
    <input type="submit" value="submit me" name="submitme" id="submitme" />
}

[HttpPost]
public ActionResult UploadFile(UploadFileModel model, HttpPostedFileBase fileUpload)
{
   // DO Stuff
   return View(model);
}

答案 2 :(得分:5)

要处理单个文件输入,您可以在 ViewModel 中定义HttpPostedFileBase属性:

public class SomeModel() 
{ 
    public SomeModel() 
    {
    }

    public HttpPostedFileBase SomeFile { get; set; }
}

然后按以下方式实施:

查看:

@model SomeModel

@using (Html.BeginForm(
    "Submit", 
    "Home", 
    FormMethod.Post, 
    new { enctype="multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.SomeFile, new { type = "file" })
    <input type="submit" value="Upload" 
        name="UploadButton" id="UploadButton" />
}

<强>控制器:

[HttpPost]
public ActionResult Submit(SomeModel model)
{
    // do something with model.SomeFile

    return View();
}

如果您需要处理多个文件,您可以:

  • 创建多个属性并单独实现它们,就像上面那样;
  • public HttpPostedFileBase SomeFile属性更改为public List<HttpPostedFileBase> SomeFiles,然后跨多个@Html.TextBoxFor(m => m.SomeFile, new { type = "file" })控件将所有属性都包含在该列表中。

如果您需要其他信息,请查看我就该主题撰写的this blog post

答案 3 :(得分:0)

或者,(如果可以接受)从模型中删除文件的[Required]验证注释,并在Controller操作中检查文件,如果找不到则添加错误:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ActionWithFileUpload(ViewModel viewModel)
{
    if (ModelState.IsValid)
    {
        if (Request.Files.Count > 0)
        {
            var postedFile = Request.Files[0];
            if (postedFile != null && postedFile.ContentLength > 0)
            {
                string imagesPath = HttpContext.Server.MapPath("~/Content/Images"); // Or file save folder, etc.
                string extension = Path.GetExtension(postedFile.FileName);
                string newFileName = $"NewFile{extension}";
                string saveToPath = Path.Combine(imagesPath, newFileName);
                postedFile.SaveAs(saveToPath);
            }
        }
        else
        {
            ModelState.AddModelError(string.Empty, "File not selected.");
        }
    }

    return RedirectToAction("Index"); // Or return view, etc.
}