Make a required class properties not required - asp.net-mvc

I have a class set up to hold values on a registration form (VB.NET, MVC), and among the properties is a Password property:
Public Class RegisterModel
...
Private _password As String
<DisplayName("Password:"), Required(), ValidatePasswordLength(), DataType(DataType.Password)> _
Public Property Password() As String
Get
Return _password
End Get
Set(ByVal value As String)
_password = value
End Set
End Property
This works great when registering a new user, but I'd like to use the same class to update existing users. (Note: this app is run by an admin who is in charge of registering individuals and assigning passwords.) The way I'd like it to behave is if the admin leaves the password blank, then the password is not changed, but the rest of the information is. If I use this class, the password can't be left blank because it fails on the Required() and ValidatePasswordLength() calls.
Is there a way to use this class but tell the model to ignore these particular validations? Even if I leave the password field off my edit form, it still fails. Do I need to create a whole duplicate class without these restrictions on the password field? There must be a better way.

You could implement IDataErrorInfo and have a flag set on the model which indicates whether it is being used by an admin or not - you could then validate conditionally.
But overall, I'd say this is a bit of a code smell. You're using a model for two different, incompatible purposes. It'd be better to use a separate view model.

I'd recommend using the FluentValidation library. It's a fantastic way to separate the concerns of your view (view model) and the actual validation you want to perform. You could pass parameters into it to drive different behavior. Check out When/Unless conditions or just writing completely custom validation methods with the Must operator.
public class RegisterModelValidator: AbstractValidator<RegisterModel>
{
public RegisterModelValidator(bool isAdmin)
{
RuleFor(x => x.Password).NotEmpty().Unless(isAdmin);
...
}
}
As long as your view model would have identical properties in both scenarios, you should use the one view model and one validation class. If the model varies at all I'd use two view models as David recommends.

You can do this in 2 ways:
1: add the [ValidateInput(false )] attribute to the action
or
2: Add a new property to the Register Model
public bool IsNewUser {get;}
3: Create a new class level attribute that takes IsNewUser into account when validating

Related

How to make business validations on fields in editable Table?

Here is the deal: I have a Table who uses a BeanItemContainer of "MyBean". "MyBean" is not really relevant, it contains only 1 String and 2 Date objects.
But the user must be allowed to change theses values for each instance of MyBean in my container.
To do that, it's easy, just do myTable.setEditable(true). Or a little bit more complex, create a Table.ColumnGenerator who returns a Field (add a ValueChangeListener to push the new value inside the bean).
With the Table.ColumnGenerator, I'm also able to add specific validations for each Field, that's great!
The purpose of this is to render the Field in "error mode".
But there is something I'm not able to do: make my business validations after the user clicks on the "Save" button and retrieve the corresponding field to call the method setComponentError(...).
Only basic validations can be done (integer only, max value, date time range, ...) but for more complex validations (business requirements) I don't know...
How can I do that?
You can write your own custom validators by implementing Validator interface and in them implement custom business logic.
public class MyValidator implements Validator {
void validate(Object valueToValidate) throws Validator.InvalidValueException {
//Your Business logic
}
}

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.

MVC Model binding / validation

After a year or so of MVC experience I'm still confused about one thing: How to effectively use the DataAnnotations with ModelState.IsValid? For simple tutorial example this all works just fine and I have no questions about that. But supposed I have the following model:
Public Class Movie
Public Property MovieID As Integer
Public Property Title As String
Public Property Year As Integer
Public Property AddedByUser As String
End Class
Now the field AddedByUser is required in the database however I don't want the user to provide this but rather the business logic based on the currently logged in user. How would I use the DataAnnotation attributes for this scenario? If I make this field required then in the controller when I say:
Public Function SaveMovie(ByVal entity as Movie) As ActionResult
If ModelState.IsValid
// Save to DB here...
End If
Return View(entity)
End Function
... the validation will fail because I don't have that field in the view bindings. Should I have a hidden field for this? Should I write a custom view model for SaveMovie action? I suppose I could write my own validation in business logic but then why use model validation at all? Custom model binder perhaps? What is the best way to handle these types of scenarios?
Just to give another example scenario what about the difference between insert and update operation and validation? For update operations object's primary key is required. However that is not the case for inserts. Are you supposed to have separate models for insert and update just because of this one key property?
so the way that I handle this is I use the DataAnnotation based validation for user input type stuff. i.e. Validation on email addresses, dates, required fields etc. Stuff that you need a quick 'sanity check' on and need to double check the users entries on.
I don't put any DataAnnotations on the fields that my Database controls or my code controls, i.e. Primary Keys, your [AddedByUser] property as the user doesn't access these properties directly and so you shouldn't have to add validation checks on this. Since your code is the only thing that updates these properties, why validate them?
For more 'business rule' type validation I implement IValidatableObject on my model which gets run, in MVC, after all property-level validations have succeeded. Note that it won't run if the property-level validations fail. And this makes sense, because if the data is 'dirty' you wouldn't want to proceed to run more complex validation etc.
Hope this helps :)

