Peter Smith
Peter Smith

Reputation: 5550

MVC 3 @Html.DropDownListFor model binding fails

I am using VS 2010 with MVC 3 and EF 5. I am using a common pattern for dropdown lists that works correctly in all but one instance and I cannot see why this one is failing to select the correct entry in the select list. The following are code snippets.

The select list is created as follows:

   public static IEnumerable<SelectListItem> GetOutcomes()
    {
        CodesEntities dataContextCodes = new CodesEntities(ConnectionString);

        return new SelectList(dataContextCodes.CodeOutcome.
            Where(x => x.DisplayOrder > 0).OrderBy(x => x.DisplayOrder), 
            "OutcomeCodeID", "Outcome");
    }

This returns the correct select list.

The view has the following code:

@Html.DropDownListFor(m => m.OutcomeCodeID,
                PerintalFormViewModels.GetOutcomes(), "Please select an item")

The model value m.OutcomeCodeID has a valid value (1) but no item is being selected.

The generated HTML is:

<select id="CodeID" name="OutcomeCodeID" data-val-required="Outcome is required" data-val-number="The field outcome must be a number." data-val="true">
<option value="">Please select an item</option>
<option value="1">Termination</option>
<option value="2">Loss</option>
<option value="3">Still</option>
<option value="4">Live</option>
</select>

I am in the hair tearing out, being driven nuts stage. Does anyone have any thoughts?

Thanks

Upvotes: 0

Views: 2793

Answers (2)

Michael Buen
Michael Buen

Reputation: 39393

You can do it like this:

public static IEnumerable<SelectListItem> GetOutcomes(string selectedID)
{
    CodesEntities dataContextCodes = new CodesEntities(ConnectionString);


    return new SelectList(dataContextCodes.CodeOutcome.
        Where(x => x.DisplayOrder > 0).OrderBy(x => x.DisplayOrder), 
        "OutcomeCodeID", "Outcome"
        , selectedID); // add this parameter
}

Or this:

public static IEnumerable<SelectListItem> GetOutcomes(string selectedID)
{
    CodesEntities dataContextCodes = new CodesEntities(ConnectionString);


    return        
      dataContextCodes.CodeOutCome
      .Where(x => x.DisplayOrder > 0)
      .OrderBy(x => x.DisplayOrder)
      .ToList()
      .Select(x => new SelectListItem 
      { 
          Value = x.OutcomeCodeID.ToString(),
          Text = x.Outcome.ToString(),
          Selected = x.OutcomeCodeID == selectedID
      });
}

Then call it like this:

@Html.DropDownListFor(m => m.OutcomeCodeID,
            PerintalFormViewModels.GetOutcomes(Model.OutcomeCodeID), 
            "Please select an item")

Upvotes: 1

Rui
Rui

Reputation: 4886

You are not setting the default selected value anywhere.

The particular constructor you are using for the SelectList is this one:

public SelectList(
    IEnumerable items,
    string dataValueField,
    string dataTextField
)

Which does not set the default value. Either you use this one:

public SelectList(
    IEnumerable items,
    string dataValueField,
    string dataTextField,
    Object selectedValue
)

And specify the selectedValue or you manually set the SelectedListItem's Selected property to true on the item you want selected (http://msdn.microsoft.com/en-us/library/system.web.mvc.selectlistitem(v=vs.108).aspx).

It's a shameless plug but still I think it's a good resource: http://blinkingcaret.wordpress.com/2012/08/11/using-html-dropdownlistfor/

Upvotes: 0

Related Questions