这是我的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做到这一点?
答案 0 :(得分:4)
我想在ViewModel中设置的属性来控制它 可能的。
ASP.NET MVC提供了一个可扩展的系统来完成这个任务。以下是您需要做的事情:
ModelMetadataProvider
。StringLengthAttribute
或MaxLengthAttribute
,提取信息并将其添加到ModelMetadata
。 第1步:实施自定义ModelMetadataProvider
。
创建一个派生自ModelMetadataProvider
的类。通常,您将从DataAnnotationsModelMetadataProvider
派生,因为这提供了一些默认功能,这意味着您只需要覆盖名为CreateMetadata
的单个方法。
第2步:提取信息:
要获取信息,您需要查找属性,提取最大长度信息并将其添加到AdditionalValues
的{{1}}字典中。实现看起来像这样(这是整个实现):
ModelMetadata
为了让ASP.NET MVC使用它,您需要在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;
}
}
中的Application_Start
方法中注册它。
Global.asax
第3步:创建自定义编辑器模板。
您现在需要创建一个使用该信息的视图。在ModelMetadataProviders.Current = new CustomModelMetadataProvider();
文件夹中创建名为String
的新视图。
<强> String.cshtml 强>
Views\Shared\
运行应用程序时,您将通过调用@{
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
如果您想了解更多有关模型元数据提供程序系统的信息,Brad Wilson has a series of blog posts详细说明它是如何工作的(这些是在Razor视图引擎之前编写的,因此某些视图语法有点时髦但其他方面的信息是健全的。)
答案 1 :(得分: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
您还需要使用none null-able结果来克服编译错误。
答案 2 :(得分: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>
但如果您不想添加脚本,则第一个示例应该有效。