0

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 />

1 Answer 1

2

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() %>
Sign up to request clarification or add additional context in comments.

10 Comments

I have updated my question. Thanks to remember to put all stuff here :)
Yes, that's exactly as what I though. You didn't respected the naming convention. Look at the generated markup and make sure you respect the naming convention.
Ok, I put the TemplateInfo but at HTTP_POST, I received all three checkboxes in SampleModelList (no matter how many I checked) and the Name parameter is null. I verified naming convention.
It's perfectly normal that the Name parameter is null. You do not have a corresponding input field for it inside your partial. Only a label. But as you know a label is just something rendered in the view, it's value will never be sent to the server. Use a hidden field or a text field if you want to send its value. As far as the checkboxes are concerned, it is also perfectly normal that you get 3 elements. That's how the CheckBoxFor helper works. If you observe carefully your generated markup you will see that the helper put an additional hidden field for each checkbox with the value="false"
So you will get 3 checkboxes but the IsChecked boolean property will depend on whether you checked or not the corresponding checkbox. Also you have another problem with your checkbox. You have set its value to the Model.Id. Why? That's wrong. A checkbox can have 2 states: checked and unchecked => you should map it to boolean fields. So fix your code in the partial: <%= Html.CheckBoxFor(x => x.IsChecked) %>.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.