Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MVC how to ignore validation of nested view model

I have a page with which i post two view models to the controller, Enquiry and Appointment. Appointment is nested within enquiry. A user can choose to submit an enquiry with our without creating an appointment .

I use the built in MVC required attributes on the view model properties.

My question is, when the user chooses to create an enquiry without an appointment, how can I elegantly ignore the validators on the nested Appointment view model and have ModelState.IsValid return true?

if(!viewModel.CreateAppointment)
            {
                //ignore the nested view models validation                            
            }
like image 851
gilbert Avatar asked Oct 03 '12 16:10

gilbert


1 Answers

You can make a custom IgnoreModelError attribute as shown below and use 2 separate buttons in your view one for enquiry only and one for appointment.

// C#
public class IgnoreModelErrorAttribute : ActionFilterAttribute
{
    private string keysString;

    public IgnoreModelErrorsAttribute(string keys)
        : base()
    {
        this.keysString = keys;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState;
        string[] keyPatterns = keysString.Split(new char[] { ',' }, 
                 StringSplitOptions.RemoveEmptyEntries);
        for (int i = 0; i < keyPatterns.Length; i++)
        {
            string keyPattern = keyPatterns[i]
                .Trim()
                .Replace(@".", @"\.")
                .Replace(@"[", @"\[")
                .Replace(@"]", @"\]")
                .Replace(@"\[\]", @"\[[0-9]+\]")
                .Replace(@"*", @"[A-Za-z0-9]+");
            IEnumerable<string> matchingKeys = _
               modelState.Keys.Where(x => Regex.IsMatch(x, keyPattern));
            foreach (string matchingKey in matchingKeys)
                modelState[matchingKey].Errors.Clear();
        }
    }
}


[HttpPost]
[IgnoreModelErrors("Enquiry.Appointment")]
public ActionResult CreateEnquiryOnly(Enquiry enquiry)
{
    // Code for enquiry only.
}

[HttpPost]
public ActionResult CreateAppointment(Enquiry enquiry)
{
    // Code for appointment.
}
like image 102
iaq Avatar answered Nov 15 '22 08:11

iaq