Validating an Email Address on jQuery postback best practice

This question title is likely to be worded poorly so feel free to adjust.
In my MVC application I have a custom attribute which i use to decorate email fields which then either passes or fails the model.
On one pge though I allow the use to submit a comment but I submit via ajax and so do not do a full postback and no model validation.
So I'd like to validate the address but not copy the code. I'd also like to avoid breaking the code out of the validator into yet another class or is this the best wAY?
Is there another way? Can I create the model in the ajax postback and validate it there and then return the partial view with the error messages?
Or is there another way?
You say, ...
So I'd like to validate the address but not copy the code. I'd also like to avoid breaking the code out of the validator into yet another class or is this the best way?
IMO, that is the best way. Factor out the common code. I see your issue though, our EmailValidator inherits from RegularExpressionValidator, so it's hard to factor out. We have a RegEx utility class that uses the same RegEx pattern. We refer to the pattern by constant in both places...
public class EmailAttribute : RegularExpressionAttribute
{
public EmailAttribute() :
base(RegExUtility.SingleEmailAddressPattern)
{
ErrorMessage = "Please enter a valid email address";
}
and
public static class RegExUtility
{
public const SingleEmailAddressPattern = #"...";
public static bool IsValidSingleEmailAddress(string email)
{
return Regex.IsMatch(email, SingleEmailAddressPattern);
For simple Ajax postback actions, I think you can often handle it in the controller or create a separate POCO ViewModel that just supports the Ajax path. I know there are articles on using the same model for both types of actions, but we've found there are usually enough differences that it's worth having separate view models. If they're complex enough, we just factor out the common code.

Custom validation with Data annotations

I'm using data annotations to check data that's being entered, but I'm stuck when it comes to more custom way to validate data.
I need to run queries against database to see if stuff exists there or not, and then report back to user if a "custom db-check error" appears, such as "The Companyname already exists"
How can I implement such a thing together with dataannotations?
I have all the queries done etc using linq and entity framework that comes with 3.5sp1
/M
Custom attributes that extend data annotations
You will have to write your own attributes that will do the validation of your object instance against data store.
Make sure your classes inherit System.ComponentModel.DataAnnotations.ValidationAttribute class:
public class MustNotExist: ValidationAttribute
{
...
}
Caution
I've run into a similar situation when I needed to validate that the object is unique within data store. But this kind of validation wasn't possible on the entity class itself, since it should only work for those entities that are being created but not when you return your entity from the data store already.
My solution was to have a separate interface, class and attribute.
public interface IExternalValidator ...
class DBUniqueValidator: IExternalValidator ...
class ValidateExternallyAttribute: FilterAttribute, IActionFilter
{
...
public ValidateExternallyAttribute(Type validatorType, Type entityType) ...
...
}
I was able to place my attribute on controller actions that get entity parameters. Filter action attribute then checks controller action parameters (it can easily access their types and values) and runs external validator against correct parameters (provided types in attribute definition) and populates ModelState errors when validation fails.
[ValidateExternally(typeof(DBUniqueValidator), typeof(User))]
public ActionResult RegisterUser(User newUser)
{
if (!this.ModelState.IsValid)
{
// act accordingly - probably return some error depending on model state errors
}
// register new user in data store
}
This way I was able to run external validation only on those actions that actually needed it, and this technique also helped my controller actions code to stay clean and short. All I had to do is to check if there are any model state errors.

Resources