4

I have a page contains a drop down list for a enum which is binding on a field in the model, also I have a url parameter have the same name(first letter's case is not same).

When the url parameter is empty, the binding for the enum is not correct. To clarify my question, please see the detail code below.

For example, when the url is Index?eventType=, the view initially show Type1 instead of Type2. Is there any special rule for the MVC5 cause that weird behavior?

When I either change the url parameter name or the field name in the model, the drop down list could select Type2 when load Index?eventType=

View:

@model TestMode
@{
    Layout = null;
}

@Html.EnumDropDownListFor(m => m.EventType)

Controller:

    public ActionResult Index(int? eventType)
    {
        var viewModel = new TestMode();
        viewModel.EventType = eventType.HasValue ? 
                              (CalendarEventType)eventType.Value :
                               CalendarEventType.Type2;
        //Check the value of EventType here is CalendarEventType.Type2, but when the view loaded, there are not selected for the drop down list of enum
        return View(viewModel);
    }

ViewModel:

public class TestMode
{
    public CalendarEventType EventType { get;set;}
}

public enum CalendarEventType
{
    Type1 = 0,
    Type2 = 1,
}

HTML for the Index?eventType=, there are no option be selected.

<select data-val="true" data-val-required="EventType field is required" id="EventType" name="EventType">
    <option value="0">Type1</option>
    <option value="1">Type2</option>
</select>
2power10
  • 1,259
  • 1
  • 11
  • 33
  • I assume that you mean when the page loads, the dropdown list has Type1 selected instead of Type2... I think that's normal behavior because Type1 is the first option of the enum. – drneel Aug 15 '15 at 13:59
  • Try making your enum nullable in the model – mbudnik Aug 15 '15 at 14:00
  • @drneel , But in the view, I already bind this drop down list to the EventType in the viewModel, and if I rename either eventType in url or EventType in Mode, it could work correctly. – 2power10 Aug 15 '15 at 14:01
  • @imJustice are you saying that the problem is that the eventtype is not posting the correct value to your action? – drneel Aug 15 '15 at 14:04
  • @drneel No. The problem is the value in the model not set to the enum drop down list in the view correctly. – 2power10 Aug 15 '15 at 14:10
  • What value does event type have when you hit the specified url – Nick Bailey Aug 15 '15 at 14:15
  • @imJustice I was able to duplicate the issue; and that is not behaving as I would have expected. Good question... – drneel Aug 15 '15 at 14:30
  • @mbudnik Tried your suggestion, it will initial select the first null option. I think the problem here is the mvc not set value in the model to the select control, – 2power10 Aug 15 '15 at 14:33
  • @NickBailey I'm not sure which position you ask for the event type value. In the action method of controller, the eventType is null. – 2power10 Aug 15 '15 at 14:36
  • It looks like MVC might be doing something with the querystring parameter as part of the initialization... If I change the action parameter to foo such that the url is 'index?foo=' it behaves as expected – drneel Aug 15 '15 at 14:51
  • @drneel I think you might be right. This only happened, when the url parameter and the binding field name is the same. – 2power10 Aug 15 '15 at 14:58
  • Make sure you have a public setter! – eddiewould May 07 '19 at 04:15

1 Answers1

2

This is the default behavior. Your parameter is named eventType so when the method is called, the value of eventType is added to ModelState (which will be null) by the DefaultModelBinder.

When you use html helpers, in your case EnumDropDownListFor(), they use the values from ModelState (if they exist) rather than the actual value of your property, so the helper is effectively using a value of null, not Type2, for binding. Because null does not match one of the enum values, the first value (Type1) is selected (because something has to be).

The reason for this behavior is explained in the second part of this answer.

The easiest solution is to change the name of the parameter so it does not match the name of one of your properties (note the DefaultModelBinder is not case sensitive so eventType and EventType are effectively the same). An alternative is to add ModelState.Clear() before you initialize the TestMode object.

Community
  • 1
  • 1