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

时间:2021-03-10 11:50:02

I've inherited a code base written in ASP.Net MVC 4. Every post method takes a FormCollection. Aside from annoyance of having to access the values through quoted strings, it also leads to drawbacks such as not being able to use things like ModelState.IsValid, or [AllowHtml] attributes on my ViewModel properties. They actually did create ViewModel classes for each of their views, (though they are pretty much just direct wrappers around the actual Entity Framework Model classes), but they are only used for the GET methods.

我继承了一个用ASP编写的代码库。净MVC 4。每个post方法都有一个FormCollection。除了必须通过引用字符串访问值的烦恼之外,它还会导致一些缺点,比如不能使用诸如ModelState之类的东西。我的ViewModel属性上的[AllowHtml]属性是有效的。实际上,他们确实为每个视图创建了ViewModel类,(尽管它们在实际的实体框架模型类中几乎是直接的包装器),但是它们只用于GET方法。

Is there anything I'm missing about FormCollection that gives a reason why this may have actually been a good idea? It seems to only have drawbacks. I'd like to go through and "fix" it by using ViewModels instead. This would take a good bit of work because the ViewModels have properties that are interfaces and not concrete classes, which means either writing a custom binder or changing the ViewModels.

关于FormCollection,我有什么遗漏吗?有什么原因可以解释为什么这可能是个好主意?它似乎只有缺点。我想通过使用ViewModels来“修复”它。这需要做很多工作,因为viewmodel具有接口属性,而不是具体的类,这意味着要么编写自定义绑定,要么修改viewmodel。

But perhaps there's something I'm missing where it makes sense to use FormCollection?

但是也许我遗漏了一些东西,在哪里使用FormCollection是有意义的?

10 个解决方案

#1


44  

Is there any good reason to use FormCollection instead of ViewModel?

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

No. I have following issues.

不。我有以下问题。

Issue - 1

问题- 1

In case FormCollection is being used...It will be mandatory to Type Cast the Primitive Type Values un-necessarily because while getting the entry of specific Index of the System.Collections.Specialized.NameValueCollection, value being returned is of type String. This situation will not come in case of Strongly Typed View-Models.

如果正在使用FormCollection……强制类型强制强制强制强制转换基本类型值,因为在获取System.Collections.Specialized.特殊化的特定索引时。NameValueCollection,返回的值是字符串类型。这种情况在强类型的视图模型中不会出现。

Issue - 2

问题- 2

When you submit the form and goes to Post Action Method, and View-Model as Parameter exists in the Action method, you have the provision to send back the Posted Values to you View. Otherwise, write the code again to send back via TempData/ViewData/ViewBag

当您提交表单并转到Post操作方法,并且Action方法中存在作为参数的视图模型时,您可以将已提交的值发送回您的视图。否则,再次编写代码,通过TempData/ViewData/ViewBag返回

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

View-Models are normal classes, created to bind data to-from Views

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

Issue - 3

问题- 3

We have Data Annotations that can be implemented in View Model or Custom Validations.

我们有可以在视图模型或自定义验证中实现的数据注释。

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

ASP.Net MVC simplifies model validatons using Data Annotation. Data Annotations are attributes thyat are applied over properties. We can create custom validation Attribute by inheriting the built-in Validation Attribute class.

ASP。净MVC validatons使用数据注释简化模型。应用数据注释属性thyat属性。我们可以通过继承创建自定义验证属性内置的验证属性类。



Issue - 4

问题- 4

Example you have the following HTML

例如,您有以下HTML

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

Question : How can we access the value of customAttr1 from the above eg from inside the controller

问题:如何从上面的(如从控制器内部)访问customAttr1的值

Answer : When a form get posted only the name and value of elements are posted back to the server.

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

Alternatives : Use a bit of jQuery to get the custom attribute values, and post that along with the form values to action method

备选方案:使用一点jQuery来获取自定义属性值,并将其与表单值一起发布到action方法

Another option is to rather put what you got in your custom attributes in hidden controls

另一种选择是将在自定义属性中获得的内容放到隐藏控件中




That's the reason, I would always prefer to use View-Models

这就是为什么我总是喜欢使用视图模型

#2


6  

The only advantage I can think of is if you want to use the automatically generated controller provided when you don't specify a EF model to be strongly typed to. In that case, your Create and Edit actions will use the FormCollection object as it is a reliable, pre-existing artifact of the framework to work with for this purpose. Perhaps the previous developer chose this option while creating his controllers, and stuck with it since Visual Studio must know what it's doing :)

