uadriveの答えは私に道を譲りましたが、それでもいくつかのギャップがありました。への入力にデータがない場合new NameValueCollectionValueProvider()
、モデルバインダーはコントローラーをmodel
オブジェクトではなく空のモデルにバインドします。
それは問題ありません。モデルをとしてシリアルNameValueCollection
化し、それをNameValueCollectionValueProvider
コンストラクタに渡します。まあ、そうではありません。残念ながら、私の場合、モデルにはコレクションが含まれており、コレクションはNameValueCollectionValueProvider
うまく機能しません。
しかしJsonValueProviderFactory
、これが救いに来ます。DefaultModelBinder
コンテンツタイプ"application/json
" を指定し、シリアル化されたJSONオブジェクトをリクエストの入力ストリームに渡す限り、で使用できます(この入力ストリームはメモリストリームであるため、メモリとして破棄しないでおいても構いません)ストリームは外部リソースを保持しません):
protected void BindModel<TModel>(Controller controller, TModel viewModel)
{
var controllerContext = SetUpControllerContext(controller, viewModel);
var bindingContext = new ModelBindingContext
{
ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => viewModel, typeof(TModel)),
ValueProvider = new JsonValueProviderFactory().GetValueProvider(controllerContext)
};
new DefaultModelBinder().BindModel(controller.ControllerContext, bindingContext);
controller.ModelState.Clear();
controller.ModelState.Merge(bindingContext.ModelState);
}
private static ControllerContext SetUpControllerContext<TModel>(Controller controller, TModel viewModel)
{
var controllerContext = A.Fake<ControllerContext>();
controller.ControllerContext = controllerContext;
var json = new JavaScriptSerializer().Serialize(viewModel);
A.CallTo(() => controllerContext.Controller).Returns(controller);
A.CallTo(() => controllerContext.HttpContext.Request.InputStream).Returns(new MemoryStream(Encoding.UTF8.GetBytes(json)));
A.CallTo(() => controllerContext.HttpContext.Request.ContentType).Returns("application/json");
return controllerContext;
}