Razor ViewModel中的StringLength未在文本框上设置maxlength

Razor ViewModel中的StringLength未在文本框上设置maxlength,razor,asp.net-mvc-4,Razor,Asp.net Mvc 4,此处显示我的ViewModel中的属性: [Display(Name = "Ext.")] [MaxLength(6, ErrorMessage = "Must be a maximum of 6 characters")] [StringLength(6)] public string Extension { get; set; } 在我看来: @Html.EditorFor(model => model.Extension) 它表明: <input class="text-b

此处显示我的ViewModel中的属性:

[Display(Name = "Ext.")]
[MaxLength(6, ErrorMessage = "Must be a maximum of 6 characters")]
[StringLength(6)]
public string Extension { get; set; }
在我看来:

@Html.EditorFor(model => model.Extension)
它表明:

<input class="text-box single-line" data-val="true" data-val-length="The field Ext. must be a string with a maximum length of 6." data-val-length-max="6" id="Extension" name="Extension" type="text" value="" />

这是否应该在我的文本框上设置maxlength属性?如果没有,我如何使用DataAttributes实现这一点

我希望我在ViewModel中设置的属性能够控制这一点 可能

NET MVC提供了一个可扩展的系统来实现这一点。以下是您需要做的:

  • 实现自定义的
    modelmataprovider
  • 查找
    StringLengthAttribute
    MaxLengthAttribute
    ,提取信息并将其添加到
    ModelMetadata
  • 提供一个使用这些信息的自定义编辑器模板
  • 步骤1:实现自定义
    modelmataprovider

    创建从
    modelmataprovider
    派生的类。通常,您可以从
    DataAnnotationsModelMetadataProvider
    派生,因为这提供了一些默认功能,这意味着您只需重写名为
    CreateMatadata
    的单个方法

    步骤2:提取信息:

    要获取信息,您需要查找属性,提取最大长度信息并将其添加到
    ModelMetadata
    AdditionalValues
    字典中。实现类似于以下内容(这是整个实现):

    步骤3:创建自定义编辑器模板

    现在需要创建一个使用这些信息的视图。在
    Views\Shared\
    文件夹中创建名为
    String
    的新视图

    String.cshtml

    @{
        object maxLength;
        if (!ViewData.ModelMetadata.AdditionalValues
                .TryGetValue("maxLength", out maxLength))
        {
            maxLength = 0;
        }
    
        var attributes = new RouteValueDictionary
        {
            {"class", "text-box single-line"},
            { "maxlength", (int)maxLength },
        };
    }
    
    @Html.TextBox("", ViewContext.ViewData.TemplateInfo.FormattedModelValue, attributes)
    
    运行应用程序时,通过调用
    @HTML.EditorFor
    ,您将获得以下HTML输出

    <input class="text-box single-line" id="Extension" maxlength="6" name="Extension" type="text" value="" />
    
    
    

    如果您想了解更多关于模型元数据提供程序系统的信息,请详细说明它的工作原理(这些是在Razor视图引擎之前编写的,因此一些视图语法有点古怪,但其他方面的信息是可靠的)。

    我遇到了类似的情况,下面是我快速而肮脏的解决方案:

    在.cshtml文件的顶部添加以下行:

    @{
    var max = ((System.ComponentModel.DataAnnotations.StringLengthAttribute)(typeof(MyType))
    .GetProperty("MyProp")
    .GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.StringLengthAttribute), true)[0]).MaximumLength;    
    }
    
    在html的下面,将EditorFor替换为:

    @Html.TextBoxFor(model => model.Extension, htmlAttributes: new {maxlength=max })
    
    我最终决定我还是用剧本来写:

    <script>
        $(function ()
        {
            var max = $("#myinput").attr("data-val-length-max");
            $("#myinput").attr("maxlength", max);
        });
    </script>
    
    
    $(函数()
    {
    var max=$(“#myinput”).attr(“数据值长度max”);
    $(“#myinput”).attr(“maxlength”,max);
    });
    

    但是,如果您不想添加脚本,第一个示例应该可以使用。

    基本上基于Brad的答案,在Html帮助程序上使用lambda语法包装了一个扩展,这样您就不会用反射内容污染Razor视图:

    using System;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Web.Mvc;
    
    public static class HtmlHelper
    {
        public static int? MaxLength<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression)
        {
            MemberExpression memberExpression = (MemberExpression)expression.Body;
    
            PropertyInfo property = typeof(TModel)
                .GetProperty(memberExpression.Member.Name);
    
            StringLengthAttribute attribute = (StringLengthAttribute)property
                .GetCustomAttributes(typeof(StringLengthAttribute), true)
                .FirstOrDefault();
    
            if (attribute != null)
            {
                return attribute.MaximumLength;
            }
    
            return null;
        }
    }
    
    其中
    x
    指的是您的型号

    如果未为属性声明
    StringLengthAttribute
    ,将返回
    null
    ,并且textbox元素的
    maxlength
    属性将为空

    请记住在razor页面中包含using,以便访问该方法

    @using HtmlHelper
    

    您还需要为该方法使用不允许为null的结果来克服编译错误。

    您是否验证了是否可以发布长度超过6个字符的字符串?我确实收到一个验证错误,但我希望它实际设置maxlength属性。如果您将其更改为
    TextBoxFor
    您可以传递HTML选项。是,但是如果可能的话,我希望我在ViewModel中设置的属性能够控制这一点。如果您使用
    非干扰性验证
    ,这可能会有帮助。Benjamin,您现在是一台机器!没问题,很高兴我能帮上忙。这段代码很有效,但您可能希望使用助手之类的工具保持Razor视图更清晰。请参见我的答案,以了解这方面的示例。
    using System;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;
    using System.Web.Mvc;
    
    public static class HtmlHelper
    {
        public static int? MaxLength<TModel, TProperty>(
            this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression)
        {
            MemberExpression memberExpression = (MemberExpression)expression.Body;
    
            PropertyInfo property = typeof(TModel)
                .GetProperty(memberExpression.Member.Name);
    
            StringLengthAttribute attribute = (StringLengthAttribute)property
                .GetCustomAttributes(typeof(StringLengthAttribute), true)
                .FirstOrDefault();
    
            if (attribute != null)
            {
                return attribute.MaximumLength;
            }
    
            return null;
        }
    }
    
    @Html.TextBoxFor(x => x.Name, new { maxlength = Html.MaxLength(x => x.Name) })
    
    @using HtmlHelper