9

这是我的 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 做到这一点?

4

3 回答 3

4

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

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

  1. 实现一个自定义ModelMetadataProvider.
  2. 查找StringLengthAttributeMaxLengthAttribute,提取信息并将其添加到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;
    }
}

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

ModelMetadataProviders.Current = new CustomModelMetadataProvider();

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

您现在需要创建一个使用该信息的视图。StringViews\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)

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

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

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

于 2013-05-10T20:49:39.040 回答
4

基本上基于 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;
    }
}

像这样使用它:

@Html.TextBoxFor(x => x.Name, new { maxlength = Html.MaxLength(x => x.Name) })

其中x是指您的模型。

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

请记住在您的剃须刀页面中包含使用,以便您可以访问该方法。

@using HtmlHelper

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

于 2016-10-13T19:54:13.540 回答
2

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

在 .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>

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

于 2013-11-01T23:42:19.650 回答