有什么好理由使用FormCollection而不是ViewModel?

我已经inheritance了使用ASP.Net MVC 4编写的代码库。每个post方法都需要一个FormCollection 。 除了不得不通过带引号的string来访问这些值以外,还会导致一些缺陷,例如无法在我的ViewModel属性中使用像ModelState.IsValid[AllowHtml]属性。 他们实际上为每个视图都创build了ViewModel类(尽pipe它们几乎只是实际的Entity Framework Model类的直接包装),但它们仅用于GET方法。

有什么我失踪的FormCollection,给出了一个原因,为什么这可能实际上是一个好主意? 这似乎只有缺点。 我想通过使用ViewModels来修复它。 这将需要很多的工作,因为ViewModel的属性是接口,而不是具体的类,这意味着要么写自定义绑定或更改ViewModels。

但也许有什么我失踪的地方使用FormCollection是有道理的?

有什么好理由使用FormCollection而不是ViewModel?

不,我有以下问题。

问题 – 1

如果正在使用FormCollection …强制Type Cast强制转换基Primitive Type值不一定是因为在获取System.Collections.Specialized.NameValueCollection的特定索引的条目时,返回的值是Stringtypes。 在强typesView-Models情况下,这种情况不会出现。

问题-2

当您提交表单并转到“ Post操作方法”,并在“操作”方法中存在“作为参数的View-Model ”时,您将有条件将“发布的值”发送回您的“ View 。 否则,再次编写代码通过TempData/ViewData/ViewBag发回

在这里输入图像描述

视图模型是普通的类,创build用于将数据绑定到视图

问题-3

我们有可以在View ModelCustom Validations实现的数据注解。

在这里输入图像描述

ASP.Net MVC使用数据注解简化了模型的有效性。 数据注释属性是应用于属性的属性。 我们可以通过inheritance内置的Validation Attribute类来创build自定义的validation属性。

问题-4

例如你有以下的HTML

 <input type="text" name="textBox1" value="harsha" customAttr1 = "MyValue" /> 

问题 :我们如何从上面例如从控制器内部访问customAttr1的值

答案 :当表单被发布时,只有元素的名称和值被发回服务器。

替代scheme :使用一点jQuery来获取自定义属性值,并将其与表单值一起发送到操作方法

另一个select是宁愿把你的自定义属性隐藏在控件中

这是原因,我总是喜欢使用View-Models

我能想到的唯一的好处是,如果你想使用自动生成的控制器,当你没有指定一个强制types的EF模型。 在这种情况下,您的创build和编辑操作将使用FormCollection对象,因为它是框架的可靠的,预先存在的工件,用于此目的。 也许以前的开发者在创build他的控制器的时候select了这个选项,并且坚持使用它,因为Visual Studio必须知道它在做什么:)

但是,实际上,我绝不会推荐几秒钟的这种头马。 build立视图模型总是比较好,如果仅仅是为了维护目的,我会build议看看朝着这个方向移动的努力。 使用模型绑定和强types化视图和html助手,你更有可能减less运行时错误的数量,因为改变了一些魔术string,直到页面被炸掉才实现。

好吧,我看到这里的普遍共识是它不被喜欢。 为了提供另一个angular度,我一直喜欢使用通过POST操作传递给控制器​​的formcollection。 它提供了使用控制器的TryUpdateModel方法,该方法将集合映射到强types的类。 TryUpdateModel也有重载,允许你列出你想允许更新模型的属性。

 if (TryUpdateModel(viewModel, new string[] { "Name" })) { //Do something } 

它仍然允许所有的模型绑定你想要的,但有助于保持除了我的viewmodel“名称”属性更新。

您可以在这里看到有关TryUpdateModel方法的更多信息:

http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.tryupdatemodel(v=vs.108).aspx

总是有解决方法离开FormCollection大声笑..你可以隐藏字段绑定到您的视图模型variables的forms到你的心的内容。

表单集合大部分来自于创build视图模型的懒惰,但最终还是花费时间来弄清楚如何从控制器中获取值:P

我认为它只是在MVC的开始时创build的,作为使用强types视图时的一种替代方法,当使用非常简单的forms时 – 早在大家使用ViewBag的时候:) …一旦它们在那里它们不能把它拿出来就这么简单

也许你可以使用它,如果你绝对确信你的观点永远不会有多个表单input? 虽然可能还是一个坏主意..

我无法find任何最近的文章谈论表单集合的任何优点..而强types的观点无处不在。

是。 有时候,这可能是有用的。 这是一个例子:

比方说,我们在我们的数据库“ date_and_time_field ”。

在Razor视图中,我们要使用两个表单域。 第一个“date”(也许与jQuery UI Datepicker)。 第二个“小时”。

在Controller Action中,我们通过Request.Form["Date"]Request.Form["Hour"] 组成 “date_and_time_field”。

还有其他的情况下,它可以是有用的:

  • 一个交叉表(带有剃刀视图中的checkbox)

  • 集合Request.Unvalidated().Form (也许这不是你的问题的一部分:我不想成为脱离主题)

默认的模型联编程序将完成您需要的所有操作。 我诉诸FormCollection一次 – 只是以后找出如何将元素的数组绑定到ViewModel的集合。

只要去ViewModel 。 列举的每一个理由都是更好的。

通过form collection您将能够获取表单中的所有值。 可能会出现以下情况,您可能需要从表单中传递一些附加值,这些值可能不是view model一部分。

只需要从表单中传递10个隐藏值的例子。 表单集合是有意义的。

你可能要面对的唯一困难是types铸造。 所有表单收集项目将是string; 您可能需要根据您的要求进行type cast

模型状态validation也是您可能面临挑战的另一个领域。

您始终可以将表单集合属性添加到您的方法签名。 他们将自动填充与相应的键的表单值。

那么与表单集合,你会发现一个快速的方式来获取表单的值。 否则,您必须创build一个模仿Form Fields的类,并且人们有时懒得为较不重要/很less使用的Forms创build自定义类。

不,没有额外的利益(实际上是有限的)表单集合作为行为参数的自定义类,它应尽可能避免。

回答标题问题:是的。

有一些FormCollection需要使用的情况。 例如,假设一个具有实现1到N关系的属性的ViewModel (在具体情况下,具有ICollection<TimesheetEntryViewModel> ),并且控制器必须在时间条目之间执行validation以在时间条件之间不进行时间冲突条目的结束时间和以下条目的开始时间。 要标记具有validation错误的相关条目,如何检索行索引?

那么,在默认的模型绑定下,索引值在控制器逻辑中丢失。 幸运的是, FormController存储你在View中使用的索引,并且可以完成更具体的validation。