【发布时间】:2012-05-25 14:23:52
【问题描述】:
作为一个相当有经验的 ASP.Net 开发人员,最近才开始使用 MVC,我发现自己正在努力将自己的思维方式从传统的“服务器控制和事件处理程序”的做事方式转变为更动态的 MVC 做事方式.我想我正在慢慢到达那里,但有时 MVC 的“魔法”会让我失望。
我目前的方案是创建一个网页,允许用户浏览本地文件,将其上传到服务器并重复此操作,直到他有一个文件列表可供使用。当他对文件列表(将显示在页面上的网格中)感到满意时,他将单击一个按钮来处理文件并提取一些将存储在数据库中的数据。
最后一部分不是那么重要,现在我正在努力解决一些琐碎的事情,比如建立一个文件列表,并在请求之间保留该列表。在传统方法中,这将非常简单——数据将保存在 ViewState 中。但在 MVC 中,我需要在控制器和视图之间传递数据,但我并不完全了解它应该如何工作。
我想我最好发布我相当不完整的编码尝试来解释问题。
为了保留我的文件列表数据,我创建了一个视图模型,它基本上是一个类型化的文件列表,以及一些额外的元数据:
public class ImportDataViewModel
{
public ImportDataViewModel()
{
Files = new List<ImportDataFile>();
}
public List<ImportDataFile> Files { get; set; }
...
在视图中,我有一个用于浏览和上传文件的表单:
<form action="AddImportFile" method="post" enctype="multipart/form-data">
<label for="file">
Filename:</label>
<input type="file" name="file" id="file" />
<input type="submit" />
</form>
视图使用 viewmodel 作为其模型:
@model MHP.ViewModels.ImportDataViewModel
这会将文件发送到我的操作:
public ActionResult AddImportFile(HttpPostedFileBase file, ImportDataViewModel importData)
{
if (file.ContentLength > 0)
{
ImportDataFile idFile = new ImportDataFile { File = file };
importData.Files.Add(idFile);
}
return View("DataImport", importData);
}
此操作返回 DataImport 页面的视图以及包含文件列表的视图模型实例。
这在一定程度上工作得很好,我可以浏览文件并上传它,我可以看到动作中的视图模型数据,然后如果我在视图中放置一个断点并调试“this.Model” ,一切都很好。
但是,如果我尝试上传另一个文件,在 AddImportFile 操作中放置断点时,importData 参数为空。所以视图显然没有将其模型的当前实例传递给动作。
在我经历过的MVC示例中,模型实例被“神奇”地作为参数传递给action方法,那为什么现在是空的呢?
我认为真正的问题是我对 MVC 的理解有限,并且可能有一个非常简单的解决方案。无论如何,如果有人能指出我正确的方向,我将非常感激。
【问题讨论】:
-
您没有将上传的文件存储在服务器上的任何位置。您如何期望它们在回发之间持续存在?您在
<form>中拥有的只是一个文件输入字段。所以你可以期望在控制器动作中得到的就是这个文件。而已。没有魔法。 ASP.NET MVC 中没有 ViewState。 -
达林,感谢您的评论。我没有将文件存储在服务器上是正确的。我可以将它存储在数据库中,但这会浪费数据库空间和用户耐心,因为它需要很长时间并且没有真正的需要。我想做的只是以某种方式将它作为变量保存在服务器内存中,直到用户决定处理它。然后我将该处理的输出存储到数据库中。我想要么我试图以错误的方式使用 MVC,要么我只是不知道该怎么做。我只是不知道它是哪一个......
-
将文件保存在服务器内存中是最糟糕的事情之一。不惜一切代价避免这种情况。这不仅会消耗服务器上的大量内存,而且不要忘记 IIS 可以随时回收应用程序域,从而丢失存储在内存中的所有数据。另外,如果您在服务器场中运行怎么办?如果您存储在服务器的内存中,这意味着场中只有一台服务器具有此信息,如果负载平衡器在场的另一台服务器上调度后续请求,您将丢失信息。
-
阅读这些“老”问题很有趣,想想世界在短短五年内发生了多大的变化!从那时起,我已经多次处理文件上传问题,现在我对它的看法与当时大不相同。我同意 Steves 的建议,即暂时存储文件可能是最好的选择,尽管我倾向于使用 Azure blob 存储而不是 Web 服务器上的文件夹。哎呀,我什至不再使用 IIS,它只是 Azure Web 应用程序或 Azure 函数。
-
我也收回了我之前关于在内存中存储东西的说法,我几乎不敢相信我真的认为这是个好主意! :) 我认为,为我辩护,有问题的应用程序是一个小型企业应用程序,用户很少,文件也很小,但是,我今天绝不会想到这样做!我想我们都应该感谢能够回顾过去的可怕错误并得出结论,从那时起我们已经发展了很多:) 干杯!
标签: asp.net-mvc action viewmodel state