开发者

ASP.NET MVC 3 - Validation Question

Good evening everyone I have a question regarding validation of drop-down list values. I have a view that is bound to a view model type called ReservationData.

This object contains a property CustomerVehicles of type List<VehicleData>. VehicleData has two int properties VehicleMakeId and VehicleModelId.

On my view I am trying to loop over the number of items in the CustomerVehicles collection and displaying two dropdowns for each, a vehicle make dropdown and a vehicle model dropdown using DropDownListFor.

When I try to submit and validate I do not see any validation errors displayed on the screen.

Just in case you are wondering I have added a ValidationMessageFor for each dropdown as well. I am not sure if this is an issue with the structure of my view model and its complexity and how the controls need to be named or how the ids need to be set. Any help would be greatly appreciated.

Here is the code for the looping over the collection:

@for (var i = 0; i < Model.CustomerVehicles.Count(); i++)
    {
        var vehicleNumber = i + 1;
        <div class="vehicle-selection-wrapper">
            <div class="content-container">
                <h3>
                    Vehicle @vehicleNumber</h3>
                <img class="vehicle-image" alt="manufacturer image" src="@Url.Content("~/Content/images/default-vehicle.gif")" /><br />
                @Html.LabelFor(m => m.CustomerVehicles[i].VehicleMakeId)
                @Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
            , new SelectList(Model.VehicleMakes, "Id", "Name")
                          , @UIDisplay.Dropdown_DefaultOption, new { @class = "long-field" })<br />
                @Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleMakeId)<br />
                @Html.LabelFor(m => m.CustomerVehicles[i].VehicleModelId)
                @Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleModelId
            , new SelectList(new List<CWR.Domain.VehicleModel>(), "Id", "Name")
                 , @UIDisplay.Dropdo开发者_如何学Pythonwn_DefaultOption, new { @class = "long-field" })
                @Html.ValidationMessageFor(m => m.CustomerVehicles[i].VehicleModelId)
            </div>
        </div>
    }

Ok so I also noticed that in the generated HTML the selects that are generated are missing the HTML5 data-val attributes that are associated to elements to handle validation. Here is the generated HTML

<select class="long-field" id="CustomerVehicles_0__VehicleMakeId"         name="CustomerVehicles[0].VehicleMakeId"><option value="">-- Select --</option>
</select><br />
<span class="field-validation-valid" data-valmsg-  for="CustomerVehicles[0].VehicleMakeId" data-valmsg-replace="true"></span><br />
<label for="CustomerVehicles_0__VehicleModelId">Model</label>
<select class="long-field" id="CustomerVehicles_0__VehicleModelId" name="CustomerVehicles[0].VehicleModelId"><option value="">-- Select --</option>
</select>
<span class="field-validation-valid" data-valmsg-for="CustomerVehicles[0].VehicleModelId" data-valmsg-replace="true"></span>

Additionally in my VehicleData class the VehicleMakeId and VehicleModelId properties are decorated with a Required attribute.

UPDATE:

Ok so I was testing and noticed that if I keep my code identical except I swap the Html.DropdownListFor calls with Html.TextboxFor calls then the validation works. What could be causing this? Could it be a framework bug with the unobtrusive validation?

UPDATE: Contains Fix

So after posting this same question on the ASP.NET Forums, I was able to get a solution. In the post you will be able to see that there is a bug in the unobtrusive validation framework and how it handles validation of dropdownlists. The user counsellorben does a good job in explaining the problem as well as a solution (including sample code) that will assist others in avoiding this issue in the future, or at least until Microsoft builds in a fix in to the framework.

Thank you everyone for your assistance.


I too have come across this obviously massive oversight regarding client side validation with dropdownlists in MVC 3 and the best solution I can offer is to put the missing HMTL attributes in yourself.

In your view model create a property like this.

public Dictionary<string, object> CustomerVechicleAttributes
    {
        get
        {
            Dictionary<string, object> d = new Dictionary<string, object>();
            d.Add("data-val", "true");
            d.Add("data-val-required", "Please select a Vechicle.");
            return d;
        }
    }

Then in your code, enter

@Html.DropDownListFor(m => m.CustomerVehicles[i].VehicleMakeId
            , new SelectList(Model.VehicleMakes, "Id", "Name")
            , @UIDisplay.Dropdown_DefaultOption, 
            **Model.CustomerVechicleAttributes** })

Just add the Model.CustomerVechicleAttributes as htmlAttributes to your dropdownlist. This will inject the necessary attributes that are missing. You will of course need to add any other attributes you may need like your class attribute.

Hope this helps.


This is the simpliest way I found to do it, just adding data-val-*-* attributes in HtmlAttributes of DropDownListFor, inside the view. The following method works with RemoteValidation too, if you do not need remote validation, simply remove the elements containing data-val-remote-*:

        @Html.DropDownListFor(m => m.yourlistID, (IEnumerable<SelectListItem>)ViewBag.YourListID, String.Empty, 
        new Dictionary<string, object>() { { "data-val", "true" }, 
        { "data-val-remote-url", "/Validation/yourremoteval" }, 
        { "data-val-remote-type", "POST" }, { "data-val-remote-additionalfield", "youradditionalfieldtovalidate" } })

I hope it may help. Best Regards!


you should try to add data annotations on your view model properties first so you could see the validation messages.

you might find what you need here

http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx

or create custom ones if needed.

what exactly do you need to validate?


I had exactly the same problem with the field getting correctly validated in TextBoxFor but not in DropDownListFor.

@Html.DropDownListFor(m => m.PaymentTO.CreditCardType,   Model.CreditCardTypeList, "Select Card Type", new { style = "width:150px;" }) 

Since I had another DropDownListFor working on the same page, I knew that it wasn’t a generic DropDownListFor problem. I also have a complex model and parent object PaymentTO wasn’t initialized. When I set viewTO.PaymentTO = new PaymentTO(); in the Controller, the validation for the DropDownListFor started to work. So there is probably a problem with DropDownListFor, but the fix can be as simple as initializing the object in the controller.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