【问题标题】:File upload problem/bug in MVC 3MVC 3 中的文件上传问题/错误
【发布时间】:2011-09-12 19:00:26
【问题描述】:

我在 ASP.NET MVC 3 中的文件上传遇到了最奇怪的问题。当我使用 Razor 使用默认项目模板(Internet 应用程序)启动一个新项目并将以下内容添加到 /views/home/index.cshtml

<form action="/Home/Index" method="post" enctype="multipart/form-data">
  <input type="file" name="upfile" />
  <input type="submit" value="post" />
</form>

每当我尝试上传文件时,上传都会失败(萤火虫显示状态“已中止”)。一些额外的信息:

  • Windows 7 / 64 位
  • 卡西尼
  • VS SP1
  • Firebug 6.0.2 和 IE8 都会出现这种情况

控制器代码:

public class HomeController : Controller {
    public ActionResult Index() {
        ViewBag.Message = "Welcome to ASP.NET MVC!";

        return View();
    }

    public ActionResult About() {
        return View();
    }

}

我已经调试了一段时间,并且已经发现了以下内容:

  • 它只发生在文件 > ~120kb
  • 如果我添加一个带有属性 [HttpPost] 的目标 Action 上传成功
  • 如果我使用 fiddler 调试(代理)上传成功
  • 如果我使用aspx并添加相同的代码,上传成功
  • 对于 aspx/razor,所有文件都是相同的,除了(当然)/Views 中的文件而不是 /Views/Web.config 中的文件

有没有其他人遇到过这个问题,是什么原因造成的?

更新:我知道我应该使用单独的操作并用 HttpPost 标记它,这不是我问这个问题的原因。我正在寻找原因为什么这不起作用,而不是如何解决它。

【问题讨论】:

  • “如果我添加一个具有属性 [HttpPost] 的目标操作上传成功” 此处可能是一个愚蠢的问题,但您是否尝试将此发布到未明确标记为 HttpPost 的操作?如果是,有什么理由不想将其标记为 HttpPost?
  • 所以当你做推荐的事情时(用 post/get/etc 装饰你的方法)它有效吗?去搞清楚?发布您的控制器代码怎么样?
  • 这确实是我想要做的。我可以将其标记为 HttpPost,但我不应该这样做。我只是想弄清楚这种行为是设计使然(这似乎不太可能,因为没有任何错误报告),还是其他原因。
  • 不,您不必“必须”,但可以 - 您“应该”将其标记为 httppost。如果你是回帖,你应该用[HttpPost]标记,你不应该为Get/Post共享相同的方法。它不是标准的,很容易导致问题。不 - 你没有“必须”,但你真的不应该。我怎么强调都不过分。如果您想采用其他方法共享相同方法,我无法提供其不起作用的内部原因,但恕我直言,当您偏离众所周知的推荐做法时,这只是一个教育问题。

标签: asp.net asp.net-mvc upload razor


【解决方案1】:

没有看到你的代码,我假设你有一个方法 HttpGet 你的默认 /home/index

您需要在某处发布此内容,而这与您的控制器方法不同。您应该有一个带有 [HttpPost] 的单独方法(用于发布/获取/更新/删除的单独控制器方法)

编辑澄清: 为您的发布操作创建一个单独的方法。您不应该为获取/发布共享相同的方法。 此外,您正在从您的帖子中返回一个视图。通常也不建议这样做,因为 MVC 需要 PRG(重定向后获取)行为,因此理想情况下您希望在完成后重定向回操作。 这里也支持使用 Post(以及网络上的许多其他帖子)

File upload MVC

在您上面的情况下,它可以正常工作,因为它很简单,没有验证,但是如果您在文件上传之前在页面上进行了验证,如果您发回并且不重定向回操作,事情很容易变得愚蠢。

【讨论】:

  • 我的 Home.Index 方法确实没有任何动词过滤器属性。但是,据我所知,上传文件不需要 HttpPost 过滤器,或者任何用于任何操作的过滤器。
  • 如果你在 MVC 中回发,你应该装饰你的动作方法。这是一种标准做法。不,它不是必需的,但强烈推荐,因为运行时可能没有选择正确的方法。可能会错误地将发布操作转到用于 GET 操作的操作方法,这在此处可能是可能的 - 但您根本不需要发布任何代码 - 我们在某种程度上对您正在做的事情进行有根据的猜测
  • 没有帮助。当我在操作上指定 HttpPost 时,我已经发布了它。
  • 我确切地指定了我所做的,“当我使用 Razor 使用默认项目模板(Internet 应用程序)启动一个新项目并将以下内容添加到 /views/home/index.cshtml 时”。这应该可以让您了解我正在使用的确切代码
  • 好的——我的回答是正确的。您使用的方法与用于 GET 方法的方法相同。不管它不起作用的原因,你都不应该这样做。创建一个新方法并像 MVC 推荐的那样使用 HttpPost。如果它不起作用,请告诉我们,但就目前而言,您的代码已被编码为“不应编码”的方式
【解决方案2】:

强烈建议单独处理文件上传:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Index(HttpPostedFileBase upfile)
    {
        // TODO: process the uploaded file here
        if (upfile != null && upfile.ContentLength > 0) 
        {
            var fileName = Path.GetFileName(upfile.FileName);
            var path = Path.Combine(Server.MapPath("~/App_Data"), fileName);
            upfile.SaveAs(path);
        }
        return RedirectToAction("Index");
    }
}

另外,请务必查看following blog post

【讨论】:

    【解决方案3】:

    您是否确保在 Web.config 中正确设置了 MaxRequestStringLength?

    这通常是我遇到这个问题的时候。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-08-12
      • 1970-01-01
      • 2012-05-23
      • 2010-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多