asp .net mvc 5 dropdownlist SelectList no validation attributes

Krzysiek picture Krzysiek · Dec 11, 2014 · Viewed 9.1k times · Source

Inside model I have data annotations:

    [Required(ErrorMessageResourceName = "SelectCategory", ErrorMessageResourceType = typeof(MyProject.Properties.Resources)), Range(1, int.MaxValue, ErrorMessageResourceName = "SelectCategory", ErrorMessageResourceType = typeof(MyProject.Properties.Resources))]
    public int CategoryId { get; set; }
    public virtual Category Category { get; set; }

and two situations:

Situation1

Inside controller I have

    List<Category> categories = db.GetCategories();
    ViewBag.CategoryId = categories;

Inside View:

<div class="form-group">
    @Html.LabelFor(model => model.CategoryId, htmlAttributes: new { @class = "control-label col-md-3" })
    <div class="col-md-6">
        @Html.DropDownListFor(model => model.CategoryId, new SelectList(ViewBag.CategoryId, "Id", "Name", 2), htmlAttributes: new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.CategoryId, "", new { @class = "text-danger" })
    </div>
</div>

Html result:

<div class="form-group">
    <label class="control-label col-md-3" for="CategoryId">Category</label>
    <div class="col-md-6">
    <select class="form-control" data-val="true" data-val-number="The field Category must be a number." data-val-range="Select category" data-val-range-max="2147483647" data-val-range-min="1" data-val-required="Select category" id="CategoryId" name="CategoryId">
        <option value="0">---Select---</option>
        <option value="1">Cat1</option>
        <option value="2">Cat2</option>
        <option value="3">Cat3</option>
    </select>
        <span class="field-validation-valid text-danger" data-valmsg-for="CategoryId" data-valmsg-replace="true"></span>
    </div>
</div>

I have validation attributes inside 'select' element, but no selected element

Situation2:

Inside controller I have

    List<Category> categories = db.GetCategories();
    ViewBag.CategoryId = new SelectList(categories, "Id", "Name", 2);

Inside View:

<div class="form-group">
    @Html.LabelFor(model => model.CategoryId, htmlAttributes: new { @class = "control-label col-md-3" })
    <div class="col-md-6">
        @Html.DropDownList("CategoryId", null, htmlAttributes: new { @class = "form-control" })
        @Html.ValidationMessageFor(model => model.CategoryId, "", new { @class = "text-danger" })
    </div>
</div>

Html result:

<div class="form-group">
    <label class="control-label col-md-3" for="CategoryId">Category</label>
    <div class="col-md-6">
        <select class="form-control" id="CategoryId" name="CategoryId">
            <option value="0">---Select---</option>
            <option value="1">Cat1</option>
            <option selected="selected" value="2">Cat2</option>
            <option value="3">Cat3</option>
        </select>
        <span class="field-validation-valid text-danger" data-valmsg-for="CategoryId" data-valmsg-replace="true"></span>
    </div>
</div>

I have no validation attributes inside 'select' element, but I have selected element

Could anyone explain me what is wrong? What should I do to have validation attributes and selected option?

Answer

user3559349 picture user3559349 · Dec 11, 2014

Firstly, you cannot use the same name for the ViewBag property as your model property. Change the ViewBag property to (say) ViewBag.CategoryList

Secondly you categories appears to contain an item with ID=0 and Name="Select" so all your options have a value (zero is an integer so its valid) and you will never get an error message. Remove that item from categories and use

@Html.DropDownListFor(m => m.CategoryId, new SelectList(ViewBag.CategoryList, "Id", "Name"), "--Select--", new { @class = "form-control" })

This will render

<select class="form-control" data-val="true" data-val-number="The field Category must be a number." data-val-range="Select category" data-val-range-max="2147483647" data-val-range-min="1" data-val-required="Select category" id="CategoryId" name="CategoryId">
    <option value>---Select---</option>
    <option value="1">Cat1</option>
    <option value="2">Cat2</option>
    <option value="3">Cat3</option>
</select>

Note the first option has no value, so if this one is selected, the Required validation error will be displayed.

Finally, to set the selected item when the page is first rendered, assign it to the property in the controller before you pass the view

model.CategoryId = 2;
return View(model);

and the the 3rd option("Cat2") will be selected by default.