Exclude a property from unobstrusive client Validation with MVC 3 - asp.net-mvc

I have a class User, that have an Email property, like that :
public class User : Entity
{
...
[Display(Name = "Email"), Required(ErrorMessage = "Required."), Remote("EmailExists", "User", ErrorMessage = "Email already in Use.")]
public virtual string Email { get; set; }
...
}
My View Create works fine with all the validation ...
But in my view Edit, my Email texbox is Readonly, so The user cant change the email...
The problem is my Remote validation EmailExists keeps firing...
Is there a way to exclude the Email client validation just in that case? Or maybe another solution?
Thanks

Best solution would be to render Email as text content(span, p, etc) in that particular case - validations would not fire. This would be best accomplished with editor templates. But if you don't wish to, you could use some javascript to remove rules on client side. Take a look at Plugins/Validation/rules - you would remove rule when textbox is readonly. But for me the first way is preferred option

I think that the easier way is to disable the field in the client instead of using readonly. The validate plugin doesn't take in account disabled fields.

You could use different ViewModels for the edit and create views and only apply the Remote attribute to view model associated with the create view or call some other remote validation logic for the view model associated with the edit view.

Related

ModelState: Validate only the properties that are inside the form

I have a User class with multiple string properties, all of them required. The properties are used for different actions, like Create and Update.
In my form, on create action, i am using only a part of these properties, and, because of this, the ModelState is invalid.
Is there a way to specify to the ModelState that it should validate only the properties that are included in the POST data (inside the form) ? So the missing properties are ignored?
You can create different models for user creation and other actions with different sets of validation attributes.
Yea, you should create different view models for each specific action method ( if they have specific requirements ).
You can use the RequiredIf attribute from Foolproof to achieve this:
using Foolproof;
[RequiredIf("Tab", "Information")]
public bool UW_AgentCreditReportsAknowlegement { get; set; }
Just use one of the attributes and set the appropriate condition.

How can I validate an email address using the same method used by the DataAnnotations attribute DataType.EmailAddress?

I am using MVC3 and in certain locations in the code I am using the System.ComponentModel.DataAnnotations.DataType.EmailAddress attribute and letting MVCs Model validation do the validation for me.
However, I would now like to validate an email address in a different section of code where I am not using a model. I would like to use the same method that is already being used by MVC, however I was unable to find any information on how to do so.
EDIT - Sorry if my question was unclear. I will attempt to clarify.
Here is a snippet from the RegisterModel that is included with the default MVC template:
public class RegisterModel
{
...
[Required]
[DataType(DataType.EmailAddress)]
[DisplayName("Email address")]
public string Email { get; set; }
...
}
These attributes instruct mvcs model validation on how to validate this model.
However, I have a string that should contain an email address. I would like to validate the email address the same way that mvc is doing it.
string email = "noone#nowhere.com";
bool isValid = SomeMethodForValidatingTheEmailAddressTheSameWayMVCDoes(email);
As others have said, the DataType attribute doesn't actually do any validation. I would recommend you to look at Data Annotations Extensions which includes already written validation extensions for a variety of things, including Email.
It is also possible to do model validation on your full model explicitly: Manual Validation with Data Annotations.
If you want to do per attribute validation for a specific field/property, you can also look at the tests for DataAnnotationExtensions which should give you what you want:
[TestMethod]
public void IsValidTests()
{
var attribute = new EmailAttribute();
Assert.IsTrue(attribute.IsValid(null)); // Don't check for required
Assert.IsTrue(attribute.IsValid("foo#bar.com"));
..
}
Have a look at this blog post by Scott Guthrie, which shows how to implement validation of an email address using a custom attribute (based on the RegularExpressionAttribute).
You can reuse that logic if you need to validate the email address somewhere else.
You may want to look at this question: Is the DataTypeAttribute validation working in MVC2?
To summarize, [DataType(DataType.EmailAddress)] doesn't actually validate anything, it just says "hey, this property is supposed to be an e-mail address". Methods like Html.DisplayFor() will check for this and render it as foo, but the IsValid() method is pretty much a simple return true;.
You'll have to roll your own code to actually perform validation. The question linked above has some sample code you can use as a starting point.

Can DataAnnotation prevent the user from posting a form field that does not exist in a database?

