How do you validate only if there's input? - asp.net-mvc-3

Using Asp.Net MVC3, I have many steps in a wizard where after every step I do a $.post to capture what was entered. The first two steps are simple and all fields are required no matter what.
The rest of the steps are not required. However, if step 3 has 10 input fields and entered values for 5 out of 10, then validations have to kick in (just for the 5 fields and display the errors for those 5 only). So in essense, things like [Required], [StringLength] and [RegEx] should kick in only if someone actually entered anything for those 5 fields. If nothing is entered, validations should be skipped.
I was thinking of naming or prefixing each step (div) with Required or Optional as
Hope there is an answer.

If you divide each step on your wizard into a separate form, then validation can be performed when necessary on that step's form.
Please be aware that BY DEFAULT StringLength and RegEx attributes will only be validated when information is entered in that particular field. If the fields are blank, validation of those attributes will not occur.
As far as Required attributes, I am unclear what you are asking. Are you saying that there are fields in a particular step which will be required based on a condition in another field? If so, then you must implement a conditionally required validator.

You can make your viewmodel implement IValidatableObject. The interface requires one function, IEnumerable<ValidationResult> Validate(ValidationContext validationContext). MVC will validate the model first from any DataAnnotations, then on the Validate function on the model (so twice, which isn't always what you want).
For example,
public class Input : IValidatableObject
{
public string Name { get; set; }
// ... Other fields ...
public virtual IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var results = new List<ValidationResult>();
if (String.IsNullOrEmpty(Name))
{
// ... Validation rules ...
results.Add(new ValidationResult("Please enter a name.", new[] { "Name" }));
}
return results;
}
}
More information from Scott Guthrie's blog.

You could write custom a validation attribute and perform this validation logic in the IsValid method where you have access to the value and could check whether the value is not null or empty and only then proceed with the default validation.

Related

Spring MVC and annotations, how to do a validator in the case of a form that will contain different fields depending of a combo box

I am trying to accomplish the following:
I have a form that starts with a combo box, let's say that the user will have to pick either "Student" or "Teacher".
Both "Student" and "Teacher" will have the same fields displayed in the form, but if "Teacher" is checked, I will have more fields being displayed (that are hidden at first and that I will show with jQuery when the user select "Teacher").
The problem is that I want those fields to be mandatory only if "Teacher" is selected.
I have no idea to manage that, I don't think it's gonna be possible using annotations such as:
#NotBlank
private String teacherCourse;
since this field will always be blank when the user will have selected the "Student" radio button.
Any idea? Can I do a custom validation method and how?
I've taken two approaches with this in the past.
Use an enum field on the submission to determine which type of validation to perform. This is flexible and allows for any number of custom validation methods.
An alternative is to use a base command object which both student and teacher classes extend. This allows both types to extend and override validation and fields. This requires that separate methods are used to bind each type.
You could use validation groups to differentiate between constraints applying to both entities and those applying to only one of them:
public interface TeacherConstraints {}
#NotBlank(groups=TeacherConstraints.class)
private String teacherCourse;
When validating your object, specify the group to validate depending on the type selected in your combo box:
//teacher
Set<ConstraintViolation<Object>> violations = validator.validate(object, TeacherConstraints.class);
//student
Set<ConstraintViolation<Object>> violations = validator.validate(object, Default.class);
You can use javascript or JQuery for front side validation... depending upon your combo box value. If it's a teacher or student
function validate(){
var combox_value = document.getElementbyID("combo_box").value;
if(combox_value == "Teacher"){
//Validate for Teacher fields
var input_text1 = document.getElementbyID("input_text"2).value;
if(input_text1=="" || input_text1==null){
alert("Field cannot be empty");
return false;
}
return true;
}
else if(combox_value == "Student"){
//Validate for Student fields
var input_text2 = document.getElementbyID("input_text2").value;
if(input_text2=="" || input_text2==null){
alert("Field cannot be empty");
return false;
}
return true;
}
}
For JQuery try these links for live examples...
http://speckyboy.com/2009/12/17/10-useful-jquery-form-validation-techniques-and-tutorials-2/
http://www.jeasyui.com/tutorial/form/form3.php
http://www.camcloud.com/blog/jquery-form-validation-tutorial

Few questions... ModelState.IsValid and Grouped CheckBox Values