我能想到的唯一优点是,如果您希望使用在不指定要强类型输入的EF模型时提供的自动生成的控制器。在这种情况下,您的创建和编辑操作将使用FormCollection对象,因为它是框架的一个可靠的、预先存在的工件,可以用于此目的。也许之前的开发人员在创建控制器时选择了这个选项,并坚持使用它,因为Visual Studio必须知道它在做什么:)

But, in reality, I would never recommend this headstart of a few seconds. It's always better to build out viewmodels, I would recommend looking at the effort to move in that direction if only for maintenance purposes. With model binding and strongly typed views and html helpers, you are much more likely to reduce the number of run-time errors as a result of changing some magic string and not realizing it until your page blows up.

但是,实际上,我永远不会推荐这种提前几秒钟开始的做法。构建视图模型总是更好的,我建议您考虑一下,如果只是为了维护目的,就应该朝着这个方向努力。使用模型绑定、强类型视图和html helper,您更有可能减少运行时错误的数量,因为更改了一些魔术字符串,直到页面崩溃时才实现。

#3


5  

Ok, I see the general consensus here is that it isn't liked. To offer another perspective, I've always liked using the formcollection passed into the controller on POST actions. It offers the use of the TryUpdateModel method from the controller which will map the collection to your strongly typed class. TryUpdateModel also has overloads that allow you to white list the properties of the model that you want to allow to be updated.

好吧,我认为大家都认为它不受欢迎。为了提供另一种视角,我一直喜欢在POST操作中使用传递给控制器的formcollection。它提供了来自控制器的TryUpdateModel方法的使用,该方法将集合映射到强类型类。TryUpdateModel也有重载,允许您将想要更新的模型的属性设置为白色。

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

It still allows all the model binding you want, but helps to keep anything other than the "Name" property on my viewmodel from being updated.

它仍然允许您想要的所有模型绑定,但是有助于避免更新我的viewmodel上的“Name”属性以外的任何内容。

You can see more about the TryUpdateModel method here:

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

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

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

#4


2  

There are always workarounds for getting away from a FormCollection lol.. you can have hidden fields bound to your view model variables in the form to your heart's content.

要想摆脱格式收集,总是有办法的。您可以将隐藏字段绑定到视图模型变量的表单中,并将其绑定到您的核心内容。

Form collections mostly emerge from the laziness of creating a view model but still end up taking time trying to get figure out how to get the values out of it in your controller :P

表单集合主要是由于创建视图模型的惰性而产生的,但最终还是要花时间试图弄清楚如何从控制器P中获取值

I think it was simply created in the very beginning of MVC as an alternative to using strongly typed views when having very simple forms - back in the days when everyone used ViewBag :) ... and once hey had it in there they couldn't just take it out as simple as that.

我认为它仅仅是在MVC的一开始就创建的,作为在拥有非常简单的表单时使用强类型视图的一种替代方法——在过去每个人都使用ViewBag:)……一旦有了它,他们就不能这么简单地把它取出来。

Maybe you can use it if you are absolutely sure your view will never have more than one form input? Probably still a bad idea though..

如果你确定你的视图永远不会有一个以上的表单输入,也许你可以使用它?也许还是个坏主意。

I cant find any recent articles talking about any advantages of form collections.. while strongly typed views are everywhere.

我找不到任何有关收集表格的优点的文章。强类型视图随处可见。

#5


2  

Yes. Sometimes, it can be useful. Here's an example:

是的。有时候,它是有用的。这里有一个例子:

Let's say we have in our db "date_and_time_field".

假设我们在db中有date_and_time_field。

In Razor View, we want to use two form fields. The first one "Date" (maybe with jQuery UI Datepicker). The second one "Hour".

在Razor视图中,我们要使用两个表单字段。第一个“Date”(可能是jQuery UI Datepicker)。第二个“小时”。

In the Controller Action, we compose the "date_and_time_field" by means of Request.Form["Date"] and Request.Form["Hour"].

在控制器动作中,我们通过请求组成“date_and_time_field”。形式(“日期”)和Request.Form(“小时”)。

There are other scenarios where it can be useful:

也有其他可能有用的情况:

  • A cross-table (with checkBoxes in Razor view)

    交叉表(在Razor视图中带有复选框)

  • The collection Request.Unvalidated().Form (maybe this is not part of your question: I don't wanna be off-topic)

    收集Request.Unvalidated()。形式(也许这不是你问题的一部分:我不想离题)

#6


2  

The default model binder will do almost everything you need it to do. I resorted to the FormCollection once - only to later figure out how to bind arrays of elements into a collection on the ViewModel.

默认的模型绑定器将完成您需要它做的所有事情。我曾经使用过FormCollection—只是后来才知道如何将元素数组绑定到ViewModel上的集合中。

Just go ViewModel. Better all around, for every reason enumerated.

视图模型。无论出于什么原因,一切都更好。

#7


2  

With form collection you will be able to get all the values inside the form. There can be situations where you may need to pass some additional values from the form which may not be part of your view model.

通过表单集合,您将能够获得表单中的所有值。在某些情况下,您可能需要从表单中传递一些不属于视图模型的附加值。

Just take an example of passing 10 hidden values from the form. The form collection makes sense.

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

The only difficulty that you may face is type casting. All form collection items that you get will be string; you may need to type cast based on your requirement.

您可能面临的唯一困难是类型铸造。您得到的所有表单集合项都是字符串;您可能需要根据您的需求输入cast。

Also model state validation is another area where you may face a challenge.

另外,模型状态验证是另一个可能面临挑战的领域。

#8


1  

You can always add the form collection properties to your method signatures. They will automatically be populated by form values with corresponding keys.

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

#9


1  

Well with Forms Collection you will find a quick way to get the values of a form. Otherwise you have to create a class that mimics the Form Fields and people are sometime lazy to create custom classes for less important/rarely used Forms.

通过表单集合,您将找到一种快速获取表单值的方法。否则,您必须创建一个类来模拟表单字段,而人们有时会懒得为不太重要/很少使用的表单创建自定义类。

No there is no extra benefit (in fact limited) of forms collection over a custom class as action parameters and it should be avoided whenever possible.

不,在自定义类上使用表单集合作为操作参数没有额外的好处(实际上是有限的),应该尽可能避免它。

#10


1  

Responding to the title question: yes.

回答题目问题:是的。

There are some situations that FormCollection needs to be used. For instance, suppose a ViewModel that has a property that implements the 1 to N relation (in concrete case, a TimesheetViewModel with ICollection<TimesheetEntryViewModel>), and the Controller has to perform a validation between the time entries to not get a time collision between the end time of an entry and the start time of the following entry. To mark a related entry with a validation error, how can be the line index be retrieved?

有些情况需要使用FormCollection。例如,假设一个视图模型,实现1到N关系有一个属性(在具体情况下,与ICollection TimesheetViewModel < TimesheetEntryViewModel >),和控制器之间执行验证条目的时间不会结束时间之间的一次碰撞一个条目和以下条目的开始时间。要用验证错误标记相关条目,如何检索行索引?

Well, with the default model binding, the index value is lost in the Controller logic. Fortunately, FormController stores the index you used in the View and a more specific validation can be done.

在默认模型绑定的情况下,索引值在控制器逻辑中丢失。幸运的是,FormController存储了您在视图中使用的索引,可以进行更具体的验证。

#1


44  

Is there any good reason to use FormCollection instead of ViewModel?

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

No. I have following issues.

不。我有以下问题。

Issue - 1

问题- 1

In case FormCollection is being used...It will be mandatory to Type Cast the Primitive Type Values un-necessarily because while getting the entry of specific Index of the System.Collections.Specialized.NameValueCollection, value being returned is of type String. This situation will not come in case of Strongly Typed View-Models.

如果正在使用FormCollection……强制类型强制强制强制强制转换基本类型值,因为在获取System.Collections.Specialized.特殊化的特定索引时。NameValueCollection,返回的值是字符串类型。这种情况在强类型的视图模型中不会出现。

Issue - 2

问题- 2

When you submit the form and goes to Post Action Method, and View-Model as Parameter exists in the Action method, you have the provision to send back the Posted Values to you View. Otherwise, write the code again to send back via TempData/ViewData/ViewBag

当您提交表单并转到Post操作方法,并且Action方法中存在作为参数的视图模型时,您可以将已提交的值发送回您的视图。否则,再次编写代码,通过TempData/ViewData/ViewBag返回

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

View-Models are normal classes, created to bind data to-from Views

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

Issue - 3

问题- 3

We have Data Annotations that can be implemented in View Model or Custom Validations.

我们有可以在视图模型或自定义验证中实现的数据注释。

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

ASP.Net MVC simplifies model validatons using Data Annotation. Data Annotations are attributes thyat are applied over properties. We can create custom validation Attribute by inheriting the built-in Validation Attribute class.

ASP。净MVC validatons使用数据注释简化模型。应用数据注释属性thyat属性。我们可以通过继承创建自定义验证属性内置的验证属性类。



Issue - 4

问题- 4

Example you have the following HTML

例如,您有以下HTML

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

Question : How can we access the value of customAttr1 from the above eg from inside the controller

问题:如何从上面的(如从控制器内部)访问customAttr1的值

Answer : When a form get posted only the name and value of elements are posted back to the server.

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

Alternatives : Use a bit of jQuery to get the custom attribute values, and post that along with the form values to action method

备选方案:使用一点jQuery来获取自定义属性值,并将其与表单值一起发布到action方法

Another option is to rather put what you got in your custom attributes in hidden controls

另一种选择是将在自定义属性中获得的内容放到隐藏控件中




That's the reason, I would always prefer to use View-Models

这就是为什么我总是喜欢使用视图模型

#2


6  

The only advantage I can think of is if you want to use the automatically generated controller provided when you don't specify a EF model to be strongly typed to. In that case, your Create and Edit actions will use the FormCollection object as it is a reliable, pre-existing artifact of the framework to work with for this purpose. Perhaps the previous developer chose this option while creating his controllers, and stuck with it since Visual Studio must know what it's doing :)

