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

Mik*_*ole 7 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; }
Run Code Online (Sandbox Code Playgroud)

在我看来:

@Html.EditorFor(model => model.Extension)
Run Code Online (Sandbox Code Playgroud)

它呈现:

<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="" />
Run Code Online (Sandbox Code Playgroud)

这应该在我的文本框上设置maxlength属性吗?如果没有,我怎么能用DataAttributes做到这一点?

dju*_*le5 5

本质上基于 Brad 的答案,使用 lambda 语法包装在 Html 帮助器的扩展中,这样你就不会用反射内容污染你的 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样使用它:

@Html.TextBoxFor(x => x.Name, new { maxlength = Html.MaxLength(x => x.Name) })
Run Code Online (Sandbox Code Playgroud)

其中x指的是您的型号。

如果StringLengthAttribute未为属性声明 ,null则将返回,并且maxlength文本框元素上的属性将为空。

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

@using HtmlHelper
Run Code Online (Sandbox Code Playgroud)

您还需要对该方法使用不可为空的结果来克服编译错误。


Ben*_*ale 4

如果可能的话,我希望在 ViewModel 中设置的属性来控制它。

ASP.NET MVC 提供了一个可扩展的系统来完成此任务。这是您需要做的:

  1. 实施自定义ModelMetadataProvider.
  2. 查找 theStringLengthAttribute或 the MaxLengthAttribute,提取信息并将其添加到 中ModelMetadata
  3. 提供利用该信息的自定义编辑器模板。

步骤 1:实施自定义ModelMetadataProvider.

创建一个派生自 的类ModelMetadataProvider。通常您会从 派生,DataAnnotationsModelMetadataProvider因为它提供了一些默认功能,这意味着您只需重写一个名为 的方法CreateMetadata

第二步:提取信息:

要获取该信息,您需要查找该属性,提取最大长度信息并将其添加AdditionalValuesModelMetadata. 实现看起来像这样(这是整个实现):

public class CustomModelMetadataProvider : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes, 
        Type containerType, 
        Func<object> modelAccessor, 
        Type modelType, 
        string propertyName)
    {
        // Call the base class implementation to create the default metadata...
        var metadata = base.CreateMetadata(
            attributes, 
            containerType, 
            modelAccessor, 
            modelType, 
            propertyName);

        // Extract the stringLengthAttribute (you can do the same for the
        // MaxLengthAttribute if you want).
        var attr = attributes
            .OfType<StringLengthAttribute>()
            .First();

        // This could be getting called on a property that doesn't have the
        // attribute so make sure you check for null!
        if (attr != null)
        {
            metadata.AdditionalValues["maxLength"] = attr.MaximumLength;
        }

        return metadata;
    }
}
Run Code Online (Sandbox Code Playgroud)

为了让 ASP.NET MVC 使用它,您需要Application_StartGlobal.asax.

ModelMetadataProviders.Current = new CustomModelMetadataProvider();
Run Code Online (Sandbox Code Playgroud)

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

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

字符串.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)
Run Code Online (Sandbox Code Playgroud)

当您运行应用程序时,您将通过调用获得以下 HTML 输出@Html.EditorFor

<input class="text-box single-line" id="Extension" maxlength="6" name="Extension" type="text" value="" />
Run Code Online (Sandbox Code Playgroud)

如果您想了解有关模型元数据提供程序系统的更多信息,B​​rad Wilson 有一系列博客文章,详细介绍了它的工作原理(这些文章是在 Razor 视图引擎之前编写的,因此某些视图语法有点时髦,但除此之外,信息是声音)。