我创建了自定义 ModelValidatorProvider,它应该仅在站点中的某些特定操作中处于活动状态。为了做到这一点,我创建了一个扩展“FilterAttribute”的自定义属性,并在 OnAuthorize 内部设置了验证器。
在过滤器属性内部 - 为了仅在所需页面中设置验证器,我正在这样做(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 });
}
我面临的问题是有时(我无法准确检测到何时出错 - 但我认为它发生在两次使用尝试访问该站点或触发此操作的页面时)删除之间存在冲突以及我正在做的添加操作,因此 - 我收到一个错误:
指数数组的边界之外。
相关的堆栈跟踪是:
[IndexOutOfRangeException:索引超出了数组的范围。] System.Collections.Generic.Enumerator.MoveNext() +112
System.Linq.d_ 71 2.MoveNext() +578 System.Linq.d1.MoveNext() +643
System.Linq.<SelectManyIterator>d__14
_14 1 clientRules, IDictionary 2 htmlAttributes) +1050 System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper 1 表达式,字符串格式,IDictionary`2 htmlAttributes) +202 ASP._Page_Views_Home_Index_cshtml.Execute() 在 c:\interpub\wwwroot\Views\Home\Index .cshtml:472.MoveNext() +578
System.Web.Mvc.UnobtrusiveValidationAttributesGenerator.GetValidationAttributes(IEnumerable2 results) +440
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, IDictionary1 htmlHelper, Expression
该属性的完整源代码为:
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)
{
// ...
}
}
我做对了吗?我的目标(要明确一点)是仅在修饰的操作中启用验证器提供程序,而在其他操作中它不应该存在于验证器提供程序集合中。
谢谢!