1

リフレクションとモデルバインダーの検証に関連していると思われる問題に遭遇しました。FormatterParameterBinding.ExecuteBindingAsync(..)特に、メソッドを使用してやりたいことを実行できますが、プロパティを使用できる場合はそれを優先します。

ここでは、モデルバインダーの検証プロセス、必要なことを実行できない理由、問題を修正する方法、または問題を回避する方法についての洞察を探しています。

セットアップ

public class ModelBindingValidationBreaker
{
    public ModelBindingValidationBreaker()
    {
        Properties = new List<string>();
    }

    public int A { get; set; }
    public int B { get; set; }
    public IList<string> Properties { get; set; }

    /*// Uncomment to break the model binder validation!
    public IList<PropertyInfo> PropertyInfos
    {
        get
        {
            return GetType()
                .GetProperties()
                .Where(pi => Properties.Contains(pi.Name))
                .ToList();
        }
    }//*/

    public IList<PropertyInfo> GetPropertyInfos()
    {
        return GetType()
            .GetProperties()
            .Where(pi => Properties.Contains(pi.Name))
            .ToList();
    }

    public IList<int> LetterCounts
    {
        get
        {
            return Properties.Select(p => p.Length).ToList();
        }
    }
}

そして、このように定義されたポストアクションを持つコントローラー

public void Post(ModelBindingValidationBreaker breaker){...}

この種のjsonでそれを呼び出します:

{
    "Properties": [
        "A"
    ],
    "A": 1,
    "B": 2
}

アクションに足を踏み入れると、ブレーカーが正しくインスタンス化されていることがわかり、GetPropertyInfos()問題なく呼び出すことができます。

それがどのように壊れるか

ただし、PropertyInfosプロパティのコメントを解除すると、モデルバインダーの検証が失敗します。これを理解するために、簡単なトレーサーを追加しました。次の関連する出力が表示されます。

System.Web.Http.Action: ApiControllerActionSelector;SelectAction;Selected action 'Post(ModelBindingValidationBreaker breaker)'
System.Web.Http.ModelBinding: HttpActionBinding;ExecuteBindingAsync;
System.Web.Http.ModelBinding: FormatterParameterBinding;ExecuteBindingAsync;Binding parameter 'breaker'
System.Net.Http.Formatting: JsonMediaTypeFormatter;ReadFromStreamAsync;Type='ModelBindingValidationBreaker', content-type='application/json'
System.Net.Http.Formatting: JsonMediaTypeFormatter;ReadFromStreamAsync;Value read='OverPostCount.Models.ModelBindingValidationBreaker'
System.Web.Http.ModelBinding: FormatterParameterBinding;ExecuteBindingAsync;
System.Web.Http.ModelBinding: HttpActionBinding;ExecuteBindingAsync;
System.Web.Http.Controllers: CustomController;ExecuteAsync;
System.Net.Http.Formatting: DefaultContentNegotiator;Negotiate;Type='HttpError', formatters=[JsonMediaTypeFormatterTracer, FormUrlEncodedMediaTypeFormatterTracer, FormUrlEncodedMediaTypeFormatterTracer]

問題のあるget_PropertyInfosを除外すると、代わりにこの行が含まれます。

System.Web.Http.ModelBinding: FormatterParameterBinding;ExecuteBindingAsync;Parameter 'breaker' bound to the value 'OverPostCount.Models.ModelBindingValidationBreaker'

DataContract、およびプロパティのような関連属性を追加[IgnoreDataMember]しても、問題は解決しません。[Bind(Exclude="Properties")]mvc名前空間からもそうではありません。LetterCountモデルバインダーの検証を中断しないため、Linqは問題ではないようです。

私の質問

  1. PropertyInfosゲッターがモデルバインダーバリデーターを壊すのはなぜですか?
  2. これはAsp.NETWebAPIのバグですか?
  3. 属性、カスタムモデルバインダーバリデーター、サービスなどによるこの破損を防ぐ方法はありますか?

基本的に、クラス全体またはコントローラー全体のモデルバインディング検証をオフにしたくありませんが、Propertiesプロパティに対してオフにできれば、それは素晴らしいことです。

4

1 に答える 1

4

原則として、他の複雑なタイプのプロパティを持つPropertyInfosのような複雑なクラスをモデルバインディングに使用されるクラスで使用することは避けてください。ただし、モデルバインディングプロセスに必要なプロパティだけを含む単純なクラスを使用する必要があります。オブジェクトグラフ全体にループが含まれていてはなりません。モデルバインディングプロセスは、さまざまな目的(検証属性など)でプロパティのタイプを分析します。eacプロパティのタイプに含まれるのサブプロパティを再帰的に分析する場合があります...ループやその他の多くを含む複雑な.netクラス.netタイプはそれを壊すかもしれません。プロパティPropertyInfosを内部にするか、メソッドに変換して、モデルバインダーコンポーネントによって処理されないようにしてください。

于 2012-08-08T08:39:28.073 に答える