ASP.Net MVC 3 DataAnnotations validating List<T> - asp.net-mvc-3

I have a ViewModel that has been deserialized from JSON which looks something like this:
public class UserThingsUpdateViewModel
{
public IList<Thing> Things { get; set; }
[Required]
public int UserId { get; set; }
public int Age { get; set; }
}
Thing is also a ViewModel which also has various DataAnnotaion ValidationAttribute attributes on the properties.
The problem is that Lists don't seem to get validated and even after a through search I cant seem to find any articles that tackle this. Most suggest that the ViewModel is wrong if it includes a list.
So, what is the best way to validate my list and add Model Errors to the Model State?

Prior to checking ModelState.IsValid, you could add code to step through and validate each Thing, as follows:
foreach (var thing in Things)
TryValidateModel(thing);
This will validate each item, and add any errors to ModelState.

You could write a custom validator attribute and decorate the list property with it? That would allow you to write custom logic to get the elements out of the list and validate them.

Related

Can Mvc EditorFor Collection Order Be Reversed?

I am using Mvc 3 and have come across the following scenario:
I've got a view model that has a list of note elemements as a property and I am using the HtmlHelper extension method EditorFor to render out the collection. All is working great. However now I need to display the note elements in the reverse order.
Is there a way to tell Mvc to reverse the elements?
// View Models
public class MyViewModel
{
public List<Note> Notes
{
get;
set;
}
}
public class Note
{
public string Username
{
get;
set;
}
public DateTime ChangedDate
{
get;
set;
}
public string Text
{
get;
set;
}
}
The elements are in oldest first order.
I can reverse the order of the elements in the collection to solve the problem which at the moments seems the most logically way to go. However that makes the javascript to insert new notes more complex as that requires the name and id of the html elements to be rewritten.
So I was hoping there maybe some sort of order option for the EditorFor method.
Another alternate would be to write a custom partial view and update the TemplateInfo.HtmlFieldPrefix but I like to keep to using the EditorTemplates if I can.

Preventing tampering of form fields in ASP.NET MVC EF

The default strongly-typed Edit page in ASP.NET MVC 3 generally exposes all fields for the Entity. While this is often workable, some fields are a security risk. For example a simplified magazine subscription entity might look like:
public void Subscription() {
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public DateTime SubscribedThru { get; set; }
}
If I provide an Edit page to let users change their own address, for example, it's a security risk to include the SubscribedThru field because a knowledgeable and malicious user could give themselves a free 10-year subscription by faking the date (even if I use #Html.HiddenFor(model => model.SubscribedThru). So I am not including that field in any way on the Edit page html (via razor).
I thought the answer might be to prevent binding attempts on SubscribedThru on the Edit method in the controller using something like:
[HttpPost]
public ActionResult Edit([Bind(Exclude="SubscribedThru")] Subscription subscription) {
if (ModelState.IsValid) {
db.Entry(subscription).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(subscription);
}
When I get to the SaveChanges(); line, it throws the error The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value. I believe that the SubscribedThru date (properly?) doesn't exist, and the empty value is less than SQL Server can handle. What surprises me is that it's even trying to update that field when I have Binding excluded for it.
So far my best solution seems to be to create a custom ViewModel that omits the SubscribedThru date, but that seems a lot of duplication of fields, validation, etc.; if possible I'd like to just make the one field SubscribedThru safe from user editing.
I can't say I fully understand the UpdateModel and TryUpdateModel methods and wonder if that's a direction to head? I played with them and EF throws errors for having duplicate objects (same key) which is perplexing.
Also, I'm not clear if the subscription data is preserved from the initial load in public ActionResult Edit(int id) in the controller all the way to the final [HttpPost]
public ActionResult Edit(Subscription subscription)... method, or does the line db.Entry(subscription).State = EntityState.Modified; try and set all the data (I thought it was just setting a flag indicating "edited-so-EF-should-save-this").
I'm a long-time .NET developer, just jumping in to my first ASP.NET MVC project, so I'm probably overlooking something painfully obvious. Thanks for any help!
So far my best solution seems to be to create a custom ViewModel that omits the SubscribedThru date, but that seems a lot of duplication of fields, validation, etc.;
That is exactly what you should do to keep things neat & tidy. AutoMapper eases the ViewModel variation headache.
This page contains an example of updating a model using TryUpdateModel (Listing 4):
http://www.asp.net/mvc/tutorials/older-versions/models-(data)/creating-model-classes-with-the-entity-framework-cs
You can whitelist only the fields that you allow to be edited, which removes the security risk.

How to find properties are not modified or change?

I have viewmodel which i am binding with my view call "EditProfile". Now once the user click on the "EditProfile" link from the menu bar I load all the profile information by calling get restful service and user can see his/her profile.
User can change any field they want but I want to post only fields that are changed by User.
I know how to compare two properties but don't know how to pull only modified properties from the viewmodel. Have anybody arrived to this situation before?
Properties in my viewmodel are:
public class UserViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Profession { get; set; }
}
In the past I implemented INotifyPropertyChanged for the ViewModel. And I logged which property's changed after the PropertyChanged event fired.
Why not take an alternative approach - post everything (so the model is available) and simply have "IsDirty" properties on your objects that are smart enough to submit only changes to the database (like the entity framework does by default)
You can simply form your own jQuery .post() parameters, but unless you have a ton of data - why? It makes for a difficult to read view model (how do you know what is posted under what scenarios) so the typical approach is to post separate view models or post everything which in my opinion for basic forms is easier.

In ASP.NET MVC3 how do you stay DRY with very similar but slightly different viewmodels?

In building an app, we created a generic object model to store some values, the viewmodel looks a bit like this at the moment:
public class FooViewModel {
public int ID { get; set; }
public byte FooType { get; set; }
[Required]
[Display(Name = "Bar Name")]
public string Name { get; set; }
[Required]
public string Email { get; set; }
//etc, etc
}
The problem is: depending on the FooType, we want to have the Display Name to be different and the Email is not required for type 1 and 2, but is required for type 3 and 4.
We tried seperating out the properties that differ per type in to classes that inherit from this one, but the validation does a fallback on what is specified in the base type, so that didn't work.
Currently, the only option seems to be to create a viewmodel for each FooType (and also seperate controllers and view), which leads to a lot of code duplication.
What are other ways to keep this DRY?
To benefit a validation context (e.g. validating objects in different contexts), I strongly recommend using FluentValidation library.
You could implement a custom RequiredIf validation attribute, or you could implement IValidatableObject.

MVC3 - Recommended way to create fields for IEnumerables with Editor Templates

I want to create a form for an entity. One of the members is an IEnumerable of a different type (that also has an IEnumerable member), for example:
public class Person
{
public string Fullname { get; set; }
public int Age { get; set; }
public IEnumerable<Position> Jobs { get; set; }
}
public class Position
{
public string Title { get; set; }
public IEnumerable<string> PhoneNumbers { get; set; }
}
I'm trying to find a good example of creating multiple fields in the html, how would I allow to enter more than one position? I think I read somewhere about someone who's cloning that part of the form with jQuery - is that the way to go?
Thanks
This blog post talks about editing a variable length list and may be what you are after.
Possible duplicate of Editing a Variable Length List, ASP.NET MVC 3 Style with Table
I personnally use an improved version of BeginCollectionItem, but I find it still too complicated when used with child views.
This is a great fail of ASP.NET MVC promises (it should be simple, fluid and powerful).

Resources