Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I keep validation rules inside of entity while using a view model inside controller?

So I've got an entity in my Models directory:

public class Event
{
    public int Id { get; set; }

    [Required, MaxLength(50), MinLength(3)]
    public string Name { get; set; }

    [Required, MaxLength(2000)]
    public string Description { get; set; }
}

and I want to expose it to views using a viewModel:

public class BaseEventViewModel
{
    public string Name { get; set; }

    [DataType(DataType.MultilineText)]
    public string Description { get; set; }
}

public class EventCreateViewModel : BaseEventViewModel
{

}

My reasoning behind this is that I want all the data validation to be done on the entity, and all the presentation stuff (such as rendering a text area) to be done on the view model. Then I can use however many view models I want to represent my entity, while maintaining data integrity.

So I changed my controller to use the new view model:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(EventCreateViewModel viewModel)
    {
        if (ModelState.IsValid)
        {
            db.Events.Add(new Event
            {
                Name = viewModel.Name,
                Description = viewModel.Description
            });
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(viewModel);
    }

However none of the entity validation gets done and I'm able to submit a blank form which raises a DbEntityValidationException exception.

Presumably this is because ModelState.IsValid is working on the view model, not the entity that the view model represents. How can I catch these validation errors?

like image 760
John Dorean Avatar asked Jan 26 '15 19:01

John Dorean


1 Answers

I actually found the answer after being prodded in the right direction. If I add this annotation to my view model, it will inherit all of the annotations applied to the properties on my entity:

[MetadataType(typeof(Event))]
public class BaseEventViewModel
{
    public int Id { get; set; }

    public string Name { get; set; }

    [DataType(DataType.MultilineText)]
    public string Description { get; set; }
}

Now when I submit a blank form I get shown the validation errors as normal.

This does come with the caveat of having to redefine every property again inside my view model, which kind of defeats the point of a view model only holding the properties you require, however it works for my case.

like image 156
John Dorean Avatar answered Sep 27 '22 23:09

John Dorean