我已经创建了自定义ModelValidatorProvider,它应该仅在网站中的某些特定操作中处于活动状态。 为了做到这一点,我创建了一个自定义属性,它扩展了“FilterAttribute”,并在OnAuthorize中设置了验证器。ModelValidatorProviders基于页面
在filter属性中 - 为了只在需要的页面设置验证器,我这样做(PostAttributeModelValidatorProvider是验证器提供者)。
var provider = (from p in ModelValidatorProviders.Providers
where p is PostAttributeModelValidatorProvider
select p).FirstOrDefault();
if (provider != null)
{
ModelValidatorProviders.Providers.Remove(provider);
}
if (EnableAttributesValidation)
{
ModelValidatorProviders.Providers.Add(new PostAttributeModelValidatorProvider() { BypassRequiredFieldsValidation = this.BypassRequiredFieldsValidation });
}
我面临的问题是,有时(我无法检测到什么时候出了问题 - 但我认为,当两种用途尝试访问的网站或触发这个动作的页面时)还有就是我在做正因为这样的删除和添加操作之间的冲突 - 我得到一个错误:
Index was outside the bounds of the array.
相关的堆栈跟踪是:
[IndexOutOfRangeException: Index was outside the bounds of the array.] System.Collections.Generic.Enumerator.MoveNext() +112
System.Linq.d_711.MoveNext() +643
2.MoveNext() +578
System.Linq.<SelectManyIterator>d__14
System.Linq.d_142.MoveNext() +578
1 clientRules, IDictionary
System.Web.Mvc.UnobtrusiveValidationAttributesGenerator.GetValidationAttributes(IEnumerable2 results) +440
2 htmlAttributes) +1050
System.Web.Mvc.HtmlHelper.GetUnobtrusiveValidationAttributes(String name, ModelMetadata metadata) +280
System.Web.Mvc.Html.InputExtensions.InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, String name, Object value, Boolean useViewData, Boolean isChecked, Boolean setId, Boolean isExplicitValue, String format, IDictionary
System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper1 htmlHelper, Expression
1 expression, String format, IDictionary`2 htmlAttributes) +202 ASP._Page_Views_Home_Index_cshtml.Execute() in c:\interpub\wwwroot\Views\Home\Index.cshtml:47
共该属性mplete源代码是:
public class InitializePostAttributesResolverAttribute : FilterAttribute, IAuthorizationFilter
{
public InitializePostAttributesResolverAttribute()
: this(true, false)
{
}
public InitializePostAttributesResolverAttribute(bool enableAttributesValidation, bool bypassRequiredFieldsValidation)
{
this.EnableAttributesValidation = enableAttributesValidation;
this.BypassRequiredFieldsValidation = bypassRequiredFieldsValidation;
}
/// <summary>
/// Should the attributes input be validated
/// </summary>
public bool EnableAttributesValidation { get; set; }
/// <summary>
/// Gets or sets the value whether we should bypass the required fields validation
/// </summary>
/// <remarks>
/// This value should be set to true only if you would like to skip on required fields validation.
/// We should use this value when searching.
/// </remarks>
public bool BypassRequiredFieldsValidation { get; set; }
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
ModelMetadataProviders.Current = new PostAttributeModelMetadataProvider();
var provider = (from p in ModelValidatorProviders.Providers
where p is PostAttributeModelValidatorProvider
select p).FirstOrDefault();
if (provider != null)
{
ModelValidatorProviders.Providers.Remove(provider);
}
if (EnableAttributesValidation)
{
ModelValidatorProviders.Providers.Add(new PostAttributeModelValidatorProvider() { BypassRequiredFieldsValidation = this.BypassRequiredFieldsValidation });
}
}
}
而且样品使用它
//
// POST: /Post/Publish/5
[InitializePostAttributesResolver]
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Publish(PublishViewModel model)
{
if (ModelState.IsValid)
{
// ...
}
}
难道我这样做对吗?我的目标(只是要明确)是仅在装饰操作中启用验证程序提供程序,而在验证程序提供程序集合中应该不存在其他操作。
谢谢!
没有想到,谢谢! (虽然我仍然需要找出一种方法来添加“BypassRequiredFieldsValidation”属性,该属性在搜索时应该为false,在添加/编辑时为true),但我会考虑一种方式)。 – OzB
如果仅搜索,则可能会根据搜索词从数据库中填充模型,因此不会触发验证。验证仅在您使用(默认)ModelBinder(发布请求,或Controller方法UpdateModel(..)和TryUpdateModel(...))时触发 – Nenad
是的我知道 - 我已经获得由DB创建的自定义属性与“FieldType”等)。验证器提供程序验证属性(必需的,日期等)。在搜索中 - 我仍然需要执行验证(例如“日期不大于X”或“0或更多”),但不希望要求值 - 因为与添加或编辑记录时不同 - 在搜索时,它们应该保持可选状态并处于这种情况下,我不包括他们在搜索。 – OzB