作为一个相当经验的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>
该视图是使用视图模型作为其模型:
@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样我已经通过,模型实例是“神奇”传递到操作方法作为参数,那么,为什么它现在空?
我认为真正的问题是我的MVC的了解有限,这有可能是一个非常简单的解决这个。 不管怎么说,我将非常感激,如果有人能在正确的方向指向我。
它一直以来我张贴的问题,这是非常我的MVC的一点经验和知识,有色一段时间。 尽管如此,我收到了一些非常有用的投入,最终导致我找到一个解决方案,也获得MVC的一些见解。
是什么把我关在首位,是你可以有一个强类型的对象作为参数,像这样的控制器:
public ActionResult DoSomething(MyClass myObject)...
这个对象源于同一个控制器:
...
return View(myObject);
...
这使我相信,对象遍及生活这两个步骤,并在某种程度上看我可以指望,你可以将它发送到视图,做一些事情,然后“神奇”又拿回来给控制器。
阅读了有关模型结合后,我明白,这当然并非如此。 的看法是完全死了,静态的,除非你的地方存储信息,就消失了。
回过头来看看这个问题,这是选择和从客户端上传文件,并建立这些文件的列表显示,我意识到,一般有存储请求之间的信息MVC三种方式:
- 你可以存储在视图中表单字段的信息,并张贴回控制器后
- 你可以在某些类型的存储坚持它,例如一个文件或数据库
- 您可以通过acessing是整个生活的要求,如会话变量对象在服务器内存中储存
就我而言,我有两种基本类型的信息坚持:1.文件元数据(文件名,文件大小等)2.文件内容
在“由这本书”的做法很可能是存储在表单字段中的元数据,并在文件或数据库文件的内容。 但也有另一种方式。 因为我知道我的文件非常小,会出现只有几个人,而这个解决方案绝不会在服务器农场或类似的部署,我想探索会话变量的#3选项。 该文件也没有兴趣后仍然保持会话 - 它们被处理和丢弃,所以我不想将它们存储在我的分贝。
:阅读这篇优秀的文章后访问使用ASP.NET动态数据会话
我相信。 我只是创造了一个sessionbag类的文章中描述,然后我可以做我的控制器中的以下内容:
[HttpPost]
public ActionResult AddImportFile(HttpPostedFileBase file)
{
ImportDataViewModel importData = SessionBag.Current.ImportData;
if (importData == null) importData = new ImportDataViewModel();
if (file == null)
return RedirectToAction("DataImport");
if (file.ContentLength > 0)
{
ImportDataFile idFile = new ImportDataFile { File = file };
importData.Files.Add(idFile);
}
SessionBag.Current.ImportData = importData;
return RedirectToAction("DataImport");
}
我充分认识到,在大多数情况下,这将是一个坏的解决方案。 但对于服务器内存的几KB的文件占用,并与这一切的简单,我觉得它的工作也很完美我。
使用SessionBag的额外的奖金是,如果用户输入不同的菜单项,然后回来,文件列表仍然会存在。 选择表单域/文件存储选项时,这不会是这种情况如。
作为最后的一句话,我意识到SessionBag是很容易被滥用,因为使用的简单性。 但是,如果你使用它这是什么意思了,即会话数据,我认为它可以是一个强大的工具。
关于上传
1)也许考虑的一个AJAX上传与HTML,让用户选择多个文件被发送到服务器之前 。 这BlueImp jQuery的AJAX文件上传是一个非常伟大的API相当惊人: Blueimp jQuery的文件上传 。 这将允许用户拖放或者多选择几个文件并编辑文件顺序,包含/排除等。然后,当他们是幸福的,他们可以按上传发送到您的控制器或上传处理操作在服务器端。
2)你可以尽一切坚持上传到数据库中,虽然你会被重新加载整个页面,写一些额外的视图模型和剃须刀代码来实现上市的效果。 这可能不会响应...
关于保持国家的WebForms / MVC
请求之间保持状态是有点黑魔法和妖术。 当进入ASP.NET MVC,去理解它是Web应用程序通信使用的请求和响应。 所以,去拥抱网络作为无状态,并从那里发展! 当你的模型是通过控制器发布的,它与控制器的任何变量一起消失了 ! 它消失之前。然而,您可以稍后在存储检索数据库的内容。
Web应用程序不能保持像桌面应用程序的真实状态。 方法有很多Ajax框架,以及人们使用的HTTP环境中模拟状态的一些巫毒工具。 和状态的模拟是唯一真正有状态的虚假模仿。 ASP.NET Web窗体试图通过一种从开发者隐藏HTTP的无状态特性的模拟状态最好就可以了。 您可以尝试使用自己的AJAX代码与Web窗体标记代码和自己的Ajax框架串联时碰到了很多头疼的。
我真的很高兴你正在学习MVC
所有的笑话放在一边,如果你的MVC / HTTP /无国籍的心态,这将是很容易的模式适用于像Ruby on Rails的,用SpringMVC(JAVA),则Django(蟒蛇),CakePHP的等其他超级流行的框架?这个简单的知识转让将帮助你成为一个更好的开发人员,在阿贾克斯真的够好。
我真的很高兴你正在学习MVC 3,我已经与几个实习的一些非常大的公司是曾与代码到处飞,这些疯狂的大ASP.NET Web窗体项目只是更改数据库中的几个数值(-_-')觉得我是用剪刀编织婴儿袜。 一个简单的错误的举动,一切都打破了。 这感觉就像在PHP开发,你出来出汗,真的不知道发生了什么,在哪一行。 这几乎是不可能的调试和更新。