La réponse d'uadrive m'a pris une partie du chemin, mais il y avait encore des lacunes. Sans aucune donnée dans l'entrée de new NameValueCollectionValueProvider(), le classeur de modèles liera le contrôleur à un modèle vide, pas à l' modelobjet.
C'est très bien - sérialisez simplement votre modèle en tant que NameValueCollection, puis transmettez-le au NameValueCollectionValueProviderconstructeur. Enfin, pas tout à fait. Malheureusement, cela n'a pas fonctionné dans mon cas car mon modèle contient une collection et NameValueCollectionValueProviderne joue pas bien avec les collections.
Le JsonValueProviderFactoryvient à la rescousse ici, cependant. Il peut être utilisé par le DefaultModelBindertant que vous spécifiez un type de contenu de "application/json"et que vous transmettez votre objet JSON sérialisé dans le flux d'entrée de votre requête (veuillez noter que ce flux d'entrée est un flux de mémoire, vous pouvez le laisser non disposé, en tant que mémoire stream ne conserve aucune ressource externe):
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;
}