I am working on a MVC 4 project. I am having an issue with multiple custom validation attribute on single property. Suppose I have 3 custom validation attribute for single property such as:
public class Test
{
[customAttribute1]
[customAttribute2]
[customAttribute3]
public string property1 { get; set; }
}
Currently when I post he form than all three custom validations are performed on the property (no matter whether first validation pass or fail).
What I want is if customAttribute1 validation fails than no need to validate the property with next next custom attribute. How can i achieve this?
The point of this behaviour is to return back (to the UI) all the errors in the Model, so the user can fix all the errors at the same time...
Let's say you want you password to be minimum 8 chars and have at least an uppercase and a number. The way you want your validation to run is to stop if the password is not long enough without checking the rest. Typical use case scenario:
User sets password "foo" -> submit
error - Password too short
User sets it to "foofoofoo"
error - Password must have an uppercase
User sets it to "FooFooFoo"
error - Password must have a number
User goes away frustrated...
So, if the 3 attributes are to be validated together, my suggestion is to keep this behaviour. If the 3 are exclusive then do as others suggested and combine them into a single attribute.
Ordering or executing conditionally is not supported AFAIK.
The best bet is to have all these 3 validations in the same attribute.
If you are badly in need of this kind of validation, then Fluent Validation can do it for you.
Related
I'm using C# in .Net-Core MVC and I have a form that users will need to fill out.
All of the fields that are shown on the page are required to be filled out. The issue I'm running into is that some of the fields on the form are hidden and others are displayed based on choices previously made on the form.
If I put the [Required] tag on all of the fields in the model, when I validate the ModelState, it flags the not displayed fields as invalid.
Is there a way that when I try to validate the ModelState, I can validate only the fields displayed on the page and ignore the fields that have been hidden?
Thanks.
Unfortunately the [Required] works globally in MVC.
You will need to develop your own validation attributes. Hopefully someone already did it but for MVC with .NET Framework (see the code here):
For validations that has the form of: “Validate this field only when
this other field has certain value”, I have coded 3 attributes:
RequiredIf, RangeIf and RegularExpressionIf that inherints from
ValidationAttribute.
Now you will need to translate it in order to work for .NET Core.
If you are looking for a more generic solution, the Web Forms framework has a very good concept of Validation group. It allows you to validate - or not - logically grouped properties.
If I put the [Required] tag on all of the fields in the model, when I
validate the ModelState, it flags the not displayed fields as invalid.
Of course cuz you set a parameter "Required". Disable that parameter from fields what can be not displayed or make nullable
I have to validate three things when a consumer of my API tries to do an update on a customer.
Prevent the customer to be updated if:
The first name or last name are blank
For a certain country, if the customer's inner collection of X is empty, then throw an exception. X is hard to explain, so just assume it's some collection. For all other countries, X doesn't apply / will always be empty. But if it's a certain country, then X is required. So it's almost a conditional required attribute. A customer belongs to a country, so it's figured out from the JSON being sent.
Prevent the customer from being updated if some conditions in the database are true.
So basically i'm stuck with the following problem, and I wanted some advice on the most appropriately way to solve it:
Do I create an Action Filter to do the validation on the customer entity before the saving takes place? Or would it be better to create custom validation attribute derived from ValidationAttribute and override the IsValid member function.
Basically a question of saying
if (first name is empty, if x, if y, etc) vs (!ModelState.IsValid)
And then using IsValid to cause the custom attributes to work.
It seems like validation attributes are best for "simple" validation, i.e. required field. But once you start getting into things like "I need to look at my database, or analyze the http request header for custom values, and based on that, invalid = false" then it almost seems wrong to do this sort of stuff so close to the entity.
Thoughts?
Thanks!
I like FluentValidation a lot: https://github.com/JeremySkinner/FluentValidation
As you mentioned built-in validation attributes are limited. For complex validations you had better implement your own attributes or use a library like this.
One thing I like about FluentValidation is that it performs at model-level rather than field-level, meaning that you can use related fields' values for validation. For example
RuleFor(customer => customer.Discount).NotEqual(0).When(customer => customer.HasDiscount);
(Code excerpt taken from project's Wiki page)
It's also extensible so you can develop your own custom validators on top of this library as well.
Is it possible to indicate a property is a required field without using data annotation attributes?
Instead of using annotation attributes, I want to set it as a required field, based on particular conditions.
For eg, something like below
if (true)
{
//set myObj.Name as required field
}
Edit: The reason why I need to do is, I'm calling a business service class of our own framework, which I can not touch, and inside the class, when the entity is being saved, mandatory checking is already catered.
But, in my requirement, I need to save my entity several times and , each times, the mandatory checking may be different . That's the reason why I need to mark the properties required fields dynamically.
Otherwise, I have to made my own mandatory checking before calling the business service class, which I don't want to do.
From your description, it seems like you need to provide your "own mandatory checking". I say this for two reasons;
To provide your user meaningful feedback as to why something field is required
Also, to satisfy the contract of your business service class
Can you have a "validate" method that simply runs through your set of rules (that mandatory checking, that you mentioned earlier) and have it return a list of strings indicating the rules that were violated on an attempt to save. Then you can use these strings to populate the text of a message box, logfile or whatever to provide meaningful feedback to the user as to why something wasn't saved, and also ensuring that data that is saved, is compliant to your business service class.
I have a 3 layered system of presentation, logic, and data access. In my logic layer, I have a Validate() method which makes sure that the data that's about to get forwarded to the data access layer is valid for the database (no nulls where nulls are not allowed, and so on).
On top of that, in the .aspx presentation layer, we have some user-friendly error checking and validation, directly checking the controls on the web form. My problem is the ValidateInput() method in the code behind which checks the controls, it's several hundreds of lines long and really annoying to maintain. The code for checking the data is far far longer than the code that does the actual work.
What I've got looks like this:
private List<string> ValidateInput()
{
List<string> errormessages = new List<string>();
if (LastNameETextBox.Text.Trim() == String.Empty)
{
errormessages.Add("Last name required.");
}
if (FirstNameETextBox.Text.Trim() == String.Empty)
{
errormessages.Add("First name required.");
}
//etc. etc.
}
We have a nice styled notification box hidden in the master page that gets turned from Visible false to true when we call it, creating the "illusion" of an overlaying box. It looks really nice and works really well so we want to use it. The idea is that we gather up all the errors for the whole form, put them in a list, and then send that list to the notification box, which then gives you all the errors in one nice list.
But the Validate() is just a torturous amount of "if" statements and it's hard to keep track of. Is this just the nature of input validation, or is there some other, better way of handling this?
I think you can able to avoid using these kind of If statements using a Generic function.
My suggestion is to define a function like this
private List<string> ValidateInput(string ErrorMessage, TextBox txtInput, ValidatationType validationType)
{
List<string> errormessages = new List<string>();
if (validatationType == ValidationType.NoNullValues)
{
if (txtInput.Text.Equals(String.Empty))
{
errormessages.Add(ErrorMessage);
}
}
if (validatationType == ValidationType.Integer)
{
int number;
if (Int32.TryParse(value, out number))
{
errormessages.Add(ErrorMessage);
}
}
// etc. etc.
}
Enum ValidationType
enum ValidationType
{
NoNullValues,
Integer,
// etc
}
Please modify the function. Also checks the syntax, I am using notepad to write the code.
This approach also helps you to achieve re-useabilty if you are use all validation methods in a separate class.
Thanks
Couple of the different ways that I had handled it (in different projects) :
Use custom control library - controls were simply extending existing ASP.NET/3rd party controls to add validation logic which was controlled by properties such as IsMandatory, MandatoryMessage etc. Properties were typically set at the design-time (and were not backed by view-state). The validation logic would accumulate error messages in the message collection exposed by base page. Another variant had used user controls combining ASP.NET controls along with validators but frankly speaking, ASP.NET validators sucks.
Essentially a base page class had a validation logic that would traverse the control collection within the page and then perform validation based on control type. The page would offer a registry to register control to validate, type of validations and error message to display. There was also method to un-register/skip control validation that was used primarily to skip control traversal within control such as repeater/grid-view.
For client-side(browser side) validation, I had used jquery validation (or own JS library). In both cases above, the validation logic would also emit necessary start-up scripts to set-up the client-side validation - however, #2 could generate a single start-up script (with less size) while #1 entails generating a start-up script per control instance. From flexibility perspective, #1 is better and fits nicely in control based development approach. #2 centralizes your validation logic at one central place (i.e. a base page) which can be very handy.
a) Create an validation type enum to enumerate all types of validation you want to perform. (In your code you are doing string null checking for both controls which are both textboxes, its unnecessary repetition of code logic)
b) Create a class of constants / or resource file that holds all the error messages.
c) Write a function that takes a control, Validation type enum, arguments for validation and error message id. It will check the type of control and perform validation as indicated by enum. If error, error message is added to your "errorMessages" collection.
enum ValidationType{
NullCheck,
IsNumber,
RangeCheck,
....
}
class ErrorMessages{
const string FNEMPTY = "First Name is empty";
....
}
class BusinessObject{
function ValidateControl(Control cntrl, ValidationType type, object[] args, string message)
{
if(cntrl is TextBox)
{
if(cntrl as TextBox).Text.Trim() == String.Empty
errorMessages.Add(message);
}
...
}
}
Now you can call the above function on every control you want to validate. One more improvement will be to Implement a base class for all your controls that holds the corresponding error message collection in a property (Dictionary<ValidationType,String>). Then you can modify the validation function to accept an array of ValidationType enum to perform several validation in one call. Each control will give you its error message for every validation type in its property we created in the base class.
Hope this helps.
Thanks
Ven
I'm new to C# MVC and I'm trying to add some dynamic validation checks to my view models that are used in a form. For example, I have a string property called FirstName. I can add the attribute StringLength(10) and Required() to it.
My problem is, depending on some other field, the FirstName StringLength could vary from 10 to 20, etc. I still want to use the MVC validations but be able to modify it. I know that attributes are bound to the class so maybe I'm using the wrong thing.
I want the abilities for attribute validation but have it modifiable at run time. Is this possible?
The values in an attribute have to be literals. You can still use attribute based validation, but you will need to use the CustomValidation tag and point it at a method to use. If it depends on multiple fields in the object, you will want to put this on the class rather than the property.
It seems you can add validation attributes at runtime by implementing DataAnnotationsModelValidatorProvider:
Dynamic Attributes # forums.asp.net