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' model
objet.
C'est très bien - sérialisez simplement votre modèle en tant que NameValueCollection
, puis transmettez-le au NameValueCollectionValueProvider
constructeur. Enfin, pas tout à fait. Malheureusement, cela n'a pas fonctionné dans mon cas car mon modèle contient une collection et NameValueCollectionValueProvider
ne joue pas bien avec les collections.
Le JsonValueProviderFactory
vient à la rescousse ici, cependant. Il peut être utilisé par le DefaultModelBinder
tant 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;
}