I have a guest book form created using asp.net mvc.
The valid gender form field must be filled in by selecting a value from a drop down control. The drop down control has 3 options, i.e., "--Select--", "Female", "Male" and the "--Select--" is selected by default. The data model has been setup to force the visitor select either female or male but not "--Select--".
We know that the visitor has a chance to temper the form data, so he can submit the gender form field pointing to a value that does not exist in the database.
My question is:
Can DataAnnotation prevent the user from posting a form field that does not exist in a database?
What is the preferred approach to counter this attempt? Do I have to check the submitted gender form field first before invoking SaveChanges()?
It depends whether you need to provide the user with a specific error, or a clean validation message. In cases where the user is trying to tamper with the form post, I would not be too concerned about the user experience.
If you care about this, you can use the IValidatableObject interface to perform a validation against the legal values:
public class Person : IValidatableObject
{
public string Gender { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
//ValidGenders is a list of valid values, retrieved from the database
if (!ValidGenders.Contains(Gender))
{
yield return new ValidationResult("Gender is not valid", new string[] { "Gender" });
}
}
}
The Model validation performs validation using IValidatableObject just as it does using data annotation validation.
On the other hand, if you don't care about the user experience, you could let the error happen in the database, and handle the issue using your standard error handling pipeline. Assuming your foreign key constraints are in place, the operation will fail because the Gender value is not found in the Genders table, or whatever your setup may be.
Not sure if you are using any form of DTO's or Business Objects, but As well as validating the object client side (or within MVC) it may be worth having your objects validate themselves also.
This way you can catch any issues before they hit the DB. An interesting post on SO about the topic can be found here: Should Business Objects or Entities be Self-Validated?

MVC2, using the same EF Entity in various Views

i have this problem that has been buggin me for the last hours.
Lets suppose i have this Signup form, that i need to fill it up, all propertieshave the RequiredAttribute, the model is a EF entity named "User".
i have this second edit account details form, and at this moment a specific field ("Username") is no longer required, because i already have it, the user doesnt need to fil it again and in matter of fact it doest enven show up on the Edit form.
The problem:
when posting the second Edit form, obviously i am stucked with the Username RequiredAttribute.
I would solve this just by adding a "Bind" attribute with "Exclude" option, BUT, this is my current model :
public class AccountDetailsModel
{
public User user { get; set; }
public string NEWPASSWORD1 { get; set; } // new password
public string NEWPASSWORD2 { get; set; } // new password comparison
}
and just looks like Bind Attribute with Exclude option doesnt handle complex Model types. I cant get it to work on this scenario.
Im stuck, scratching my heads for a long time now...
How can i overcome this?
I just want to re-use my EF Entity (User) on 2 different views along with its DataAnnotations.
Thanks in advance.
I just want to re-use my EF Entity (User) on 2 different views along with its DataAnnotations.
Here's the problem. You shouldn't do this. I would recommend you setting up view models which are classes specifically tailored for a given view and contain the necessary validation attributes for this view only. To ease the mapping between your EF models and the view models you could use AutoMapper.
Put the UserName in a hidden input field for the details page.

Is there any way to stop DataAnnotation validation after the first failure?

In my ViewModels I use several DataAnnotations to validate the form data, there are usually 2-3 annotations per field.
For example a field for an email address might look like this:
[Required(ErrorMessage = "Please enter an email address.")]
[Email(ErrorMessage = "That is not a valid email address.")] // Custom
public string Email { get; set; }
Now if someone were to submit the form, both errors would show up in the validation summary. Is there any easy way to specify an order to run the validation annotations so that if the Required validation fails, the Email validation doesn't run?
If this isn't possible, how is this usually handled? Should I create custom validators for any field that has more than a single annotation? Would that be a proper way to use annotations, where a single one handles multiple types of validation?
(I'm also aware I could probably combine the Required annotation into the custom Email one, but this is just an example).
In this specific case I would probably take the same approach that the ASP.NET WebForms validators take - simply have the EmailAttribute validator return true if the value is null or empty.
Think about it:
If the e-mail address is required, then there will also be a [Required] validator and a null/empty e-mail address will generate a validation error anyway;
If the e-mail address is optional, a null/empty value should be considered valid.
No need to solve the complex problem of intercepting validators when you can just design the individual validators to play nice together!
Ordering validation: No.
In this case you could simply remove the Required attribute because "" or " " will fail the email address validation.
And yes, AFAIK creating a custom validation attribute that combines both of them is probably your best bet.
The problem here is that the ordering on the attributes is completely arbitrary and decided at compile time. You actually can enforce simple ordering depending on the kind of validation runner you're using. If you are using something like xVal and a validation runner like the one mentioned here, you can add an orderby clause like this to force a specific kind of attribute to sort to the top:
orderby attribute.GetType() == typeof(T) ? 0 : 1
Just make a strongly-typed validation runner method, where T is derived from the ValidationAttribute class.

Resources