サイト内の特定のアクションでのみアクティブになるカスタム 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 });
}
私が直面している問題は、時々 (いつ問題が発生したかを正確に検出できませんでしたが、このアクションをトリガーするサイトまたはページに 2 つのユーザーがアクセスしようとしたときに発生すると考えています)、削除の間に競合が発生することです。私が行っている追加操作とそのため、エラーが発生しています:
インデックスが配列の範囲外だった。
関連するスタック トレースは次のとおりです。
[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() in 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)
{
// ...
}
}
私は正しくやっていますか?私の目標は(明確にするために)、装飾されたアクションでのみバリデータープロバイダーを有効にすることですが、他のアクションではバリデータープロバイダーコレクションに存在してはなりません。
ありがとう!