IValidatableObject Validate() for different scenarios - asp.net-mvc-3

I’ve been implementing IValidatableObject on Model entities, and using Validate(ValidationContext) to perform validation, often complex.
Can I use ValidationContext to distinguish different validation scenerios?
e.g. take for example a User model where I have 3 validation scenerios:
Sign up – I want to test an email is unique, and a small selection of required fields have been entered
Change details – Different email uniqueness check, bit more required details after sign up, not changing password here so it doesn't need checked
Change password – Only password field to validate
Is this a proper use for it, and if so how do I ensure the correct ValidationContext properties are set after a post and before Validate() is called? Or should I be taking a totally different approach?

The IValidatableObject is used to perform multiple validations against a single model. In your case you have a User model and you want to do three validations and you can do that perfectly by implementing the IValidatableObject in the User model.
The ValidationContext is not bringing much benefit (other than providing access to the context) since we can access all the properties directly in the Validate method.
An example of performing multiple validations related to the single model by IValidatableObject. (So what is the use of ValidationContext here?)
public class Party : IValidatableObject
{
[Required(ErrorMessage = "Start date is required")]
[FutureDateValidator(ErrorMessage = "Start date should be a future date")]
public DateTime StartDate { get; set; }
[Required(ErrorMessage = "Duration is required")]
public int DurationInHours { get; set; }
[Required(ErrorMessage = "No. of joinees is required")]
[Range(2, 10, ErrorMessage = "No. of joinees should be minimum 2 and not more than 10")]
public int NoOfJoinees { get; set; }
public bool Drinks { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (StartDate.TimeOfDay > new TimeSpan(22 - DurationInHours, 0, 0))
{
yield return new ValidationResult("The party should not exceed after 10.00 PM");
}
if (NoOfJoinees < 5 && Drinks)
{
yield return new ValidationResult("Drinks are only allowed if no. of joinees is 5 or more.");
}
}
}

