Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to validate an MVC-3 model without validating "sub-models"?

I have a class that requires another class to be specified, but I don't want the MVC ModelState validator to check whether the secondary model is valid. Is this possible?

Here's a brief overview:

My entities look something like this:

public class WidgetType
{
    public long Id { get; private set; }

    [Required]
    public string Name { get; set; }

    ...
}

public class Widget
{
    public long Id { get; private set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public WidgetType WidgetType { get; set; }

    ...
}

I have them encapsulated in a WidgetViewModel class that I'm passing to/from the View like this:

public class WidgetViewModel
{
    public Widget Widget { get; set; }

    public ICollection<WidgetType> WidgetTypes
    {
        get
        {
            return _repository.GetWidgets();
        }
    }

    ...
}

My view looks something like this:

...
@Html.DropDownListFor( m => m.Widget.WidgetType.Id, new SelectList( new EquipmentViewModel().EquipmentTypes, "Id", "Name" ) )
...

All of this works except for validation. ModelState.IsValid is always false because "Widget.WidgetType.Name" is required. I need the user to select a WidgetType, but I don't want ModelState to be validated deeper than "Widget.WidgetType.Id" (which should be all that Widget needs for its foreign key?).

Is there a better way to do this? I feel like there should be some way to validate without recursively inspecting deeper into the properties, but I can't find it. What am I missing...?

like image 330
Farray Avatar asked Dec 21 '25 06:12

Farray


2 Answers

public class WidgetViewModel
{    
    [Required]
    public string Name { get; set; }

    [Required]
    public WidgetType WidgetTypeId { get; set; }

    public SelectList WidgetTypes 
    {
        get
        {
             //This should be popuplated in your controller or factory not in the view model
             retun new SelectList{ _repository.GetWidgets(),"Id","Name");

        }
   }
}

In your view

 @Html.DropDownListFor( m => m.WidgetTypeId, Model.WidgetTypes)

And in your controller

public ActionResult Create(WidgetViewModel model)
{
    Widget widget = new Widget{
         Name = model.Name,
         WidgetType = yourManager.GetWidgetTypeByID(model.WigetTypeId);
    };

    yourManager.Create(widget);

    //...
}
like image 99
Gregoire Avatar answered Dec 22 '25 19:12

Gregoire


If all you need in your view is the WidgetID then you don't need to include the entire Widget in the WidgetViewModel. Just have property called WidgetID. View model classes should have only the data the is necessary for the view.

In the controller action method that is called when you submit the form, you can use the WidgetID to fetch the Widget object from the database if it is needed.

like image 22
HitLikeAHammer Avatar answered Dec 22 '25 18:12

HitLikeAHammer