0

サイト内の特定のアクションでのみアクティブになるカスタム 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(IEnumerable
2 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, IDictionary

1 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)
        {
            // ...
        }
    }

私は正しくやっていますか?私の目標は(明確にするために)、装飾されたアクションでのみバリデータープロバイダーを有効にすることですが、他のアクションではバリデータープロバイダーコレクションに存在してはなりません。

ありがとう!

4

1 に答える 1