我能想到的唯一优点是,如果您希望使用在不指定要强类型输入的EF模型时提供的自动生成的控制器。在这种情况下,您的创建和编辑操作将使用FormCollection对象,因为它是框架的一个可靠的、预先存在的工件,可以用于此目的。也许之前的开发人员在创建控制器时选择了这个选项,并坚持使用它,因为Visual Studio必须知道它在做什么:)

But, in reality, I would never recommend this headstart of a few seconds. It's always better to build out viewmodels, I would recommend looking at the effort to move in that direction if only for maintenance purposes. With model binding and strongly typed views and html helpers, you are much more likely to reduce the number of run-time errors as a result of changing some magic string and not realizing it until your page blows up.

但是,实际上,我永远不会推荐这种提前几秒钟开始的做法。构建视图模型总是更好的,我建议您考虑一下,如果只是为了维护目的,就应该朝着这个方向努力。使用模型绑定、强类型视图和html helper,您更有可能减少运行时错误的数量,因为更改了一些魔术字符串,直到页面崩溃时才实现。

#3


5  

Ok, I see the general consensus here is that it isn't liked. To offer another perspective, I've always liked using the formcollection passed into the controller on POST actions. It offers the use of the TryUpdateModel method from the controller which will map the collection to your strongly typed class. TryUpdateModel also has overloads that allow you to white list the properties of the model that you want to allow to be updated.

好吧,我认为大家都认为它不受欢迎。为了提供另一种视角,我一直喜欢在POST操作中使用传递给控制器的formcollection。它提供了来自控制器的TryUpdateModel方法的使用,该方法将集合映射到强类型类。TryUpdateModel也有重载,允许您将想要更新的模型的属性设置为白色。

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

It still allows all the model binding you want, but helps to keep anything other than the "Name" property on my viewmodel from being updated.

它仍然允许您想要的所有模型绑定,但是有助于避免更新我的viewmodel上的“Name”属性以外的任何内容。

You can see more about the TryUpdateModel method here:

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

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

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

#4


2  

There are always workarounds for getting away from a FormCollection lol.. you can have hidden fields bound to your view model variables in the form to your heart's content.

要想摆脱格式收集,总是有办法的。您可以将隐藏字段绑定到视图模型变量的表单中,并将其绑定到您的核心内容。

Form collections mostly emerge from the laziness of creating a view model but still end up taking time trying to get figure out how to get the values out of it in your controller :P

表单集合主要是由于创建视图模型的惰性而产生的,但最终还是要花时间试图弄清楚如何从控制器P中获取值

I think it was simply created in the very beginning of MVC as an alternative to using strongly typed views when having very simple forms - back in the days when everyone used ViewBag :) ... and once hey had it in there they couldn't just take it out as simple as that.

我认为它仅仅是在MVC的一开始就创建的,作为在拥有非常简单的表单时使用强类型视图的一种替代方法——在过去每个人都使用ViewBag:)……一旦有了它,他们就不能这么简单地把它取出来。

