Question

I have a simple model like:

public class AppointmentModel
   {
      private static List<SampleModel> _list;

      public string ClientName {
         get;
         set;
      }

      [DataType( DataType.Date )]
      public DateTime Date {
         get;
         set;
      }

      public bool TermsAccepted {
         get;
         set;
      }

      public List<SampleModel> SampleModelList {
         get;
         set;
      }

      public static List<SampleModel> GetSampleList() {
         if ( _list == null ) {

            _list = new List<SampleModel>( 0 );

            _list.Add( new SampleModel {
               Id = 1,
               Name = "Test",
               IsChecked = false
            } );

            _list.Add( new SampleModel {
               Id = 2,
               Name = "Another test",
               IsChecked = true
            } );

            _list.Add( new SampleModel {
               Id = 3,
               Name = "All test",
               IsChecked = false
            } );
         }

         return _list;
      }
   }

SampleModel looks like (it is created to simulate checkbox inputs):

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

      public string Name {
         get;
         set;
      }

      public bool IsChecked {
         get;
         set;
      }
   }

In my view, I implemented:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SimpleAppWithModelBinding.Models.AppointmentModel>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Page
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Page</h2>

   <% using ( Html.BeginForm(FormMethod.Post) ) { %>
         <%:Html.ValidationSummary()%>

      <p>Name: <%: Html.EditorFor( model => model.ClientName )%></p>
      <p>Date: <%: Html.EditorFor( model => model.Date )%></p>
      <p><%: Html.EditorFor( model => model.TermsAccepted )%> Accept terms</p>

      <%-- here I put the checkbox list using editor template --%>
      <%: Html.Action( "RenderPartialSample" ) %>

      <input type="submit" value="Test" />
   <%} %>

</asp:Content>

and the controller side, HomeController:

      public ActionResult Page() {

         return View();
      }

      // explicit validate model
      [HttpPost]
      public ActionResult Page( AppointmentModel model ) {

        // do some verification here

         if ( model.SampleModelList == null || ( model.SampleModelList != null && model.SampleModelList.Count == 0 ) ) {
            ModelState.AddModelError( "SampleModelList", "Please check something !" );
         }

         if ( ModelState.IsValid ) {
            //do something here
            return View( "Completed", model );
         } else {
            return View( "Page", model );
         }
      }


      public PartialViewResult RenderPartialSample() {
         List<SampleModel> model = new List<SampleModel> {
            new SampleModel{
               Id = 1,
               IsChecked = true,
               Name = "Test"
            },

            new SampleModel{
               Id = 2,
               IsChecked = false,
               Name = "Test1"
            },

            new SampleModel{
               Id = 3,
               IsChecked = false,
               Name = "Test2"
            }
         };

         AppointmentModel a = new AppointmentModel();
         a.SampleModelList = model;

         return PartialView( "SamplePartialView", a.SampleModelList );
      }

The problem:

When I press submit, the public ActionResult Page( AppointmentModel model ) gave me a model and he has SampleModelList null, always is null. I want to have the checked inputs in that list from model but maybe is not working because of partial view.

How to validate two models in my case ? Or what is the best approach in my case, maybe my approach is not good.

Please help :)

UPDATE:

SamplePartialView contains:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<List<SimpleAppWithModelBinding.Models.SampleModel>>" %>

<%: Html.EditorForModel() %>

and the template:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<SimpleAppWithModelBinding.Models.SampleModel>" %>

<%: Html.HiddenFor( x => x.Id ) %>
<%: Html.CheckBoxFor( x => x.IsChecked, new {
      value = Model.Id
   } )%>
<%: Html.LabelFor( x => x.IsChecked, Model.Name ) %>

<br />
Was it helpful?

Solution

You haven't shown the SamplePartialView partial but I suspect that inside you didn't respect the naming convention for your input fields. They were not prefixed with SampleModelList in order to respect the naming convention of the default model binder.

Inside this partial you should have input fields that look like this:

<input type="text" name="SampleModelList[0].Id" value="1" />
<input type="text" name="SampleModelList[0].Name" value="name 1" />

<input type="text" name="SampleModelList[1].Id" value="1" />
<input type="text" name="SampleModelList[1].Name" value="name 1" />

...

Look at the rendered markup for your form and make sure you have respected this convention.

In order to respect this naming convention you could set the template prefix, either inside the child controller action rendering your partial:

ViewData.TemplateInfo.HtmlFieldPrefix = "SampleModelList";
return PartialView("SamplePartialView", a.SampleModelList);

or inside the partial itself if you prefer:

<%@ Control 
    Language="C#" 
    Inherits="System.Web.Mvc.ViewUserControl<List<SimpleAppWithModelBinding.Models.SampleModel>>" 
%>
<% ViewData.TemplateInfo.HtmlFieldPrefix = "SampleModelList"; %>
<%= Html.EditorForModel() %>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top