代码之家  ›  专栏  ›  技术社区  ›  Chris

ASP.NET MVC2验证不适用于IE<8中的下拉列表

  •  0
  • Chris  · 技术社区  · 14 年前

    我有一个带有DropDownList的表单,该表单使用 Html.DropDownListFor(...) . 与下拉列表对应的视图模型字段具有 [Required(...)] 附加到它的属性。这在我的本地计算机上工作正常,但是一旦我发布到我们的开发服务器,下拉列表就会继续显示所需的错误消息,即使在列表中选择了一个值。这只在IE中发生-火狐提交很好。

    有什么想法吗?

    相关代码

    观点:

    <ol class="form">
        <li>
            <%= Html.LabelFor(x => x.ContactTitle) %>
            <%= Html.DropDownListFor(x=>x.ContactTitle, Model.GetTitleOptions()) %>
            <%= Html.ValidationMessageFor(x => x.ContactTitle) %>
        </li>
        <!-- more fields... -->
    </ol>
    

    视图模型:

    [Required(ErrorMessage = "Title is required")]
    [DisplayName("Title")]
    public string ContactTitle { get; set; }
    
    // ...
    
    public SelectList GetTitleOptions()
    {
        return new SelectList(new string[] 
        {
            "","Dr.", "Mr.", "Ms.", "Mrs.", "Miss"
        });
    }
    

    这些都是很基本的东西…我不知所措。

    编辑:刚刚发现这个bug仅限于IE8兼容性视图(可能是以前的版本)。IE 8在标准模式下按预期工作…

    1 回复  |  直到 14 年前
        1
  •  2
  •   Chris    14 年前

    把这件事归咎于愚蠢。示例中的代码生成类似于以下内容的输出:

    <select>
        <option></option>
        <option>Dr.</option>
        <option>Mr.</option>
        <option>Ms.</option>
        <option>Mrs.</option>
        <option>Miss</option>
    </select>  
    

    相关的MVC验证函数(当将RequiredAttribute应用于对应于下拉列表的属性时)为:

    Sys.Mvc.RequiredValidator._validateSelectInput = function Sys_Mvc_RequiredValidator$_validateSelectInput(optionElements) {
        /// <param name="optionElements" type="DOMElementCollection">
        /// </param>
        /// <returns type="Object"></returns>
        for (var i = 0; i < optionElements.length; i++) {
            var element = optionElements[i];
            if (element.selected) {
                if (!Sys.Mvc._validationUtil.stringIsNullOrEmpty(element.value)) {
                    return true;
                }
            }
        }
        return false;
    }
    

    注意功能检查 element.value . 在上面的HTML中, value 属性为空,因为选项元素上没有值属性。因此,validation函数返回false并发生错误。这似乎只在IE<8中发生,可能是因为默认情况下,其他浏览器会将选项元素的文本分配给value属性(如果未指定)。

    解决方案是修改我返回下拉列表的选择列表项的方式,如下所示:

    public IEnumerable<SelectListItem> GetTitleOptions()
    {
        return BuildSelectListItems(new string[] 
        {
            "","Dr.", "Mr.", "Ms.", "Mrs.", "Miss"
        });
    }
    
    private List<SelectListItem> BuildSelectListItems(IEnumerable<string> values) {
        return (from v in values
                select new SelectListItem()
                {
                    Text = v,
                    Value = v
                }).ToList();
    }
    

    这将导致更可预测的HTML输出:

    <select>
        <option value=""></option>
        <option value="Dr.">Dr.</option>
        <option value="Mr.">Mr.</option>
        <option value="Ms.">Ms.</option>
        <option value="Mrs.">Mrs.</option>
        <option value="Miss">Miss</option>
    </select>
    

    当然,函数可以正确地验证。