コンテンツタイプをJSONに設定してAJAX経由で投稿する場合、MVC3はコントローラーアクションで適切にバインドできます。
$.ajax({
url: location.href,
type: "POST",
data: ko.toJSON(viewModel),
datatype: "json",
contentType: "application/json charset=utf-8",
success: function (data) { alert("success"); },
error: function (data) { alert("error"); }
});
ただし、例のように、JSONを含む通常のフォーム投稿を行う場合は、コンテンツタイプがapplication / x-になるため、MVC3がモデルに自動的にバインドしないため、さらに作業を行う必要があります。 www-form-urlencoded。
Steve Sandersonには、送信されたJSONデータをコントローラーアクションで適切にバインドする方法を示す古いサンプルがあります:http://blog.stevensanderson.com/2010/07/12/editing-a-variable-length-list-knockout-スタイル/
その要点は、彼が次のような「FromJson」という属性を作成することです。
public class FromJsonAttribute : CustomModelBinderAttribute
{
private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();
public override IModelBinder GetBinder()
{
return new JsonModelBinder();
}
private class JsonModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
if (string.IsNullOrEmpty(stringified))
return null;
return serializer.Deserialize(stringified, bindingContext.ModelType);
}
}
}
次に、アクションは次のようになります。
[HttpPost]
public ActionResult Index([FromJson] IEnumerable<GiftModel> gifts)
また、属性を使用したくない場合は、実際にタイプを登録して、常に特定のモデルバインダーを使用することができます。
次のようなモデルバインダーを作成できます。
public class JsonModelBinder: IModelBinder
{
private readonly static JavaScriptSerializer serializer = new JavaScriptSerializer();
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var stringified = controllerContext.HttpContext.Request[bindingContext.ModelName];
if (string.IsNullOrEmpty(stringified))
return null;
return serializer.Deserialize(stringified, bindingContext.ModelType);
}
}
次に、次のようにglobal.asax.csに登録します。
ModelBinders.Binders.Add(typeof(DocumentModel), new JsonModelBinder());
これで、属性を使用する必要がなくなり、DocumentModelが適切にバインドされます。これは、常にJSON経由でDocumentModelを送信することを意味します。