5

I have the following model class:

public abstract class CompanyFormViewModelBase
{
    public CompanyFormViewModelBase()
    {
        Role = new CompanyRoleListViewModel();
        ContactPerson = new PersonListViewModel();
        Sector = new SectorListViewModel();
    }
    [Required]
    [Display(Name = "Company Name")]
    public string CompanyName { get; set; }
    public CompanyRoleListViewModel Role { get; set; }
    [Display(Name = "Contact Name")]
    public PersonListViewModel ContactPerson { get; set; }
    public SectorListViewModel Sector { get; set; }
}
public class AddCompanyViewModel : CompanyFormViewModelBase, IValidatableObject
{
    public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
    {
        PlugandabandonEntities db = new PlugandabandonEntities();
        CompanyName = CompanyName.Trim();

        var results = new List<ValidationResult>();

        if (db.Company.Where(p => p.CompanyName.ToLower() == CompanyName.ToLower()).Count() > 0)
            results.Add(new ValidationResult("Company already exists.", new string[] { "CompanyName" }));
        return results;
    }
}

It works fine with "classic" using like:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(Plugandabandon.ViewModels.AddCompanyViewModel model)
    {
        if (ModelState.IsValid)
        {
            CreateCompany(model);
            return RedirectToAction("Index");
        }
        else
        {
            return View(model);
        }
    }

But I want to use this model class for another, ajax form also. I have the following method:

   public JsonResult ReturnJsonAddingCompany(string companyName, int roleID, int sectorID, int personID)
    {
        Plugandabandon.ViewModels.AddCompanyViewModel model = new ViewModels.AddCompanyViewModel()
        {
            CompanyName = companyName,
            ContactPerson = new ViewModels.PersonListViewModel()
            {
                SelectedItem = personID
            },
            Role = new ViewModels.CompanyRoleListViewModel()
            {
                SelectedItem = roleID
            },
            Sector = new ViewModels.SectorListViewModel()
            {
                SelectedItem = sectorID
            }
        };

        ValidateModel(model);

        if (ModelState.IsValid)
        {
            CreateCompany(model);
        }
        else
        {
            throw new Exception("Company with such name already exists");
        }

        var list = Utils.CompanyList();
        return Json(list, JsonRequestBehavior.AllowGet);
    }

Look at

    ValidateModel(model);

line. If model is correct - it works fine. If not correct - it throw exception and break a continue executing of method (and return exception to view). Also, if I set breakpoint on

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)

method, it never called in invalid model case! (with valid model Validate method is called). I want to have the behaviour like "classic" method, just validate model and then validate ModelState.IsValid. Behaviour of ValidateModel(model) is very strange for me, it's a "black box"...

Oleg Sh
  • 8,496
  • 17
  • 89
  • 159
  • 1
    You need to use [TryValidateModel](https://msdn.microsoft.com/en-us/library/system.web.mvc.controller.tryvalidatemodel%28v=vs.118%29.aspx). But why does your `ReturnJsonAddingCompany()` method not just have `Plugandabandon.ViewModels.AddCompanyViewModel model` as the parameter? –  May 15 '15 at 12:43
  • because I call it via ajax – Oleg Sh May 15 '15 at 12:54
  • What does that have to do with it. You can serialize you form or you can name the values you post the same as the model properties if your controls have no relationship to the model –  May 15 '15 at 12:56
  • maybe you are right. But in this case it's more comfortable for me to pass just like parameters, not model.. – Oleg Sh May 15 '15 at 13:01

1 Answers1

4

ValidateModel() throws an exception if the model is not valid. Instead, use TryValidateModel()

From the documentation

The TryValidateModel() is like the ValidateModel() method except that the TryValidateModel() method does not throw an InvalidOperationExceptionexception if the model validation fails.

  • Yeah except `TryValidateModel()` still throws an exception if the model is null. A custom attribute might be useful https://khalidabuhakmeh.silvrback.com/fixing-webapi-s-null-parameter-value-and-validation. – David Clarke Jun 23 '20 at 00:17