2

I'm trying to implement what this answer suggests but without storing the display name in my model code, so I believe it's a separate question.

I have an MVC view

<%@ Page Language="C#" MasterPageFile="PathToMaster" Inherits="System.Web.Mvc.ViewPage<ModelData>" %>

and a model:

public class ModelData {
    public bool Option1 { get; set; }
}

and I have a .aspx with HTML markup for a form that contains a checkbox:

<label for="MyCheckbox">Your choice</label>
<%= Html.CheckBoxFor(Model=>Model.Option1, new { id="Option1", @class="checkbox", onchange="return myValidation();", name="MyCheckbox", value="Option one" } ) %>

which when it is compiled yields this HTML:

<label for="MyCheckbox">Your choice</label>
<input class="checkbox" id="Option1" name="Option1" onchange="return myValidation();" type="checkbox" value="Option one" /><input name="Option1" type="hidden" value="false" />

and whenever I check the checkbox and submit the form the controller-action

class MyController : Controller {
   [AcceptVerbs(HttpVerbs.Post)]
   public ActionResult RequestStuff( ModelData data )
   {
   }
}

receives data where Option1 is false.

What am I doing wrong? How do I make the checkbox map to the model member?

Community
  • 1
  • 1
sharptooth
  • 167,383
  • 100
  • 513
  • 979
  • 1
    I'm not quite sure that `Html.CheckBoxFor(Model=>Model.Option1)` is going to be correct, probably the lambda variable should not be named `Model`, which is an alias for, well, current model, and I don't know if it's going to override the alias. `Html.CheckBoxFor(item => item.Option1)` looks better, although I'm not sure if it's the source of the problem. By the way, the 'Id' generated by the view will correspond your property name and the value will correspond to the value, so you don't really have to set it yourself. And the 'value' most probably can only be true/false, not 'My value' :) – Patryk Ćwiek May 18 '12 at 10:42
  • By the way, I usually refrained from adding the custom HTML options when using the helpers, e.g. messing up the DOM element's ID will ruin your binding. The most I have ever added was `new { @class = "MyAwesomeStyle"}`. Everything else (the rendered description, value etc) was handled by preparing the view model, annotations etc. – Patryk Ćwiek May 18 '12 at 10:48
  • @Trust me - I'm a Doctor: What would be `item`? – sharptooth May 18 '12 at 10:50
  • A lambda expression variable, name it however you want. Essentially, it captures the model passed to the view, so after writing `item => item.` you'll get the Intellisense for the model's elements :) Html helpers work on expressions, hence the lambda statement. – Patryk Ćwiek May 18 '12 at 10:53
  • @Trust me - I'm a Doctor: Such change didn't help at all. – sharptooth May 18 '12 at 10:55
  • @Trust me - I'm a Doctor: Is it this thing? http://stackoverflow.com/a/2896565/57428 Looks like I already have this. – sharptooth May 18 '12 at 11:08

2 Answers2

2

Since you said changing the alias in the helper expression didn't cut it, I took the time to prepare the MVC2 test project, here's how it looks:

MyModel.cs:

namespace TestAppMVC2.Models
{
    public class MyModel
    {
       public bool Option1 { get; set; }
    }
}

Controller's actions:

    public ActionResult MyAction()
    {
        var viewModel = new MyModel();
        return View(viewModel);
    }


    [HttpPost]
    public ActionResult MyAction(MyModel viewModel)
    {
        bool option = viewModel.Option1;
        return View();
    }

The view (MyAction.aspx):

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

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

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

<h2>MyAction</h2>

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

    <fieldset>
        <legend>Fields</legend>

        <div class="editor-label">
            <%: Html.LabelFor(model => model.Option1) %>
        </div>
        <div class="editor-field">
            <%: Html.CheckBoxFor(model => model.Option1) %>
            <%: Html.ValidationMessageFor(model => model.Option1) %>
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

<div>
    <%: Html.ActionLink("Back to List", "Index") %>
</div>

Looks like this:

Basic action

And the result after checking the checkbox: Breakpoint stop

By the way, the View was generated entirely (well, almost entirely, I changed TextBoxFor to CheckBoxFor) by Add View -> Strongly Typed View for the MyModel class and template: Edit.

So it looks like the binding above should be OK. Try this and then you can fiddle with custom options on checkboxes. :)

Like I wrote in the other answer, the idea is essentially the same, only in MVC3 the Razor syntax looks a bit cleaner. But that's about it when it comes to differences. :)

Community
  • 1
  • 1
Patryk Ćwiek
  • 14,078
  • 3
  • 55
  • 76
0

In your line:

<%= Html.CheckBoxFor(Model=>Model.Option1, new { id="Option1", @class="checkbox", onchange="return myValidation();", name="MyCheckbox", value="Option one" } ) %>

Replace Model with another alias, i.e. m. So it looks like:

<%= Html.CheckBoxFor(m=>m.Option1, new { id="Option1", @class="checkbox", onchange="return      myValidation();", name="MyCheckbox", value="Option one" } ) %>

You referred to the Model directly where CheckBoxFor takes an an HTML helper instance.

I believe the following maybe appropriate to help you understand further:

MVC HTML Helpers and Lambda Expressions

Community
  • 1
  • 1
Darren
  • 68,902
  • 24
  • 138
  • 144