MVC 3 Conditionally Required Properties

How do you create conditionally necessary properties with an MVC 3 card that will work with client-side validation, as well as server-side validation when disabling JS? For instance:

public class PersonModel { [Required] // Requried if Location is not set public string Name {get; set;} [Range( 1, 5 )] // Requried if Location is not set public int Age {get; set;} [Required] // Only required if Name and Age are not set. public string Location {get; set;} } 

The rules in this example:

  • Name and Age are required if Location not specified.
  • Location is required only if Name and Age not set.
  • It doesn’t matter if the name, age and location are set.

In the view, I need the result sent to Action if the name / age is given. And a different Action value if set to "Location". I tried with two separate forms with different Get Url's; this works fine except that validation rules cause problems. Preferably, I would like to use 2 separate Get action Url, i.e.

 @model PersonModel @using( Html.BeginForm( "Age", "Person", FormMethod.Post ) ) { @Html.TextBoxFor( x => x.Name ) @Html.ValidationMessageFor( x => x.Name ) @Html.TextBoxFor( x => x.Age ) @Html.ValidationMessageFor( x => x.Age ) <input type="submit" value="Submit by Age" /> } @using( Html.BeginForm( "Location", "Person", FormMethod.Post ) ) { @Html.TextBoxFor( x => x.Location ) @Html.ValidationMessageFor( x => x.Location ) <input type="submit" value="Submit by Location" /> } 

Based on the PersonModel above, if a location is provided, verification will not be performed as PersonModel expects the name and age to be set as well. And vice versa with name / age.

Based on the above example, how do you create conditionally necessary properties with an MVC 3 framework that will work with client-side validation, as well as server-side validation when disabling JS?

+6
source share
2 answers

You can add custom validation to your model, either subclass ValidationAttribute , or implement IValidatableObject .

ValidationAttribute makes adding client-side validation relatively easy by implementing IClientValidatable and registering a new adapter and method through jQuery. See Running client-side validation for a custom attribute .

IValidatableObject more suitable for one-time validation requirements when reuse is not an option. It also leads to a simple simple code. Unfortunately, there is no easy way to implement client-side validation using this method.

+1
source

I created my own RequiredAttribute descendant. It takes the name of the boolean property, what the check condition should be. Please note that this code is not ready for production, there is no error checking, and could be clarified a bit when checking the zero value.

 [Localizable(false),AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] public class RequiredIfAttribute : RequiredAttribute { public string BoolProperty { get; private set; } public RequiredIfAttribute(string boolProperty) { BoolProperty = boolProperty; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { if (!Equals(value, null) || !string.IsNullOrEmpty(value as string)) return ValidationResult.Success; var boolProperty = validationContext.ObjectInstance.GetType().GetProperty(BoolProperty); var boolValue = (bool)boolProperty.GetValue(validationContext.ObjectInstance, null); if (!boolValue) return ValidationResult.Success; return new ValidationResult(FormatErrorMessage(validationContext.DisplayName)); } } 

You can create a readonly property to represent your condition, as shown below. Also note that the Age property cannot be "empty" in your code. If you want to support it, you must use the null (int?) Type for this property.

 public class PersonModel { // helper properties public bool LocationNotSet { get { return string.IsNullOrEmpty(Location); } } public bool NameAndAgeNotSet { get { return string.IsNullOrEmpty(Name) && Age <= 0; } } [RequiredIf("LocationNotSet")] // Requried if Location is not set public string Name {get; set;} [Range( 1, 5 ), RequiredIf("LocationNotSet")] // Requried if Location is not set public int Age {get; set;} [RequiredIf("NameAndAgeNotSet")] // Only required if Name and Age are not set. public string Location {get; set;} } 
0
source

Source: https://habr.com/ru/post/896791/


All Articles