ASP.NET MVC Conditional Validation

ASP.NET MVC Conditional validation

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).

Set Required Field Validation based on condition in ASP.NET MVC

You can add custom validation logic by implementing IValidatableObject on the ViewModel.

public class MyViewModelThatMixesTwoUsecases : IValidatableObject {
public string EmployeeCode { get; set; }
public bool IsCreateUsecase { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (IsCreateUsecase && string.IsNullOrWhiteSpace(EmployeeCode)) {
yield return new ValidationResult(
"EmployeeCode is required for create usecase",
new[] {"EmployeeCode"}
);
}
}
}

In the controller, test whether your model is valid by calling ModelState.IsValid.

Conditional client side validation in ASP.NET MVC Core 3.1

According to your description, I suggest you could add a property in the RequiredIfAttribute AddValidation attribute to add the role to the input salary.

Then I suggest you could try to use below validation unobtrusive scripts:

RequiredIfAttribute :

public class RequiredIfAttribute : ValidationAttribute, IClientModelValidator
{
public string PropertyName { get; set; }
public object Value { get; set; }

public RequiredIfAttribute(string propertyName, object value, string errorMessage = "")
{
PropertyName = propertyName;
ErrorMessage = errorMessage;
Value = value;
}

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
var instance = validationContext.ObjectInstance;
var type = instance.GetType();
var proprtyvalue = type.GetProperty(PropertyName).GetValue(instance, null);
if (proprtyvalue != null)
{
if (proprtyvalue.ToString() == Value.ToString() && value == null)
{
return new ValidationResult(ErrorMessage);
}
}
return ValidationResult.Success;
}

public void AddValidation(ClientModelValidationContext context)
{
context.Attributes.Add("data-val", "true");
context.Attributes.Add("data-val-country", ErrorMessage);
context.Attributes.Add("data-val-country-role", Value.ToString());
}
}

Scripts:

@section Scripts{
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validation-unobtrusive/3.2.11/jquery.validate.unobtrusive.min.js"></script>

<script>

$.validator.addMethod('country', function (value, element, params) {
var genre = $(params[0]).val(), role = params[1], salar = value;

var selecttest = $("#Role option:selected").text();

if (selecttest == role) {
if (value.length == 0) {
console.log("selecttest == role value = null");
return false;

} else {
console.log("selecttest == role value != null");
return true;
}
} else {
console.log("selecttest != role");
return true;
}



});

$.validator.unobtrusive.adapters.add('country', ['role'], function (options) {
var element = $(options.form).find('select#Salary')[0];

options.rules['country'] = [element, options.params['role']];
options.messages['country'] = options.message;
});
</script>

}

Result:

Sample Image

Conditional validation on model in MVC

If you're on MVC3/.NET4, you can use IValidatableObject which exists specifically for such purposes.

Quoting ScottGu,

...The IValidatableObject interface enables you to perform model-level
validation, and enables you to provide validation error messages
specific to the state of the overall model....

You model would look like

public class MyViewModel : IValidatableObject
{
public long? Id { get; set; }
public decimal? ProposedCost { get; set; }

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Id != null && ProposedCost == 0) {
yield return new ValidationResult("ProposedCost must be provided.");
}
}
}

and then in the controller,

[HttpPost]
public ActionResult Submit(MyViewModel model)
{
if (!ModelState.IsValid) {
//failed - report an error, redirect to action etc
}
//succeeded - save to database etc
}

Otherwise, the most clean solution would be to use view models - UpdateViewModel where the property is required, and CreateViewModel where it's not required.

Conditional validation in MVC.NET Core (RequiredIf)

Found an answer

Changed

if (proprtyvalue.ToString() == DesiredValue.ToString() && value == null)

to

if (proprtyvalue.ToString() == DesiredValue.ToString() && value.ToString() == "N/A")

Conditional Validation for ViewModel Fields on ASP MVC

I seem to have found the solution:

if(EmailTurnedOff)
{
this.ViewData.ModelState.Remove("Email");
}

Then when I call ModelState.IsValid it will give me the correct answer



Related Topics



Leave a reply



Submit