Using ASP.NET MVC when I create my model, then a controller based on the model with CRUD operations, the CRUD views are generated. I added some code using Fluent API to require certain fields but for some reason the ModelState.IsValid passes even when these fields are not completed. What determines whether this passes or not? I thought it was based on your model property data types and other things like being required or maxlength, etc....
Also, I have manually added code to grab a list of Categories from the database and generate a checkbox for each one in the View. This is a navigation property for the Project model where there is a many-many relationship. To get the group of checked values in the Create(Project project) method in the controller I use:
var selected = Request["categories"].Split(',');
This however, throws the classic Object reference not set to an instance of an object error if no values are checked. So what I want to know is, how can I determine that this does not have any values so I can do something else once detected?
I added some code using Fluent API to require certain fields but for
some reason the ModelState.IsValid passes even when these fields are
not completed.
ASP.NET MVC doesn't know anything about the Fluent API of Entity Framework and doesn't evaluate this configuration. You only can use the data annotations which MVC will recognize:
[Required]
public string SomeProperty { get; set; }
...how can I determine that this does not have any values so I can do
something else once detected?
Not sure if I understand it correctly but I'd say:
var categories = Request["categories"];
if (categories != null)
{
var selected = categories.Split(',');
// ...
}
else
{
// do something else
}

How to programatically turn on/off a Data Annotation Validation Attribute

So, I am using ASP.NET MVC 3 and Entity Framework 4.1 (code-first).
I have a class like this:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
[Range(18, 99)]
public int Age { get; set; }
}
The range validation is fired correctly. But, for example, in some situations I would like to change the range for the Age attribute. Or even turn it off. How could I do it without changing my Model class? Is this possible to made programatically?
You can use the IValidatableObject interface and define custom validation rules.
See my answer at:
Using Data Annotations to make a field required while searching for another in a form mvc 3
Its usually just a matter of implementing the interface and determine when to enforce your rules.
I just realised the solution for this case.
Eg. A user can have an authorization to create a 14 years old person.
Before save the Model, we can invoke DataContext.GetValidationErrors() and infer if the only error validation is that we want to disable, and then set
DataContext.Configuration.ValidateOnSaveEnabled = false;
So, this way we are able to save the model.
Yes, it is possible to inject validators programmatically. Altering existing validators presents separate issues, as some attributes are read-only, so you may have to delete and replace your existing validator.
You can add a class to work on the validators by following my answer to this question.

Validating parameters passed through the URL

I am working on an ASP.Net MVC3 application and I'm having trouble understanding the "right way" to do the validation I'm looking for.
For example, consider a model that looks like this:
[Required]
[StringLength(10, MinimumLength = 10)]
[RegularExpression("[0-9]{10}")]
public string Id { get; set; }
[Required]
public string Value { get; set; }
If I have an Id of "2342" and try to POST back, the model mapping kicks in and registers an error because of the length validation. However, if perform a GET against /controller/2342, then MVC seems to happily create a model with this invalid state (ModelState.Valid will be true). I could create some validations in the controller to catch this, but it seems redundant.
What is the best way to do this?
Thanks!
Jacob
When you perform a GET, you are simply retrieving a model with a given ID. So there is no validation performed. If you really want to make sure that requested model IDs should be 10 numbers in length, you should define constraint in Global.asax:
routes.MapRoute(
"Product",
"Product/{productId}",
new {controller="Product", action="Details"},
new {productId = #"[0-9]{10}" }
);
There is nothing in the framework that by default validates a model on a GET request as validation isn't generally required at that time. If you do want to force a validation here, this was answered in this prior question
See:
Validate model on initial request

.NET MVC3 Remove Currency Symbol and Commas

In my model I have the following property:
[DataType(DataType.Currency)]
public decimal? Budget { get; set; }
When the user enters in $1,200.34, I need that value to be valid and strip out the currency symbol and comma.
In my controller I'm doing:
if (race.Budget != null)
{
race.Budget.ToString().Replace("$", "").Replace(",", "");
}
The problem is that client validation doesn't pass the value for budget into the controller. I get a value of null. How can I override the client validation so that I can strip out the currency symbol and comma?
Thank you in advance for the help.
UPDATE
So here's the strange thing. Let's say I want to bypass client validation all together. I added #{ Html.EnableClientValidation(false); } to my view and it's still sending a null value for Budget when I submit to the controller.
This isn't a client side validation problem. Your model has a field of type decimal? The model binder will try to bind a value of $123,456.78 into that and fail, so the value will be null. Here's one way to get around this:
Change your model to have a string property that masks your decimal:
public decimal? Budget { get; set; }
public string BudgetText {
get {
return Budget.HasValue ? Budget.ToString("$") : string.Empty;
}
set {
// parse "value" and try to put it into Budget
}
}
Then, just bind to BudgetText from your View. Validate it as a string with a regular expression that accepts only money input. It'll probably be the same regex you can use for your BudgetText's set method
So you can probably hook in some JQuery to pre-process the form field to strip the characters off you don't want (prior to form submission to the server). This is probably the quickest, dirtiest approach.
For something reusable, have a look into custom client validation adapters. The links aren't spot on, but should get you in the right direction. For Brad's screencast, I believe the relevant parts are fairly early on.
Check out the support for jQuery localization
cliente validation using jQuery validate for currency fields
also there is a plugin for currency validation as well
http://code.google.com/p/jquery-formatcurrency/
check out this recent post as well for a $ in binding
.NET MVC 3 Custom Decimal? Model Binder

Resources