Jawaban uadrive membantu saya, tetapi masih ada beberapa celah. Tanpa data apa pun di input ke new NameValueCollectionValueProvider()
, pengikat model akan mengikat pengontrol ke model kosong, bukan ke model
objek.
Tidak apa-apa - cukup buat model Anda NameValueCollection
menjadi serial, lalu teruskan ke NameValueCollectionValueProvider
konstruktor. Yah, kurang tepat. Sayangnya, ini tidak berfungsi dalam kasus saya karena model saya berisi koleksi, dan tidak berfungsi NameValueCollectionValueProvider
dengan baik dengan koleksi.
Tapi JsonValueProviderFactory
datang untuk menyelamatkannya di sini. Ini dapat digunakan DefaultModelBinder
selama Anda menentukan jenis konten "application/json
"dan meneruskan objek JSON serial Anda ke dalam aliran input permintaan Anda (Harap diperhatikan, karena aliran input ini adalah aliran memori, tidak apa-apa membiarkannya tidak dibuang, sebagai memori aliran tidak berpegang pada sumber daya eksternal):
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;
}