为了使用Regex进行验证,我通常这样做:
// In my ViewModel
[RegularExpression("MyRegex", ErrorMessageResourceName = "MyErrorMessage")]
public string MyField { get; set; }
和HTML助手
@Html.TextBoxFor(model => model.MyField)
生成如下所示的标记:
<input type="text" class="valid" name="MyField" value="" id="MyField" data-val="true" data-val-regex-pattern="MyRegex" data-val-regex="MyErrorMessage"></input>
问题是,我希望有一个动态的字段数,现在正在使用
// In my ViewModel
[RegularExpression("MyRegex", ErrorMessageResourceName = "MyErrorMessage")]
public IList<string> MyField { get; set; }
这一次
@Html.TextBoxFor(model => model.MyField[0])
将生成(没有regex属性)
<input id="MyField_0_" type="text" value="" name="MyField[0]"></input>
如何确保在绑定在我的data-val
中具有DataAnnotation验证属性的列表的元素时创建ViewModel html属性?
发布于 2014-05-02 21:42:28
您正在使用DataAnnotations进行验证。据我所知,您正在寻找一种将DataAnnotation验证应用于列表中每个元素的方法。
每当调用Html.EditorFor时,它都会获取传递给它的模型的ModelMetadata,然后获取与该模型关联的任何ModelValidators。正是这些ModelValidators的存在导致了‘dat-val-*’属性在HTML中的出现。
当Html.EditorFor作为模型(或任何可枚举的模型)传递列表时,它首先获取属性的ModelMetadata和相关验证器--在您的示例中,它将获取与'MyField‘属性关联的ModelMetadata,在本例中将获取与验证器- 'RegularExpression’相关联的验证器。接下来,它遍历字符串列表,并获取每个字符串的ModelMetadata和验证器。虽然已经为每个字符串构造了ModelMetadata,但是没有为这些字符串指定任何验证器。这就是显示字符串的原因,但验证属性没有添加到HTML元素中。
在我看来,可以通过在运行时将在“MyField”属性上指定的Validator添加到所有list元素中来实现您想要的结果。
这可以通过
下面给出了step1的共享编辑器模板
@model System.Collections.Generic.IEnumerable<object>
@{
ViewBag.Title = "Collection";
var modelMetadata = this.ViewData.ModelMetadata;
var validators = modelMetadata.GetValidators(ViewContext).ToList();
ViewContext.HttpContext.Items["rootValidators"] = validators;
}
@foreach (var item in Model)
{
@Html.EditorFor(m => item)
}
您可以在上面的代码中看到,我们正在获取列表中指定的所有验证器。这些验证器稍后将添加到列表的元素中。它们已经存储在HttpContext.Items中,以便在我们的自定义ModelValidatorProvider中使用。
步骤2-在Global.asax中,输入以下代码-
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new DAModelValidatorProvider());
ModelMetadataProviders.Current = new CachedDataAnnotationsModelMetadataProvider();
步骤3-通过重写ModelValidatorProvider方法编写自己的GetValidators,如下面的代码所示
public class DAModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
var validators = base.GetValidators(metadata, context, attributes).ToList();
// get root validators of the collection. this was stored in the editor template - fetching it for use now.
// fetching the rootvalidators inside this method is a bad idea because we have to call GetValidators method on the
// containers ModelMetadata and it will result in a non-terminal recursion
var rootValidators = context.HttpContext.Items["rootValidators"] as IEnumerable<ModelValidator>;
if (rootValidators != null)
{
foreach (var rootValidator in rootValidators)
{
validators.Add(rootValidator);
}
}
return validators;
}
}
执行上述三个步骤对我来说是有效的。但是,我使用的是Html.EditorFor而不是Html.TextBoxFor。使用Html.EditorFor时,我没有给出正确的id和name属性--我认为这在事物方案中是一个微不足道的问题。我已经为此创建了一个解决方案,并将其上传到https://github.com/swazza85/Stackoverflow上,这样您就可以试一试,看看它是否适合您的需要。我在这里所做的并不是一个完全的解决方案,但希望它能让你不必改变你的模型。
干杯,斯沃拉普。
https://stackoverflow.com/questions/23337170
复制相似问题