Maybe you can use it if you are absolutely sure your view will never have more than one form input? Probably still a bad idea though..

如果你确定你的视图永远不会有一个以上的表单输入,也许你可以使用它?也许还是个坏主意。

I cant find any recent articles talking about any advantages of form collections.. while strongly typed views are everywhere.

我找不到任何有关收集表格的优点的文章。强类型视图随处可见。

#5


2  

Yes. Sometimes, it can be useful. Here's an example:

是的。有时候,它是有用的。这里有一个例子:

Let's say we have in our db "date_and_time_field".

假设我们在db中有date_and_time_field。

In Razor View, we want to use two form fields. The first one "Date" (maybe with jQuery UI Datepicker). The second one "Hour".

在Razor视图中,我们要使用两个表单字段。第一个“Date”(可能是jQuery UI Datepicker)。第二个“小时”。

In the Controller Action, we compose the "date_and_time_field" by means of Request.Form["Date"] and Request.Form["Hour"].

在控制器动作中,我们通过请求组成“date_and_time_field”。形式(“日期”)和Request.Form(“小时”)。

There are other scenarios where it can be useful:

也有其他可能有用的情况:

  • A cross-table (with checkBoxes in Razor view)

    交叉表(在Razor视图中带有复选框)

  • The collection Request.Unvalidated().Form (maybe this is not part of your question: I don't wanna be off-topic)

    收集Request.Unvalidated()。形式(也许这不是你问题的一部分:我不想离题)

#6


2  

The default model binder will do almost everything you need it to do. I resorted to the FormCollection once - only to later figure out how to bind arrays of elements into a collection on the ViewModel.

默认的模型绑定器将完成您需要它做的所有事情。我曾经使用过FormCollection—只是后来才知道如何将元素数组绑定到ViewModel上的集合中。

Just go ViewModel. Better all around, for every reason enumerated.

视图模型。无论出于什么原因,一切都更好。

#7


2  

With form collection you will be able to get all the values inside the form. There can be situations where you may need to pass some additional values from the form which may not be part of your view model.

通过表单集合,您将能够获得表单中的所有值。在某些情况下,您可能需要从表单中传递一些不属于视图模型的附加值。

Just take an example of passing 10 hidden values from the form. The form collection makes sense.

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

The only difficulty that you may face is type casting. All form collection items that you get will be string; you may need to type cast based on your requirement.

您可能面临的唯一困难是类型铸造。您得到的所有表单集合项都是字符串;您可能需要根据您的需求输入cast。

Also model state validation is another area where you may face a challenge.

另外,模型状态验证是另一个可能面临挑战的领域。

#8


1  

You can always add the form collection properties to your method signatures. They will automatically be populated by form values with corresponding keys.

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

#9


1  

Well with Forms Collection you will find a quick way to get the values of a form. Otherwise you have to create a class that mimics the Form Fields and people are sometime lazy to create custom classes for less important/rarely used Forms.

通过表单集合,您将找到一种快速获取表单值的方法。否则,您必须创建一个类来模拟表单字段,而人们有时会懒得为不太重要/很少使用的表单创建自定义类。

No there is no extra benefit (in fact limited) of forms collection over a custom class as action parameters and it should be avoided whenever possible.

不,在自定义类上使用表单集合作为操作参数没有额外的好处(实际上是有限的),应该尽可能避免它。

#10


1  

Responding to the title question: yes.

回答题目问题:是的。

There are some situations that FormCollection needs to be used. For instance, suppose a ViewModel that has a property that implements the 1 to N relation (in concrete case, a TimesheetViewModel with ICollection<TimesheetEntryViewModel>), and the Controller has to perform a validation between the time entries to not get a time collision between the end time of an entry and the start time of the following entry. To mark a related entry with a validation error, how can be the line index be retrieved?

有些情况需要使用FormCollection。例如,假设一个视图模型,实现1到N关系有一个属性(在具体情况下,与ICollection TimesheetViewModel < TimesheetEntryViewModel >),和控制器之间执行验证条目的时间不会结束时间之间的一次碰撞一个条目和以下条目的开始时间。要用验证错误标记相关条目,如何检索行索引?

Well, with the default model binding, the index value is lost in the Controller logic. Fortunately, FormController stores the index you used in the View and a more specific validation can be done.

在默认模型绑定的情况下,索引值在控制器逻辑中丢失。幸运的是,FormController存储了您在视图中使用的索引,可以进行更具体的验证。