For my two cents worth I would say that your model is either in a valid state (applying all validation criteria) or it isn't. If, under certain circumstances, you don't want to apply a validation then I think you should really be using a separate model (ViewModel, actually).
In your example, I would create a RegisterViewModel for sign up and a separate EditUserViewModel for changing details. Each of these would then have their own validation and they would have a single responsibility.
Creating a fat model that you reuse in many different views is, imho, a bit of a code smell. I have a number of reasons for thinking this. Firstly, let's say that you have a single model that is used for all interaction with user data. It looks like this:
public class UserModel
{
public int UserId { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public bool IsAdministrator { get; set; }
}
Later you decide to track the browser that was used during registration with the site. Where do you add that? It really has nothing to do with the user, so it shouldn't go on the UserModel model. If you had a separate RegisterViewModel you could modify it as needed when your registration process changes without concern as to how it would affect the other places it is used.
A more serious problem arises if, for example, you were using the above model with MVC's DefaultModelBinder. As described here, the user could create their own request and grant themselves administrator privileges even if you don't have the IsAdministrator field on the form (by exploiting a mass-assignment vulnerability). Again, if a separate ViewModel was used without the IsAdministrator property it would reduce the surface area for security holes.
The above is just an example, but I'm sure you get the point.

Related

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.

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.

POCO - if POCO means pure .net class with only properties, where i can write validations in MVC

Very new to POCO, find some google links but found many different stories.
Some connected with Entity framework, lazy loading etc. Some says its a pure .det class.
Atleast MSDN.
LINK FOR DEFINE POCO FROM MSDN:
msdn.microsoft.com/en-us/library/dd456872.aspx
I trust MSDN(a simple defination), and assume that it is a pure .NET Class.
Now let me come to the point.
IF it is pure .net class with only properties inside it than it is equilateral to "MODEL" in MVC.
example.
[Required(ErrorMessage = "Full Name required.")]
[StringLength(20, ErrorMessage = "Username must be under 20 chars.")]
public string UserName { get; set; }
[Required(ErrorMessage = "Email required.")]
[RegularExpression(".+#.+\\..+", ErrorMessage = "Email not valid.")]
public string Email { get; set; }
[Required(ErrorMessage = "PassWord required.")]
[StringLength(20, ErrorMessage = "Maximum 20 chars. allow")]
[DataType(DataType.Password)]
public string Password { get; set; }
Upto this level it is clear to me. Now if i want to write my own validation (conditional) in MODEL
using
ValidationAttribute
or
IValidatableObject
this will be not pure .net class if i am not wrong.
example.... (Something like below)
public class Wizard : ValidationAttribute,IValidatableObject
{
public override bool IsValid(object value)
{
return base.IsValid(value);
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
throw new NotImplementedException();
}
[Required(ErrorMessage = "Full Name required.")]
[StringLength(20, ErrorMessage = "Username must be under 20 chars.")]
public string UserName { get; set; }
[Required(ErrorMessage = "Email required.")]
[RegularExpression(".+#.+\\..+", ErrorMessage = "Email not valid.")]
public string Email { get; set; }
[Required(ErrorMessage = "PassWord required.")]
[StringLength(20, ErrorMessage = "Maximum 20 chars. allow")]
[DataType(DataType.Password)]
public string Password { get; set; }
}
Is this the POCO still?
If yes, how can it contains methods.(opposite to MSDN link)
IF NO, where should i write down my validation code (of course conditional validation in MVC).
Looking for a really great answer with an example.
POCOs mean you do not have to inherit from some framework defined base class in order to implement functionality. Basically you are free to design your class hierarchy.
You can add your own methods be it validation or some business logic.
A counter example would be to inherit from EntityObject class for entities in Entity Framework.
The linked article doesn't say that POCO mustn't have methods. Clear description what POCO is can be found on Wikipedia:
... the term is used to contrast a simple object with one that is
designed to be used with a complicated, special object frameworks such
as an ORM component. Another way to put it is that POCOs are objects
unencumbered with inheritance or attributes needed for specific
frameworks.
POCO can have all methods or logic you need. The difference between POCO and non-POCO is that POCO is class you can use always even if you don't use specific framework (EF) but non-POCO can be used only when specific framework is linked or even worse initialized and used.
For purists data annotations violates POCO as well because they also demand specific API but in pragmatic approach data annotations are OK (except special annotations used in EF Code first to define mapping) because they bring dependency only to the way how entity is validated but not the dependency to the way how entity is persisted (non-POCO EF object). Dependency on persistence can demand reference to EF in assemblies where you never expect to use EF - for example presentation layer like MVC application.
Personally I like to make my POCOs partial classes with the basic properties needed to define that model and then put and validation logic in a separate class. e.g:
public partial class Wizard
{
public string UserName { get; set; }
public string EmailAddress { get; set; }
}
and then if I wanted to add validation to UserName:
public partial class Wizard
{
[Required]
[StringLength(20)]
public string UserName { get; set; }
}
I know the complier just amalgamates the two classes anyway and you may be repeating properties but I think its the cleanest approach.
Another option is to use the MetadataType attribute.

How to assign my models to built-in users

I am trying to implement a foreign key connection between the built-in User model and my models in ASP.NET MVC 3.
How to assign ownership or some other roles to various entries represented with my models. Example of how my models look like:
public class Entry
{
public int Id { get; set; }
public string Value { get; set; }
public User Owner { get; set; }
public User SomeoneElse { get; set; }
}
Where to find the model for users, what do I need to import? Or is there a better approach to accomplish this?
Do you use Entity Framework ?? If so...
Simple solution
You could simply keep the Guid from the Built-In User model. You won't have a "real relationship" but it will do the trick for what you want to do. You can always get the UserId with Membership.GetUser().ProviderUserKey
Other more complex
Completely rewrite and override the MembershipProvider and login module. That way you can use your own User object and add other properties to it aswell.
Not Sure about this one
Not sure if this one will work with the auto generated tables from the MembershipProvider but you can add the Foreign Key Property this way:
[ForeignKey("User")]
public Guid UserId { get; set; }

What is the best practice for a service layer design where the business data has a 1 to 0..1 relationship?

Greetings all,
I have researched and found a number of discussions on designing a MVC service layer, but I haven't found an answer to my exact questions. The post on service layer interdependency has an image illustrating what I have in mind, but I have a further question that I don't believe is covered in the referenced post.
My application will track data for a non-profit that interacts with humans in multiple contexts. Maybe the human was a client, maybe they were an adviser, or maybe they were an adversary. They can be multiple. A client may later become an adversary (think lawyers' clients).
My idea is that the creation of a new client or a new adversary always creates two records: 1 record in the person table and one record in the ancillary table. My thoughts behind this is that there will be one place (the person table) to check to see if the business has had any past interaction with a given person.
My question is , when representing entities in a 1 to 0..1 relationship to the controller layer, (1) Should the controller be involved in combining and splitting classes before passing them to a view? (2) If not, should the service layer construct the viewmodel?
I've read the post about the 1800 line Controller here.
I've also read this post that says your service layer shouldn't know about the view model, which makes me think it lives and dies in the controller layer. If the service layer doesn't touch the viewmodel, for example, (3) is it good design for the workerService to return both Person and Worker objects to the Controller?
Here are my entity classes:
public class Record
{
public DateTime datecreated { get; set; }
public DateTime dateupdated { get; set; }
public string Createdby { get; set; }
public string Updatedby { get; set; }
}
public class Person : Record
{
public int ID { get; set; }
public virtual Worker Worker { get; set; }
publiv virtual Defendant defendant {get; set;}
...
}
public class Worker : Record
{
public int ID { get; set; }
public virtual Person person { get; set; }
...
}
public class Defendant : Record
{
public int ID { get; set; }
public virtual Person person { get; set; }
...
}
I think you should try and find a balance between whats "good design" and what works for you.
For instance, I have an MVC application that uses ASP.NET Membership, but I also have a custom User table, where I store things like a user's fiendly name, or OpenID. In that same application I have an IAdminService that handles everything concerning user administration.
What IAdminService returns to the controller is an AdminUser class, which looks like:
public class AdminUser
{
public string UserName { get; set; }
public User User { get; set; }
public MembershipUserWrapper MembershipUser { get; set; }
}
MembershipUserWrapper is just a wrapper around the default MembershipUser to allow for testing and more flexibility in general.
Anyway, you could argue that AdminUser is actually a view model and indeed I do have a couple of views strongly typed to AdminUser. It would be complicating matters unnecessarily to not let IAdminService return an AdminUser just because it is in the "service layer", and in this case, you don't want the controller performing the "transformation" from User and MembershipUserWrapper to AdminUser every time.
is it good design for the workerService to return both Person and Worker objects to the Controller?
I think in this case it probably is. You could have two separate services, but most of the logic for fetching a Worker and a Person is probably the same, so you'd be forcing yourself to either repeat a lot of code or create a third service that performs the common tasks.
You should pay attention to proper desing, but take also K.I.S.S. and YAGNI into account. Do what makes sense now, and refactor accordingly whenever needed.

Resources