【问题标题】:mvc upload file with model - second parameter posted file is null带有模型的 mvc 上传文件 - 第二个参数发布的文件为空
【发布时间】:2014-03-07 18:35:02
【问题描述】:

我有一个带有 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);
}

现在,当我提交时,模型确实被填充,但第二个参数 HttpPostedFileBase 为空。但是,在执行 Request.Files 时 - 它似乎确实显示正在发布的请求中有一个文件。 我如何才能真正获得要绑定的第二个参数?

【问题讨论】:

  • 绑定是按名称进行的,由于您在输入标记上有name="fileUpload",因此您的操作方法的第二个参数应命名为相同的名称,即HttpPostedFileBase fileUpload

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


【解决方案1】:

为什么不像这样将上传的文件添加到您的模型中:

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);
}

【讨论】:

  • 有趣。这行得通。谢谢!但是为什么它不会绑定到第二个参数仍然没有意义。不过我想要一个解释。
  • 只是在等待它让我接受答案 - 全部完成。我同意你的观点,VM 方法。只是......令人难以置信为什么它不会绑定第二个参数。
  • 为什么使用 HttpPostedFileBase 而不是 HttpPostedFile?
  • 参考 m.Files.Files 不正确。提交编辑
  • 需要添加 HTML5 多个属性,如果你想选择多个具有相同输入控件的文件@Html.TextBoxFor(m =&gt; m.Files, new { type = "file", multiple = "multiple", name = "Files" })
【解决方案2】:

为了处理单个文件输入,您可以在 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&lt;HttpPostedFileBase&gt; SomeFiles 之类的属性,然后跨越多个@Html.TextBoxFor(m =&gt; m.SomeFile, new { type = "file" }) 控件以将它们全部包含在该列表中。

如果您需要更多信息,请查看我在该主题上写的 this blog post

【讨论】:

    【解决方案3】:

    把你的名字 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);
    }
    

    【讨论】:

    • @Ahmedilyas 我不知道为什么它不适合你。它完全适合我。
    • 这种方法是我一直在寻找的,直接的方法,我有问题的解决方案中缺少的部分是 BeginForm 中的 "enctype="multipart/form-data" }" :-/。
    【解决方案4】:

    或者,(如果可以接受)从模型中删除文件的 [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.
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      • 2013-05-29
      • 1970-01-01
      • 1970-01-01
      • 2015-05-29
      相关资源
      最近更新 更多