La risposta di uadrive mi ha portato in parte, ma c'erano ancora delle lacune. Senza alcun dato nell'input a new NameValueCollectionValueProvider()
, il raccoglitore del modello legherà il controller a un modello vuoto, non model
all'oggetto.
Va bene: serializza il tuo modello come a NameValueCollection
, quindi passalo al NameValueCollectionValueProvider
costruttore. Beh, non proprio. Sfortunatamente, nel mio caso non ha funzionato perché il mio modello contiene una raccolta e NameValueCollectionValueProvider
non funziona bene con le raccolte.
Ma qui JsonValueProviderFactory
viene in soccorso. Puòessere usato DefaultModelBinder
finché specifichi un tipo di contenuto "application/json
"e passi il tuo oggetto JSON serializzato nel flusso di input della tua richiesta (Nota, poiché questo flusso di inputèun flusso di memoria, va bene lasciarlo non disponibile, come memoria stream non mantiene alcuna risorsa esterna):
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;
}