Ответ uadrive взял меня на часть пути, но все еще были некоторые пробелы. Без каких-либо данных во входных данных new NameValueCollectionValueProvider()
связыватель модели привяжет контроллер к пустой модели, а не к model
объекту.
Это нормально - просто сериализуйте свою модель как объект NameValueCollection
, а затем передайте его в NameValueCollectionValueProvider
конструктор. Не совсем так. К сожалению, в моем случае это не сработало, потому что моя модель содержит коллекцию, а NameValueCollectionValueProvider
она плохо работает с коллекциями.
Однако JsonValueProviderFactory
здесь на помощь приходит. Его можно использовать до тех DefaultModelBinder
пор, пока вы укажете тип содержимого "application/json
"и передадите свой сериализованный объект JSON во входной поток вашего запроса (обратите внимание, поскольку этот входной поток является потоком памяти, можно оставить его нераспределенным, как память stream не привязан ни к каким внешним ресурсам):
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;
}