2011-01-25 106 views
7

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

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



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

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

+0

将复选框添加到该框中,我有一个必选的复选框,在未选中时不会高亮显示为错误字段。 – JBeckton 2011-01-25 23:37:46

+0

不是一个真正的答案,更多的解决方法,但你有没有尝试过使用IValidatableObject接口 - 现在可能会帮助你? – RichardW1001 2011-01-26 00:01:14

+3

我已经在使用IValidatableObject进行服务器端验证。这是客户端问题。我确实在codeplex上找到了这个http://aspnet.codeplex.com/workitem/7629 – JBeckton 2011-01-26 00:26:49

回答

4

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

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

型号:

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助手作为最后一个参数。这将在开始时插入一个选项空值和自定义文本,如果用户不选择一些状态,所需的验证器应该踢入。

8

它看起来像一个合法的错误,这里是我在我的搜索找到了最好的解决办法:

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

总之。您缠绕问题,DropDownListFor的来源,在自定义HTML扩展和手动检索这样不显眼的客户端验证规则:

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

然后您传递到您的自定义帮助其他HTML属性结合您validationAttributes字典你传递一起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)); 
} 
1

这是我找到的最简单的方法,只需在DropDownListForHtmlAttributes的视图内添加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" } }) 

我希望它可以帮助。最好的祝福!

相关问题