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 model
objeto.
Está bien, simplemente serialice su modelo como NameValueCollection
y luego páselo al NameValueCollectionValueProvider
constructor. Bueno, no del todo. Desafortunadamente, no funcionó en mi caso porque mi modelo contiene una colección y NameValueCollectionValueProvider
no funciona bien con las colecciones.
Sin JsonValueProviderFactory
embargo, viene al rescate aquí. Puede ser utilizado por el DefaultModelBinder
siempre 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;
}