I'm having an issue with a validation error in ASP.NET MVC 4.
I've applied a RegularExpression rule for a field which will accept only numeric input. Should the data contain any other character it should display an error message.
[RegularExpression("^[0-9]*$", ErrorMessageResourceType = typeof(Resources.General), ErrorMessageResourceName = "CodeMustBeNumeric")]
public string Code { get; set; }
Problem is, no matter what's the current culture setting, it always displays the default resource and not the localized one. Some more details to follow.
My resources:
The result:
As you can see, the current culture for all strings is Italian, but not for the validation error. What am I doing wrong?
I thought I was doing something wrong and there was an out-of-the-box way to solve this, but with a deeper search I found out the common solution is just creating a custom validation attribute which inhreits from the ASP.NET one.
So I did, and it works fine. Should anyone need it, here it is:
public class CustomRegularExpressionAttribute : RegularExpressionAttribute
{
public override string FormatErrorMessage(string name)
{
string currentLang = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
CultureInfo ci = new CultureInfo(currentLang);
return HttpContext.GetGlobalResourceObject(ErrorMessageResourceType.Name.ToString(), ErrorMessageResourceName, ci).ToString();
}
public CustomRegularExpressionAttribute(string pattern)
: base(pattern)
{
}
}
And the new call:
[CustomRegularExpression("^[0-9]*$", ErrorMessageResourceType = typeof(Resources.General), ErrorMessageResourceName = "CodeMustBeNumeric")]
public string Code { get; set; }
I am using NancyFX for my API Gateway and I have a model such as the following:
public class CreatePerson
{
[Required]
public string FirstName {get;set;}
[Required]
public string LastName {get;set;}
[Required]
[Phone]
public string Phone {get;set;}
[Required]
[MyCustomValidationRule]
public string ImagePath {get;set;}
}
It uses both a custom MyCustomValidationRule attribute as well as the provided Phone and Required attributes.
In my module I have the following:
public class PersonModule
{
public PersonModule()
{
Post["/",true] = async (context,cancel)=>
{
var request = this.BindAndValidate<CreatePerson>();
if(!ModelValidationResult.IsValid)
{
//THIS NEVER HITS
}
}
}
}
The [Required] attributes are working and if I omit any of the properties, it works fine. However, if I pass in an invalid phone (such as sdfsdgsdg or I do something that clearly breaks MyCustomValidationRule attribute, it is not caught. Furthermore, I have placed a breakpoint in the constructor of the MyCustomValidationRule attribute, and it never hits.
Why is this not hitting?
#TheJediCowboy. I had the same problem in my project.
I can't check my theory now, but I think you should add ValidationAdapter for each kind of attribute, example you can find on github
I think only 4 validation attribute will work in default package(Range, Regex, Required, StringLength), please check list of validation adapters github
For custom attributes required add custom adapter, I think.
UPDATED
This solution checked and works good.
For validation attribute (except Range, Regex, Required and StringLength) required add validation adapter (or override exiting). Nancy use all validation adapters that are in the project.
I am building an MVC 5 app and have come to the point where I need to validate user input.
I would like to apply a [Required] attribute to a class that is not a built-in data type. Here is a snippet of my view model:
public class GraffitiViewModel : EformBase
{
[Required(ErrorMessage = "Please select yes or no")]
public RadioButtonList<YesNoType> GraffitiOffensive { get; set; }
[Required(ErrorMessage = "Please select yes or no")]
public RadioButtonList<YesNoType> GraffitiTag { get; set; }
// ... more stuff here
}
The RadioButtonList is a class that emits HTML markup for corresponding C# radio button definitions. The [Required] attribute is not working in this context. Is there a way I can extend either my RadioButtonList class, or the [Required] attribute, so I don't have to modify my ViewModel?
I am thinking along the lines of a custom attribute that will perform this validation or a method in my RadioButtonList that will return a bool indicating whether or not the validation succeeded.
Looking forward to your responses!
M
The [Required] attribute should fire if:
the property is null
OR
the property is a string type, which is either empty or whitespace
See MSDN for more details.
Alternatively you can use the code here to create a custom attribute which fires on whatever conditions you decide.
How to use data annotations to do a conditional validation on model?
For example, lets say we have the following model (Person and Senior):
public class Person
{
[Required(ErrorMessage = "*")]
public string Name
{
get;
set;
}
public bool IsSenior
{
get;
set;
}
public Senior Senior
{
get;
set;
}
}
public class Senior
{
[Required(ErrorMessage = "*")]//this should be conditional validation, based on the "IsSenior" value
public string Description
{
get;
set;
}
}
And the following view:
<%= Html.EditorFor(m => m.Name)%>
<%= Html.ValidationMessageFor(m => m.Name)%>
<%= Html.CheckBoxFor(m => m.IsSenior)%>
<%= Html.ValidationMessageFor(m => m.IsSenior)%>
<%= Html.CheckBoxFor(m => m.Senior.Description)%>
<%= Html.ValidationMessageFor(m => m.Senior.Description)%>
I would like to be the "Senior.Description" property conditional required field based on the selection of the "IsSenior" propery (true -> required). How to implement conditional validation in ASP.NET MVC 2 with data annotations?
There's a much better way to add conditional validation rules in MVC3; have your model inherit IValidatableObject and implement the Validate method:
public class Person : IValidatableObject
{
public string Name { get; set; }
public bool IsSenior { get; set; }
public Senior Senior { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (IsSenior && string.IsNullOrEmpty(Senior.Description))
yield return new ValidationResult("Description must be supplied.");
}
}
Read more at Introducing ASP.NET MVC 3 (Preview 1).
I have solved this by handling the "ModelState" dictionary, which is contained by the controller. The ModelState dictionary includes all the members that have to be validated.
Here is the solution:
If you need to implement a conditional validation based on some field (e.g. if A=true, then B is required), while maintaining property level error messaging (this is not true for the custom validators that are on object level) you can achieve this by handling "ModelState", by simply removing unwanted validations from it.
...In some class...
public bool PropertyThatRequiredAnotherFieldToBeFilled
{
get;
set;
}
[Required(ErrorMessage = "*")]
public string DepentedProperty
{
get;
set;
}
...class continues...
...In some controller action ...
if (!PropertyThatRequiredAnotherFieldToBeFilled)
{
this.ModelState.Remove("DepentedProperty");
}
...
With this we achieve conditional validation, while leaving everything else the same.
UPDATE:
This is my final implementation: I have used an interface on the model and the action attribute that validates the model which implements the said interface. Interface prescribes the Validate(ModelStateDictionary modelState) method. The attribute on action just calls the Validate(modelState) on IValidatorSomething.
I did not want to complicate this answer, so I did not mention the final implementation details (which, at the end, matter in production code).
I had the same problem yesterday but I did it in a very clean way which works for both client side and server side validation.
Condition: Based on the value of other property in the model, you want to make another property required. Here is the code
public class RequiredIfAttribute : RequiredAttribute
{
private String PropertyName { get; set; }
private Object DesiredValue { get; set; }
public RequiredIfAttribute(String propertyName, Object desiredvalue)
{
PropertyName = propertyName;
DesiredValue = desiredvalue;
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
Object instance = context.ObjectInstance;
Type type = instance.GetType();
Object proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
if (proprtyvalue.ToString() == DesiredValue.ToString())
{
ValidationResult result = base.IsValid(value, context);
return result;
}
return ValidationResult.Success;
}
}
Here PropertyName is the property on which you want to make your condition
DesiredValue is the particular value of the PropertyName (property) for which your other property has to be validated for required
Say you have the following
public class User
{
public UserType UserType { get; set; }
[RequiredIf("UserType", UserType.Admin, ErrorMessageResourceName = "PasswordRequired", ErrorMessageResourceType = typeof(ResourceString))]
public string Password
{
get;
set;
}
}
At last but not the least , register adapter for your attribute so that it can do client side validation (I put it in global.asax, Application_Start)
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredIfAttribute),typeof(RequiredAttributeAdapter));
I've been using this amazing nuget that does dynamic annotations ExpressiveAnnotations
You could validate any logic you can dream of:
public string Email { get; set; }
public string Phone { get; set; }
[RequiredIf("Email != null")]
[RequiredIf("Phone != null")]
[AssertThat("AgreeToContact == true")]
public bool? AgreeToContact { get; set; }
You can disable validators conditionally by removing errors from ModelState:
ModelState["DependentProperty"].Errors.Clear();
Thanks Merritt :)
I've just updated this to MVC 3 in case anyone finds it useful: Conditional Validation in ASP.NET MVC 3.
There is now a framework that does this conditional validation (among other handy data annotation validations) out of the box:
http://foolproof.codeplex.com/
Specifically, take a look at the [RequiredIfTrue("IsSenior")] validator. You put that directly on the property you want to validate, so you get the desired behavior of the validation error being associated to the "Senior" property.
It is available as a NuGet package.
You need to validate at Person level, not on Senior level, or Senior must have a reference to its parent Person. It seems to me that you need a self validation mechanism that defines the validation on the Person and not on one of its properties. I'm not sure, but I don't think DataAnnotations supports this out of the box. What you can do create your own Attribute that derives from ValidationAttribute that can be decorated on class level and next create a custom validator that also allows those class-level validators to run.
I know Validation Application Block supports self-validation out-of the box, but VAB has a pretty steep learning curve. Nevertheless, here's an example using VAB:
[HasSelfValidation]
public class Person
{
public string Name { get; set; }
public bool IsSenior { get; set; }
public Senior Senior { get; set; }
[SelfValidation]
public void ValidateRange(ValidationResults results)
{
if (this.IsSenior && this.Senior != null &&
string.IsNullOrEmpty(this.Senior.Description))
{
results.AddResult(new ValidationResult(
"A senior description is required",
this, "", "", null));
}
}
}
I had the same problem, needed a modification of [Required] attribute - make field required in dependence of http request.The solution was similar to Dan Hunex answer, but his solution didn't work correctly (see comments). I don't use unobtrusive validation, just MicrosoftMvcValidation.js out of the box.
Here it is. Implement your custom attribute:
public class RequiredIfAttribute : RequiredAttribute
{
public RequiredIfAttribute(/*You can put here pararmeters if You need, as seen in other answers of this topic*/)
{
}
protected override ValidationResult IsValid(object value, ValidationContext context)
{
//You can put your logic here
return ValidationResult.Success;//I don't need its server-side so it always valid on server but you can do what you need
}
}
Then you need to implement your custom provider to use it as an adapter in your global.asax
public class RequreIfValidator : DataAnnotationsModelValidator <RequiredIfAttribute>
{
ControllerContext ccontext;
public RequreIfValidator(ModelMetadata metadata, ControllerContext context, RequiredIfAttribute attribute)
: base(metadata, context, attribute)
{
ccontext = context;// I need only http request
}
//override it for custom client-side validation
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
//here you can customize it as you want
ModelClientValidationRule rule = new ModelClientValidationRule()
{
ErrorMessage = ErrorMessage,
//and here is what i need on client side - if you want to make field required on client side just make ValidationType "required"
ValidationType =(ccontext.HttpContext.Request["extOperation"] == "2") ? "required" : "none";
};
return new ModelClientValidationRule[] { rule };
}
}
And modify your global.asax with a line
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredIfAttribute), typeof(RequreIfValidator));
and here it is
[RequiredIf]
public string NomenclatureId { get; set; }
The main advantage for me is that I don't have to code custom client validator as in case of unobtrusive validation. it works just as [Required], but only in cases that you want.
Check out Simon Ince's Conditional Validation in MVC.
I am working through his example project right now.
Typical usage for conditional removal of error from Model State:
Make conditional first part of controller action
Perform logic to remove error from ModelState
Do the rest of the existing logic (typically Model State validation, then everything else)
Example:
public ActionResult MyAction(MyViewModel vm)
{
// perform conditional test
// if true, then remove from ModelState (e.g. ModelState.Remove("MyKey")
// Do typical model state validation, inside following if:
// if (!ModelState.IsValid)
// Do rest of logic (e.g. fetching, saving
In your example, keep everything as is and add the logic suggested to your Controller's Action. I'm assuming your ViewModel passed to the controller action has the Person and Senior Person objects with data populated in them from the UI.
I'm using MVC 5 but you could try something like this:
public DateTime JobStart { get; set; }
[AssertThat("StartDate >= JobStart", ErrorMessage = "Time Manager may not begin before job start date")]
[DisplayName("Start Date")]
[Required]
public DateTime? StartDate { get; set; }
In your case you would say something like "IsSenior == true".
Then you just need to check the validation on your post action.
I'm building a MVC web application with C#. Since the site will be multilingual, I've implemented my own ResourceManager. This class is responsible for fetching the required resource strings from a database/cache depending on the currents thread culture and works fine so far.
My problem is, I'd like to use the my custom ResourceManager solution to fetch validation error messages when for example using the Required Attribute on a property. Can this be done?
The RequiredAttribute allows to use a custom resource manager:
[Required(
ErrorMessageResourceType = typeof(CustomResourceManager),
ErrorMessageResourceName = "ResourceKey")]
public string Username { get; set; }
UPDATE:
Another possibility is to write your custom attribute:
public class CustomRequiredAttribute : RequiredAttribute
{
public override string FormatErrorMessage(string name)
{
return YourCustomResourceManager.GetResource(name);
}
}