1
votes

Environment: Entity Framework (v6.0) with MVC and Razor. Backend is SQL Server.

HTML helper DropDownListFor() is working perfectly for a string column on the database. However, when I use a decimal column with a numeric dropdownlist the framework does not select the value loaded from the database when the form is rendered.

I assume this is related to the fact that DropDownListFor() contains strings for both Text and Value, and cannot match the decimal value from the database, so SelectedItem is not determined.

I've tried casting within the HTML helper, but fails either at compile or runtime. All examples I can find assume you want to select a string, not a number.

Any help gratefully received. Thanks.

View code: the problem field is CollarSize. The dropdownlist is CollarSizeSelect.

<div class="form-group">
     @Html.LabelFor(model => model.CollarSize, htmlAttributes: new { @class = "control-label col-md-2" })
     <div class="col-md-10">
            @Html.DropDownListFor(model => model.CollarSize, Model.CollarSizeSelect, htmlAttributes: new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.CollarSize, "", new { @class = "text-danger" })
     </div>
</div>

The class definition contains the column defined thus:

public Nullable<decimal> CollarSize { get; set; }

CollarSize dropdown list is built as follows:

public IEnumerable<SelectListItem> ChestSizeSelect
{
    get
    {
        return GetSelectNumberRange(32, 60, (decimal)1.0);
    }
}

private static List<SelectListItem> GetSelectNumberRange(int start, int end, decimal increment)
{
    List<SelectListItem> numlist = new List<SelectListItem>();
    for (decimal i = start; i <= end; i = i + increment)
    {
       numlist.Add(new SelectListItem() {Text = i.ToString(), Value = i.ToString()});
    }
    return numlist;
}
1
There is no such thing as decimal in html. If the value of CollarSize matches exactly the value of one of your options (i.e. using ToString()) then that option will be displayeduser3559349
Thanks. I tried that, but got InvalidOperationException. Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions. I tried: @Html.DropDownListFor(model => model.CollarSize.ToString(),S Jones
No, I don't mean to do that! What is the value of CollarSize. If its (say) 42 and you have an option with value="42" then it will be selected. Does the value of CollarSize match exactly the value of one of your optionsuser3559349
Yes, there is a match e.g. CollarSize = 15.0, CollarSizeSelect has an entry for "15.0" (string).S Jones
Works fine for me - refer this DotNetFiddle. I suspect CollarSize.ToString() is not returning "15.0"user3559349

1 Answers

1
votes

The issue was not the construction of the SelectList, but due to the underlying database schema.

The database column:

CollarSize decimal(5, 2) NULL,

I used Entity Framework to build the model from the database (wizard option "EF Designer from database"). EF generated the field in the generated model:

public Nullable<decimal> CollarSize { get; set; }

The SelectList I generated to populate the DropDownListFor() contained a list of decimal items, but these items had a precision of a one decimal place, i.e. 15.0M. However, EF preserved the original precision, so when the DropDownList was being populated the Selected item could not be found since it was comparing 15.0 with 15.00.

My solution was to build the SelectList with explicit precision:

public IEnumerable<SelectListItem> CollarSizeSelect
{
    get
    {
         return new SelectList(new List<decimal> { 14.00M, 14.50M, 15.00M, 15.50M...
    }
}