Conditional Validation for ViewModel Fields on ASP

2019-07-02 07:31发布

问题:

Title: Conditional Validation for ViewModel Fields on ASP MVC

I have a question about ASP MVC validtion. Let's say that I have the follwing View Model

public class PersonViewModel
{
    [Required]
    public string Name {get; set; }

    [Required]
    public string Email {get; set; }
}

According to this when I submit the form MVC will validate that both fields have values. However, in my website I have the situation where the Email can be turned off in a global site setting, so the model will only render the Name Textbox on the form. Now when I submit the form it still asks me for the Email field since it is indicated as "Required", despite there is no way the user can fill that field now.

Is there a solution for this type of scenario when using ASP MVC validations?

回答1:

The solution is that you'll have to take off the Required attribute on the Email field and perform the validation yourself on post, if such a setting is set. Something like this

[HttpPost]
public ActionResult Post(PersonViewModel model)
{
    //replace EmailTurnedOff with your setting
    if (!EmailTurnedOff && string.IsNullOrWhiteSpace(model.Email))
    {
        ModelState.AddModelError("Email", "Field is Required");
    }

    if (ModelState.IsValid)
    {
        //do whatever
    }

    return View(model);
}


回答2:

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



回答3:

Piggybacking off of groovejet, this is how I used a conditional [Required] in a Controller instead of the view model. I did this because there is only one action that I want to ignore the [Required] in my application.

    public ActionResult Update(MyViewModel mVM)
    {
        if(mVM.Role == "Role" && mVM.Property == null)
        {
            ModelState.Remove("Property");
        }
        if (ModelState.IsValid)
        {
           // code...
        }
     }


回答4:

Conditional validation can be performed from the ViewModel. The ViewModel class will need to implement the IValidatableObject interface.

Then add a method similar to this at the bottom of the ViewModel:

    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        if (validationContext == null)
            return null;

        var valResults = new List<ValidationResult>();

        if (!EmailExists))
            valResults.Add(new ValidationResult($"Email is required.", new[] { "EmailErrorMsg" }));

        return valResults;
    }

Don't forget to add a ValidationMessage to the right spot in the View:

@Html.ValidationMessage("EmailErrorMsg")

Happy Coding!