Airn5475 Airn5475 - 2 months ago 15
C# Question

How do I get the correct radio button selected using MVC RadioButtonFor with float values?

I have an editor template

Duration
that holds four simple radio buttons.

I am using this template for a property on my class
Test
.
I cannot get this property to bind to the radio button list and select the correct radio button on load. Selecting a value and submitting will return the correct value.
I have tried changing the values of the radio buttons to a variety of different values, but to no avail.

What value should I pass to
RadioButtonFor
to get this to work?
Ideally this editor template takes in nullable float and still works.

Duration.cshtml

@model float
<h3>Model Value: @Model</h3>
@Html.RadioButtonFor(model => model, 0.25F, new { id = "btnQuarterDay" }) @(.25F)
@Html.RadioButtonFor(model => model, 0.5F, new { id = "btnHalfDay" }) @(.5F)
@Html.RadioButtonFor(model => model, 0.75F, new { id = "btnThreeQuarterDay" }) @(.75F)
@Html.RadioButtonFor(model => model, 1.0F, new { id = "btnOneDay" }) @(1.0F)


Test.cs

public class Test
{
[UIHint("Duration")]
[Display(Name = "Days")]
public float Duration { get; set; }
}


HomeController

public class HomeController : Controller
{
public ActionResult Index(float? duration = null)
{
var model = new Test
{
Duration = duration.GetValueOrDefault(1F)
};
return View(model);
}

[HttpPost]
public ActionResult Index(Test model)
{
ViewBag.Success = true;
ViewBag.ValueSelected = model.Duration;
return View(model);
}
}


Index.cshtml

@model RadioButtonForTest.Models.Test

@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<div class="row">
<div class="col-md-4">
@Html.EditorFor(model => model.Duration)
@Html.ValidationMessageFor(model => model.Duration)
</div>
</div>

<button type="submit" class="btn btn-primary">Submit</button>
if (ViewBag.Success ?? false)
{
<span>Value Selected:</span> @ViewBag.ValueSelected
}
}


UPDATE: Plot Thickener

I wired up the Index action to take in duration, so that I can pass it via the query string. If a value is not passed via the query string. It will select the radio button below:

@Html.RadioButton("", Model, Model.Equals(1.0F), new { id = "radbtnOneDay4" })


If I navigate to the query string
/Home/Index?duration=.5

NOTHING is selected, but when debugging
Duration.cshtml
Model.Equals(.50F)
reports
TRUE
. So I would expect this radio button to be selected:

@Html.RadioButton("", Model, Model.Equals(.50F), new { id = "radbtnHalfDay4" })


Is this not crazy? Why is it not checking this radio button??? Is this a bug? Is there a custom model binders I could add to handle floats?

UPDATE 2

The query string parameter
duration
matches the model name and the query string is overriding the model value.

When I changed the parameter to be
dur
it worked fine. Using the following URL it would use the value from the ViewModel.
/Home/Index?dur=.5


I know there is a solid reason behind this...but this has been exasperating.

Answer

The RadioButtonFor helper does not work in templates (edit: ... in cases like yours when using it to bind to simple member values as model => model expression will become an empty name). You need to change your template code to

@Html.RadioButton("", 0.25F, Model == 0.25F, new { id = "btnQuarterDay" }) @(.25F)
@Html.RadioButton("", 0.5F, Model == 0.5F, new { id = "btnHalfDay" }) @(.5F)
@Html.RadioButton("", 0.75F, Model == 0.75F, new { id = "btnThreeQuarterDay" }) @(.75F)
@Html.RadioButton("", 1.0F, Model == 1.0F, new { id = "btnOneDay" }) @(1.0F)

Edit#2: another alternative would be to use a more complex model:

public class DurationContainer {
    public float Duration { get; set; }
}

public class Test2 {

    [UIHint("Duration2")]
    public DurationContainer Container { get; set; }
}

Index.cshtml:

@Html.EditorFor(model => model.Container)

And then as Duration2.cshtml template:

@Html.RadioButtonFor(model => model.Duration, 0.25F, new { id = "btnQuarterDay" }) @(.25F)
@Html.RadioButtonFor(model => model.Duration, 0.5F, new { id = "btnHalfDay" }) @(.5F)
@Html.RadioButtonFor(model => model.Duration, 0.75F, new { id = "btnThreeQuarterDay" }) @(.75F)
@Html.RadioButtonFor(model => model.Duration, 1.0F, new { id = "btnOneDay" }) @(1.0F)
Comments