La respuesta de uadrive me llevó parte del camino, pero aún quedaban algunas lagunas. Sin ningún dato en la entrada new NameValueCollectionValueProvider(), la carpeta de modelos vinculará el controlador a un modelo vacío, no al modelobjeto.
Está bien, simplemente serialice su modelo como NameValueCollectiony luego páselo al NameValueCollectionValueProviderconstructor. Bueno, no del todo. Desafortunadamente, no funcionó en mi caso porque mi modelo contiene una colección y NameValueCollectionValueProviderno funciona bien con las colecciones.
Sin JsonValueProviderFactoryembargo, viene al rescate aquí. Puede ser utilizado por el DefaultModelBindersiempre que especifique un tipo de contenido de "application/json"y pase su objeto JSON serializado al flujo de entrada de su solicitud (tenga en cuenta que, debido a que este flujo de entrada es un flujo de memoria, está bien dejarlo sin eliminar, como una memoria stream no se aferra a ningún recurso externo):
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;
}