在这种情况下,我列出了我在数据库中定义的大约20个属性(称为属性)。这包括名称,可能的值,可选的正则表达式,表示该字段是必需的布尔值等。
在我的ViewModel中,我得到属性列表,在我的视图中,作为List,我有一个很好的EditorTemplate for AttributeViewModel,使用Steve Sanderson的酷BeginCollectionItem来显示它们,以确保帖子被绑定回AttributeViewModel列表(这很好用)。
我的AttributeViewModel如下所示:
public class AttributeViewModel
{
public string Description { get; set; }
public IEnumerable<SelectListItem> Values { get; set; }
public string SelectedValue { get; set; }
public byte RenderAs { get; set; }
public int AttributeID { get; set; }
public int ID { get; set; }
public int RegexValidation { get; set; }
public bool IsRequired { get; set; }
}
My View看起来像这样(edit.cshtml):
@model Company.Services.ViewModels.StaffMemberViewModel
<h2>Edit</h2>
@using (Html.BeginForm())
{
Some fields here, nothing of interest.
@Html.EditorFor(model => model.AttributeValues)
<input type="submit" value="Send" />
}
这是有趣的一点,这是我对AttributeValues的EditorTemplate:
@using Company.Web.Helpers // This is where "BeginCollectionItem" lives
@model Company.Services.ViewModels.AttributeViewModel
using (Html.BeginCollectionItem("attributes"))
{
<div class="editor-label">
@Model.Description
</div>
<div class="editor-field">
@Html.DropDownListFor(m => m.SelectedValue, new SelectList(Model.Values, "Value", "Text"), "-- Select --")
@Html.HiddenFor(model => model.AttributeID)
</div>
}
我想要做的是使用IsRequired和RegexValidation来确保每个属性的SelectedValue有效。我该怎么做呢?如果可能的话,我真的很想利用MVC3验证框架和不引人注意的验证,就像我“通常”那样。
我显然无法动态添加RequiredAttribute或RegularExpressionAttribute,因为这些对于列表中的每个属性对象都不同。
答案 0 :(得分:1)
考虑使用FluentValidation.Net(可通过以下Install-Package FluentValidation.MVC3
中的NuGet获得)。它使任何类型的相对复杂的数据验证比声明式样式更简单,更直观。也支持客户端验证。
答案 1 :(得分:1)
这是未经测试的。你可能不得不玩这个来获得你想要的结果。
首先,创建自定义DataAnnotationsModelValidatorProvider
类:
public class MyModelMetadataValidatorProvider : DataAnnotationsModelValidatorProvider
{
internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = Create;
internal static Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories =
new Dictionary<Type, DataAnnotationsModelValidationFactory>()
{
{
typeof(RequiredAttribute),
(metadata, context, attribute) => new RequiredAttributeAdapter(metadata, context, (RequiredAttribute)attribute)
},
{
typeof(RegularExpressionAttribute),
(metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute)
}
};
internal static ModelValidator Create(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute)
{
return new DataAnnotationsModelValidator(metadata, context, attribute);
}
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
List<ModelValidator> vals = base.GetValidators(metadata, context, attributes).ToList();
if (metadata.ModelType.Name == "SelectedValue")
{
// get our parent model
var parentMetaData = ModelMetadataProviders.Current.GetMetadataForProperties(context.Controller.ViewData.Model,
metadata.ContainerType);
// get the associated AttributeId
var attributeId = Convert.ToInt32(parentMetaData.FirstOrDefault(p => p.PropertyName == "AttributeId").Model);
// get AttributeViewModel with specified AttributeId from repository
var attributeViewModel = _db.AttributeViewModels.FirstOrDefault(x => x.AttributeId == attributeId);
DataAnnotationsModelValidationFactory factory;
// check if required
if (attributeViewModel.IsRequired)
{
// must be marked as required
var required = new RequiredAttribute();
required.ErrorMessage = attributeViewModel.Description.Trim() +
" is Required";
if (!AttributeFactories.TryGetValue(required.GetType(), out factory))
factory = DefaultAttributeFactory;
vals.Add(factory(metadata, context, required));
}
// check for regex
if (attributeViewModel.RegexValidation > 0)
{
// get regex from repository
var regexValidation = _db.attributeViewModels.
FirstOrDefault(x => x.RegexValidation == attributeViewModel.RegexValidation);
var regex = new RegularExpressionAttribute(regexValidation.Pattern);
regex.ErrorMessage = attributeViewModel.Description.Trim() +
" is not in a valid format";
if (!AttributeFactories.TryGetValue(regex.GetType(), out factory))
factory = DefaultAttributeFactory;
vals.Add(factory(metadata, context, regex));
}
}
return vals.AsEnumerable();
}
}
然后,将以下内容添加到Global.asax.cs中的Application_Start
:
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new MyModelMetadataValidatorProvider());
答案 2 :(得分:0)
我希望我能正确理解你的问题。您想为视图添加自定义验证属性,注释和验证逻辑吗?
如果是这样,您想要转到System.ComponentModel.DataAnnotation
命名空间。您的验证逻辑将放在源自ValidationAttribute
:
using System.ComponentModel.DataAnnotation;
public class MyValidationAttribute : ValidationAttribute
{
string readonly _validationParameter;
public MyValidationAttribute(string validationParameter)
{
_validationParameter = validationParameter;
}
protected override ValidationResult IsValid(object value,
ValidationContext validationContext)
{
// add validation logic here
if (//not valid)
{
var errorMessage = FormatErrorMessage(validationContext.DisplayName);
return new ValidationResult(errorMessage);
}
return ValidationResult.Success;
}
}
您可以将该属性应用于任何模型属性
[Required]
[MyValidationAttribute("parameter", ErrorMessage="Error in {0}")]
public string MyProperty { get; set; }
我希望这会有所帮助。见
第127页了解更多信息。