Two Models in One View, Validate only one of them

asp.net-mvc, asp.net-mvc-3, model, view

Solution

Create one form with `HtmlHelper<BlueUser>` and the other with `HtmlHelper<GreenUser>`, and make them post to different actions.

First, the view model is:

@model ParentModel

Then use `HtmlHelperFor` to create an HtmlHelper for each of the submodels:

@{
   var blueHtml = Html.HtmlHelperFor(Model.BlueUser);
   var greenHtml = Html.HtmlHelperFor(Model.GreenUser);
}

@using (blueHtml.BeginForm("BluePost", null)) {
   @blueHtml.EditorForModel()
}

@using (greenHtml.BeginForm("GreenPost", null)) {
   @greenHtml.EditorForModel()
}

Lastly, in the controller create a diferent POST action for each form:

[HttpPost]
public ActionResult BluePost(BlueUser model) {
   ...
}

[HttpPost]
public ActionResult GreenPost(GreenUser model) {
   ...
}

Here's the extension method:

public static class HtmlHelperFactoryExtensions {

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper) {
      return HtmlHelperFor(htmlHelper, default(TModel));
   }

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper, TModel model) {
      return HtmlHelperFor(htmlHelper, model, null);
   }

   public static HtmlHelper<TModel> HtmlHelperFor<TModel>(this HtmlHelper htmlHelper, TModel model, string htmlFieldPrefix) {

      var viewDataContainer = CreateViewDataContainer(htmlHelper.ViewData, model);

      TemplateInfo templateInfo = viewDataContainer.ViewData.TemplateInfo;

      if (!String.IsNullOrEmpty(htmlFieldPrefix))
         templateInfo.HtmlFieldPrefix = templateInfo.GetFullHtmlFieldName(htmlFieldPrefix);

      ViewContext viewContext = htmlHelper.ViewContext;
      ViewContext newViewContext = new ViewContext(viewContext.Controller.ControllerContext, viewContext.View, viewDataContainer.ViewData, viewContext.TempData, viewContext.Writer);

      return new HtmlHelper<TModel>(newViewContext, viewDataContainer, htmlHelper.RouteCollection);
   }

   static IViewDataContainer CreateViewDataContainer(ViewDataDictionary viewData, object model) {

      var newViewData = new ViewDataDictionary(viewData) {
         Model = model
      };

      newViewData.TemplateInfo = new TemplateInfo { 
         HtmlFieldPrefix = newViewData.TemplateInfo.HtmlFieldPrefix 
      };

      return new ViewDataContainer {
         ViewData = newViewData
      };
   }

   class ViewDataContainer : IViewDataContainer {

      public ViewDataDictionary ViewData { get; set; }
   }
}

Problem

I have a View that contains a ParentModel, which contains 2 Models. I only want to validate the fields of one or the other. Not both. Let´s say I have: ``` public ParentModel{ public BlueUser BlueUser {get; set;} public GreenUser GreenUser {get; set;} } ``` So the user selects either he is a GreenUser or a BlueUser. Each type of user has different fields, and depending which type of User the user selects, I want to only validate the fields on that specific type of user. How can this be achieved? EDIT: Both forms/models must be on the same View, maybe with some JQuery or Partials?

Original source