【问题标题】:ASP.NET MVC 3 - Data Annoation and Max Length/Size for Textbox RenderingASP.NET MVC 3 - 文本框渲染的数据注释和最大长度/大小
【发布时间】:2011-08-29 14:24:55
【问题描述】:

我知道 Razor View 文件,我们可以做这样的事情 @Html.TextBox("username", null, new { maxlength = 20, autocomplete = "off" })

但是,我希望为 MVC 创建一个模型,该模型可用于创建一个明确定义文本框大小和最大长度的表单。我在模型的属性之上尝试 [StringLength(n)],但这似乎只是进行验证而不是设置文本框的大小。

我们是否可以将文本字段的长度定义为模型属性之上的数据注释?

所以最终,我们可以通过使用 razor 映射到模型来创建整个表单,而不是显式地逐个获取模型属性来设置文本框大小。

【问题讨论】:

    标签: asp.net-mvc-3 data-annotations razor


    【解决方案1】:

    这是使用StringLengthAttribute 的自定义助手的概要。

    public class MyModel
    {
        [StringLength(50)]
        public string Name{get; set;}
    }
    
    public MvcHtmlString MyTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> helper, 
          Expression<Func<TModel, TProperty>> expression)
    {
    
        var attributes = new Dictionary<string, Object>();
        var memberAccessExpression = (MemberExpression)expression.Body;
        var stringLengthAttribs = memberAccessExpression.Member.GetCustomAttributes(
            typeof(System.ComponentModel.DataAnnotations.StringLengthAttribute), true);
    
        if (stringLengthAttribs.Length > 0)
        {
            var length = ((StringLengthAttribute)stringLengthAttribs[0]).MaximumLength;
    
            if (length > 0) 
            {
                 attributes.Add("size", length);
                 attributes.Add("maxlength", length);
            }
        }
    
        return helper.TextBoxFor(expression, attributes);
    }
    

    【讨论】:

    • 看起来很棒!是否有可能在 Html.EditorForModel() 中使用类似于您上面提到的内容?感谢您的帮助。
    • @frostshoxx 您也许可以使用UIHintAttribute 并为每种数据类型制作自定义模板。不过我还没试过。
    【解决方案2】:

    这不行吗?

    public class ViewModel
    {
        [StringLength(20)]
        public string UserName {get;set;}
    }
    

    在视图中:

    @Html.TextBoxFor(x => x.UserName, new {autocomplete = "off"})
    

    或:

    @Html.EditorFor(x => x.UserName)
    

    【讨论】:

    • 您提到的语法是正确的,但我希望只调用 @Html.EditorForModel() 并让它呈现模型中的所有字段,而不是单独显式呈现每个字段。除此之外,我还希望能够将文本字段的大小定义为数据注释标记的一部分。请注意,拥有 [StringLength(20)] 似乎不会将文本字段的大小设置为 20。我希望这能澄清一点。谢谢!
    • @frostshoxx 在模型中指定文本字段大小等表示逻辑违反了 MVC 的核心原则。除非你的意思是 maxlength..
    【解决方案3】:

    我发现我更喜欢我的观点而不是调用 Html.EditorFor(...)。这意味着编辑器和显示模板决定了我的视图中控件的命运,因此我的视图代码被清理了很多 - 它只有 html 和对编辑器的通用请求。

    以下链接提供了一个在编辑器模板中工作的示例 https://jefferytay.wordpress.com/2011/12/20/asp-net-mvc-string-editor-template-which-handles-the-stringlength-attribute/

    我在 String.cshtml 编辑器模板中使用了类似的模板(在 Shared/EditorTemplates 中)。

    @model object
    @using System.ComponentModel.DataAnnotations
    @{
        ModelMetadata meta = ViewData.ModelMetadata;
        Type tModel = meta.ContainerType.GetProperty(meta.PropertyName).PropertyType;
    }
    @if(typeof(string).IsAssignableFrom(tModel)) {
    
        var htmlOptions = new System.Collections.Generic.Dictionary<string, object>();
    
        var stringLengthAttribute = (StringLengthAttributeAdapter)ViewData.ModelMetadata.GetValidators(this.ViewContext.Controller.ControllerContext).Where(v => v is StringLengthAttributeAdapter).FirstOrDefault();
        if (stringLengthAttribute != null && stringLengthAttribute.GetClientValidationRules().First().ValidationParameters["max"] != null)
        {
            int maxLength = (int)stringLengthAttribute.GetClientValidationRules().First().ValidationParameters["max"];
    
            htmlOptions.Add("maxlength", maxLength);
    
            if (maxLength < 20)
            {
                htmlOptions.Add("size", maxLength);
            }
        }
    
        htmlOptions.Add("class", "regular-field");
    
        <text>
             @Html.TextBoxFor(m => m, htmlOptions)
        </text>
    }
    else if(typeof(Enum).IsAssignableFrom(tModel)) {
        //Show a Drop down for an enum using:
        //Enum.GetValues(tModel)
        //This is beyond this article
    }
    //Do other things for other types...
    

    然后我的model被标注如:

    [Display(Name = "Some Field", Description = "Description of Some Field")]
    [StringLength(maximumLength: 40, ErrorMessage = "{0} max length {1}.")]
    public string someField{ get; set; }
    

    而我的 View 只需调用:

    <div class="editor-label">
        @Html.LabelWithTooltipFor(model => model.something.someField)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.something.someField)
        @Html.ValidationMessageFor(model => model.something.someField)
    </div>
    

    您可能还注意到我的 String.cshtml 编辑器模板也可以自动处理 Enum,但这开始偏离当前主题,所以我取消了该代码,我在这里只说字符串编辑器模板可以拉额外的重量,很可能谷歌对此有一些意见https://www.google.com/search?q=string+editor+template+enum

    Label With Tooltip For 是一个自定义 HTML 帮助器,它只是将描述放入标签标题中,以获取有关每个标签的鼠标悬停的更多信息。

    如果您想在编辑器模板中执行此操作,我建议您使用此方法。

    【讨论】:

      猜你喜欢
      • 2017-07-05
      • 1970-01-01
      • 2012-08-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      • 2013-01-24
      相关资源
      最近更新 更多