リフレクションとモデルバインダーの検証に関連していると思われる問題に遭遇しました。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は問題ではないようです。
私の質問
- PropertyInfosゲッターがモデルバインダーバリデーターを壊すのはなぜですか?
- これはAsp.NETWebAPIのバグですか?
- 属性、カスタムモデルバインダーバリデーター、サービスなどによるこの破損を防ぐ方法はありますか?
基本的に、クラス全体またはコントローラー全体のモデルバインディング検証をオフにしたくありませんが、Propertiesプロパティに対してオフにできれば、それは素晴らしいことです。