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.
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.
But perhaps there's something I'm missing where it makes sense to use FormCollection?
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
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.
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.
You can always add the form collection properties to your method signatures. They will automatically be populated by form values with corresponding keys.
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.
No. I have following issues.
Issue - 1
In case
FormCollection
is being used...It will be mandatory toType Cast
thePrimitive Type
Values un-necessarily because while getting the entry of specific Index of theSystem.Collections.Specialized.NameValueCollection
, value being returned is of typeString
. This situation will not come in case of Strongly TypedView-Models
.Issue - 2
When you submit the form and goes to
Post
Action Method, andView-Model
as Parameter exists in the Action method, you have the provision to send back the Posted Values to youView
. Otherwise, write the code again to send back viaTempData/ViewData/ViewBag
View-Models are normal classes, created to bind data to-from Views
Issue - 3
We have Data Annotations that can be implemented in
View Model
orCustom Validations
.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.
Issue - 4
Example you have the following HTML
Question : How can we access the value of customAttr1 from the above eg from inside the controller
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
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
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.
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.
You can see more about the TryUpdateModel method here:
http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.tryupdatemodel(v=vs.108).aspx
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.Just go ViewModel. Better all around, for every reason enumerated.