3

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

4 Answers 4

5

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

Sign up to request clarification or add additional context in comments.

1 Comment

Had this exact same problem and this is beautifully simple solution. Genius!
4

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);
}

Comments

1

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!

1 Comment

I am hoping that this answer doesn't also get flagged because it really is relevant to the question. It is better to keep your conditional validation with the viewmodel rather than in the controller action for 2 reasons. 1 - declutters controller action. 2 - if you reuse the viewmodel elsewhere, you won't need to duplicate the conditional validation in another controller action. Peace.
0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.