MVC5 RadioButtonFor model property not being bound properly

Jen picture Jen · Sep 18, 2014 · Viewed 14k times · Source

I'm using MVC5 with Razor views. My viewmodel has a property of type nullable enum. I made it nullable so that when the user loads the page they have to select an option and validates when they haven't selected anything.

public class PaymentViewModel
{
        [Required(ErrorMessage = "Please select a payment method", AllowEmptyStrings = false)]
        public PaymentType? SelectedPaymentType { get; set; }
}

public enum PaymentType
{
    CreditCard,
    DirectDebit
}

On my view I have a form and am calling submit which in turn calls a controller action as a post.

The relevant part of my view looks like this:

<div class="row button-group" data-toggle="buttons">
          <div class="col-xs-6">
              <label class="btn btn-tertiary">
                 @Html.RadioButtonFor(model => model.SelectedPaymentType, PaymentType.CreditCard, new {@Name = "payment-method", @Value = "credit", @Id="rdoCredit"}) 
                 Credit Card
              </label>
           </div>
           <div class="col-xs-6">
                 <label class="btn btn-tertiary">
                      @Html.RadioButtonFor(model => model.SelectedPaymentType, PaymentType.DirectDebit, new {@Name = "payment-method", @Value = "debit", @Id="rdoDebit"}) 
                      Direct Debit
                 </label>
            </div>
    </div>

For some reason the value coming through on my model.PaymentType is always null, even though I've selected a radio button. I added the @Id attribute as I noticed it was being given the same Id if I didn't specify one but that didn't help.

I've also tested another string property is coming through on the post so it seems specific to this property / radio button group.

If I make the property not nullable it gets set to CreditCard (being the first value of the enum), and if I select the DirectDebit radio option and submit the form it still says it is CreditCard.

(I'm sure I could be doing the labels better but my concern for now is to get the binding working properly

Edit. The html being generated is:

<form method="post" action="/myapplication/payment" novalidate="novalidate">
....
<div data-toggle="buttons" class="row button-group">
 <div class="col-xs-6">
   <label class="btn btn-tertiary">
<input type="radio" checked="checked" value="credit" name="payment-method" id="rdoCredit"> 
     Credit Card
   </label>
 </div>
 <div class="col-xs-6">
   <label class="btn btn-tertiary">
      <input type="radio" value="debit" name="payment-method" id="rdoDebit"> 
      Direct Debit
   </label>
 </div>
</div>
...
</form>

Answer

user3559349 picture user3559349 · Sep 18, 2014

Your rendering the name attribute as name="payment-method" but it should be SelectedPaymentType to match you model property name. Remove the { @name = "payment-method", You also don't need the value attribute

For better usability (with <label>)

@Html.RadioButtonFor(m=> m.SelectedPaymentType, PaymentType.CreditCard, new {@Id="rdoCredit"})
<label for="rdoCredit">Credit Card</label>
@Html.RadioButtonFor(m=> m.SelectedPaymentType, PaymentType.DirectDebit, new {@Id="rdoDebit"})
<label for="rdoDebit">Direct De</label>