【问题标题】:ASP.Net MVC 3 unobtrusive client validation does not work with drop down listsASP.Net MVC 3 不显眼的客户端验证不适用于下拉列表
【发布时间】:2011-01-25 23:20:43
【问题描述】:

我有一个简单的下拉列表,列表中的第一项有一个空值。如果我没有在列表中选择任何内容,客户端验证将忽略它。我使用注释属性在模型上根据需要设置了该字段。

 @Html.DropDownListFor(model => Model.CCPayment.State, UnitedStatesStates.StateSelectList)



[Required(ErrorMessage = "State is Required.")]
    public string State
    {
        get
        {
            return _state;
        }
        set
        {
            _state = value;
        }
    }

有什么想法吗?我错过了什么吗?

【问题讨论】:

  • 也添加复选框,我有一个必填复选框,在未选中时未作为错误字段高亮显示。
  • 不是真正的答案,更多的是一种解决方法,但您是否尝试过使用 IValidatableObject 接口 - 现在可能对您有所帮助?
  • 我已经在使用 IValidatableObject 进行服务器端验证。这是一个客户端问题。我确实在 codeplex 找到了一个针对此 aspnet.codeplex.com/workitem/7629 的未解决问题
  • 看来问题出在属性路径的大小上。如果我这样做 model => model.State 它验证正常。但是model => model.Address.State 没有。你有没有想出任何解决方法?
  • 请注意,在 MVC 5 中,此错误已被修复。

标签: jquery validation asp.net-mvc-3 drop-down-menu unobtrusive-validation


【解决方案1】:

它看起来像一个合法的错误,这是我在搜索中找到的最佳解决方法:

http://forums.asp.net/t/1649193.aspx

简而言之。您将问题的根源 DropDownListFor 包装在自定义 Html 扩展中,然后手动检索不显眼的客户端验证规则,如下所示:

IDictionary<string, object> validationAttributes = htmlHelper.
    GetUnobtrusiveValidationAttributes(
        ExpressionHelper.GetExpressionText(expression),
        metadata
    );

然后,您将您的 validationAttributes 字典与传递给您的自定义帮助程序的任何其他 html 属性结合起来,然后将其传递给 DropDownListFor

我正在使用的完整代码(我也有一个标签,你可以随意解耦):

public static IHtmlString DropDownListWithLabelFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string label, IEnumerable<SelectListItem> items, string blankOption, object htmlAttributes = null)
{
    var l = new TagBuilder("label");
    var br = new TagBuilder("br");

    var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
    var mergedAttributes = helper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata);

    if (htmlAttributes != null)
    {
        foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(htmlAttributes))
        {
            object value = descriptor.GetValue(htmlAttributes);
            mergedAttributes.Add(descriptor.Name, value);
        }
    }

    l.InnerHtml = label + br.ToString(TagRenderMode.SelfClosing) + helper.DropDownListFor(expression, items, blankOption, mergedAttributes);
    return MvcHtmlString.Create(l.ToString(TagRenderMode.Normal));
}

【讨论】:

  • 说真的,这绝对是答案!!!为这个工作了三天!我永远不会想到这一点。惊人的!!!谢谢@Milimetric
  • 这救了我几个小时无处可去!!!!它应该被标记为答案!
  • 谢谢尼克 :) 这是一个已经发生太久的严重错误。 18 个月!
【解决方案2】:

您提供的信息太少,我们无法查明问题所在。您可能忘记在视图中包含适当的不显眼的验证脚本,但谁知道呢?你还没有展示你的观点。

这是一个完整的工作示例:

型号:

public class MyViewModel
{
    [Required(ErrorMessage = "State is Required.")]
    public string State { get; set; }

    public IEnumerable<SelectListItem> States 
    { 
        get
        {
            return Enumerable.Range(1, 5).Select(x => new SelectListItem
            {
                Value = x.ToString(),
                Text = "state " + x
            });
        }
    }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new MyViewModel());
    }

    [HttpPost]
    public ActionResult Index(MyViewModel model)
    {
        return View(model);
    }
}

查看:

@model AppName.Models.MyViewModel
@{
    ViewBag.Title = "Home Page";
}
<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

@using (Html.BeginForm())
{
    @Html.LabelFor(x => x.State)
    @Html.DropDownListFor(
        x => x.State, 
        new SelectList(Model.States, "Value", "Text"), 
        "-- Please select a state --"
    )
    @Html.ValidationMessageFor(x => x.State)
    <input type="submit" value="OK" />
}

请注意我们如何在 DropDownListFor 帮助程序中提供默认值作为最后一个参数。这将在开头插入一个带有空值和自定义文本的选项,如果用户没有选择某些状态,则需要的验证器应该启动。

【讨论】:

  • 它应该启动但它没有,我尝试添加默认值但我遇到了同样的问题。我可以让它工作的唯一方法是将“必需”添加到 html 类属性。问题是它只提供一般错误消息,而不是我在模型验证属性中指定的错误消息。
  • 对我来说也被破坏了。如果我排除 jq.validate.js 而只包含 jq.validate.unobtrusive.js,它会起作用,这很奇怪。
【解决方案3】:

我将 @class="required" 添加到属性中,就像有人在 codeplex http://aspnet.codeplex.com/workitem/7629 的线程上所说的那样,它对我来说效果很好 =)

【讨论】:

  • 是的,这是一种解决方法,但您会收到通用错误消息,而不是验证属性中定义的自定义错误消息。
【解决方案4】:

这是我发现的最简单的方法,只需在视图内的HtmlAttributesDropDownListFor 中添加data-val-*-* 属性。以下方法也适用于 RemoteValidation,如果您不需要远程验证,只需删除包含 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" } })

我希望它会有所帮助。最好的问候!

【讨论】:

    【解决方案5】:

    如果问题是当您选择“空白”选项时,您没有看到说明该字段为必填项的验证消息,这可能是因为 Html 助手如何为“空白”选项生成选项标签。问题是空值属性。

    <select ...>
      <option value="">
      ...
    </select>
    

    我使用这种单行解决方法来删除 value 属性,它就像一个魅力!

    $('option[value=""]').removeAttr("value");

    所有这一切都是从任何具有空白值属性的“选项”元素中删除值属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-06
      相关资源
      最近更新 更多