Odpowiedź uadrive zajęła mi część drogi, ale nadal były pewne luki. Bez żadnych danych wejściowych do new NameValueCollectionValueProvider()
, spinacz modelu powiąże kontroler z pustym modelem, a nie z model
obiektem.
W porządku - po prostu serializuj swój model jako a NameValueCollection
, a następnie przekaż go do NameValueCollectionValueProvider
konstruktora. Cóż, niezupełnie. Niestety w moim przypadku to nie zadziałało, ponieważ mój model zawiera kolekcję i NameValueCollectionValueProvider
nie bawi się ładnie z kolekcjami.
Tutaj jednak JsonValueProviderFactory
przychodzi z pomocą. Może być używany przez, o DefaultModelBinder
ile określisz typ zawartości "application/json
„i przekażesz zserializowany obiekt JSON do strumienia wejściowego żądania (Uwaga, ponieważ ten strumień wejściowy jest strumieniem pamięci, można go pozostawić niewykorzystany jako pamięć stream nie zatrzymuje żadnych zasobów zewnętrznych):
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;
}