John
John

Reputation: 762

Validate model on initial request

I'm returning a model to my view on the initial load of a page, the model is populated from the DB, I want to validate the model so that when the user receives the page a validation summary show the errors if any.

I have tried using TryValidateModel(model) but this does not work, it does not update the ModelState, the reasion I assume is that it will only validate against what is populated from the ModelBinder

Is there anyway around this? I just want to validate the model first without the user having to post it back...

        [Authorize, HttpGet, ActionName("StepOne")]
    public ActionResult StepOneGET(StepOneModel model)
    {
        var individual = _onsideService.Get(User.Identity.Name);

        model.PersonalInformation = new PersonalInformationModel
                                        {
                                            FirstName = individual.FirstName,
                                            LastName = individual.LastName,
                                            DoB = individual.DateOfBirth.ToString("dd/MM/yyyy"),
                                            Email = individual.DefaultEmail.EmailAddress,
                                            Phone = individual.DefaultPhone.Number,
                                            AddressLine1 = location.Address1,
                                            AddressLine2 = location.Address2,
                                            City = location.City,
                                            PostCode = location.PostalCode,
                                            Country = location.Country
                                        };

        // NOTE: Does not update ModelState
        TryValidateModel(model);

        // Need to return potential errors to user on page load

        return View(model);     
    }

Upvotes: 0

Views: 1254

Answers (1)

alexn
alexn

Reputation: 59002

Here is a snippet provided in another question here at SO. I don't take any credit for it, but it should do exactly what you want.

public static IList<KeyValuePair<string, string>> GetErrors(object obj)
    {
        // get the name of the buddy class for obj
        MetadataTypeAttribute metadataAttrib = obj.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true).FirstOrDefault() as MetadataTypeAttribute;

        // if metadataAttrib is null, then obj doesn't have a buddy class, and in such a case, we'll work with the model class
        Type buddyClassOrModelClass = metadataAttrib != null ? metadataAttrib.MetadataClassType : obj.GetType();

        var buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass).Cast<PropertyDescriptor>();
        var modelClassProperties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();

        var errors = from buddyProp in buddyClassProperties
                           join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name // as this is an inner join, it will return only the properties that are in both the buddy and model classes
                           from attribute in buddyProp.Attributes.OfType<ValidationAttribute>() // get only the attributes of type ValidationAttribute
                           where !attribute.IsValid(modelProp.GetValue(obj))
                           select new KeyValuePair<string, string>(buddyProp.Name, attribute.FormatErrorMessage(string.Empty));

        return errors.ToList();
    }

Upvotes: 2

Related Questions