For a short answer, you need to do three things:
- Remove
new { Checked = "checked" } from the second switch. This hard-coded value will cancel all magic actions. - When you return your ViewResult from the controller action, give it an instance of your model class where TermsAndConditions is false. This will provide the false default value that you need so that a false radio book is selected for you.
- Use
true and false as the values ββfor your radio buttons instead of "True" and "False" . This is because your property is of type bool . Strictly speaking, you accidentally selected the correct string representations for true and false , but the value parameter for the RadioButtonFor method is of type object . It is best to pass the actual type you want to compare instead of converting it to a string yourself. More on this below.
Here's what happens in depth:
The frame wants to do all this for you automatically, but you did these first two things wrong, which forces you to struggle with the frame to get the behavior you need.
The RadioButtonFor method calls .ToString() by the value of the property you specified and compares it with the .ToString() value that you passed when creating the switch. If they are equal, then it internally sets isChecked = true and finishes rendering checked="checked" in the HTML. Here's how he decides which switch to choose. It simply compares the value of the switch with the value of the property and checks the one that matches.
You can display switches for almost any property this way, and it will magically work. Lines, ints, and even listings all work! Any object that has a ToString method that returns a string that uniquely represents the value of the object will work. You just need to make sure that you set the value of the switch to a value that your property may have. The easiest way to do this is to simply pass in the value, not a string representation of the value. Let the structure convert it to a string for you.
(Since you managed to pass the correct string representations true and false , these values ββwill work as long as you correct your two actual errors, but it is still wise to pass the actual values, not their strings.)
Your first real mistake was hard coding Checked = "checked" for the "No" switch. This will override what the system is trying to do for you, and the results of this switch are always checked.
Obviously, you want the No switch to be pre-selected, but you must make it compatible with everything above. You need to provide a view of the instance of your model class, where the "Terms of Use" parameter is set to "false" and "bind" it to the switches. Typically, a controller action that responds to an initial GET request for a URL does not display an instance of the model class at all. Typically, you simply return View(); . However, since you want the default value to be selected, you must provide a view for your model instance for which the TermsAndConditions conditions are set to false.
Here are some sources to illustrate all of this:
Some kind of account class that you probably already have. (Model of your kind):
public class Account { public bool TermsAndConditions { get; set; }
Some methods in your controller:
//This handles the initial GET request. public ActionResult CreateAccount() { //this default instance will be used to pre-populate the form, making the "No" radio button checked. var account = new Account { TermsAndConditions = false }; return View( account ); } //This handles the POST request. [HttpPost] public ActionResult CreateAccount( Account account ) { if ( account.TermsAndConditions ) { //TODO: Other validation, and create the account. return RedirectToAction( "Welcome" ); } else { ModelState.AddModelError( "TermsAndConditionsAgreement", "You must agree to the Terms and Conditions." ); return View( account ); } } //Something to redirect to. public ActionResult Welcome() { return View(); }
The whole view:
@model Account @{ ViewBag.Title = "Create Account"; } @using ( Html.BeginForm() ) { <div> <span>Do you agree to the Terms and Conditions?</span> <br /> @Html.RadioButtonFor( model => model.TermsAndConditions, true, new { id = "TermsAndConditions_true" } ) <label for="TermsAndConditions_true">Yes</label> <br /> @Html.RadioButtonFor( model => model.TermsAndConditions, false, new { id = "TermsAndConditions_false" } ) <label for="TermsAndConditions_false">No</label> <br /> @Html.ValidationMessage( "TermsAndConditionsAgreement" ) </div> <div> <input id="CreateAccount" type="submit" name="submit" value="Create Account" /> </div> }
BONUS:. You will notice that I have added some extra features to the switches. Instead of just using plain text for radio button labels, I used an HTML label element with a for attribute set to the identifiers of each radio button. This allows users to click on a label to select a radio button instead of clicking on the button itself. This is standard HTML. To do this, I had to set manual identifiers on the switches, otherwise they both will get the same identifier only "TermsAndConditions", which will not work.