A resposta do uadrive me atrapalhou, mas ainda havia algumas lacunas. Sem nenhum dado na entrada para new NameValueCollectionValueProvider()
, o fichário do modelo vinculará o controlador a um modelo vazio, não ao model
objeto.
Tudo bem - basta serializar seu modelo como um NameValueCollection
e, em seguida, passá-lo para o NameValueCollectionValueProvider
construtor. Bem, não exatamente. Infelizmente, não funcionou no meu caso porque meu modelo contém uma coleção, e NameValueCollectionValueProvider
não combina bem com coleções.
O JsonValueProviderFactory
vem ao resgate aqui, no entanto. Ele pode ser usado pelo DefaultModelBinder
, contanto que você especifique um tipo de conteúdo de "application/json
"e passe seu objeto JSON serializado para o fluxo de entrada de sua solicitação (observe, porque esse fluxo de entrada é um fluxo de memória, não há problema em deixá-lo sem disposição, como uma memória stream não mantém nenhum 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;
}