ASP.NET MVC4 Web API アプリケーションは、顧客を保存するための post メソッドを定義します。顧客は、POST 要求本文で json 形式で渡されます。post メソッドの顧客パラメーターには、プロパティの null 値が含まれます。
投稿されたデータが顧客オブジェクトとして渡されるようにこれを修正するにはどうすればよいですか?
可能であれば、Content-Type: application/x-www-form-urlencoded を使用する必要があります。フォームを投稿する JavaScript メソッドでこれを変更する方法がわからないためです。
コントローラ:
public class CustomersController : ApiController {
public object Post([FromBody] Customer customer)
{
return Request.CreateResponse(HttpStatusCode.OK,
new
{
customer = customer
});
}
}
}
public class Customer
{
public string company_name { get; set; }
public string contact_name { get; set; }
}
リクエスト:
POST http://localhost:52216/api/customers HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
{"contact_name":"sdfsd","company_name":"ssssd"}
ベストアンサー1
編集: 2017/10/31
同じコード/アプローチはAsp.Net Core 2.0IActionResult
でも機能します。主な違いは、asp.net core では、Web API コントローラーと MVC コントローラーの両方が単一のコントローラー モデルに統合されていることです。したがって、戻り値の型は、またはその実装の 1 つである可能性があります(例: OkObjectResult
)
使用
contentType:"application/json"
JSON.stringify
送信時にJSON文字列に変換するメソッドを使用する必要があります。
そして、モデル バインダーは JSON データをクラス オブジェクトにバインドします。
以下のコードは問題なく動作します(テスト済み)
$(function () {
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
});
});
結果
contentType
プロパティは、データを JSON 形式で送信していることをサーバーに伝えます。JSON データ構造を送信したので、モデル バインディングが適切に行われます。
Content-Type
ajax リクエストのヘッダーを調べると、値が として設定されていることがわかりますapplication/json
。
contentTypeを明示的に指定しない場合は、デフォルトのコンテンツタイプが使用されます。application/x-www-form-urlencoded;
コメントで提起されたその他の問題に対処するため、2015年11月に編集しました。
複雑なオブジェクトの投稿
次のような複雑なビューモデルクラスをWeb APIアクションメソッドパラメータとして持っているとします。
public class CreateUserViewModel
{
public int Id {set;get;}
public string Name {set;get;}
public List<TagViewModel> Tags {set;get;}
}
public class TagViewModel
{
public int Id {set;get;}
public string Code {set;get;}
}
そしてWeb APIエンドポイントは次のようになります
public class ProductController : Controller
{
[HttpPost]
public CreateUserViewModel Save([FromBody] CreateUserViewModel m)
{
// I am just returning the posted model as it is.
// You may do other stuff and return different response.
// Ex : missileService.LaunchMissile(m);
return m;
}
}
この記事の執筆時点では、ASP.NET MVC 6 が最新の安定バージョンであり、MVC6 では、Web API コントローラーと MVC コントローラーの両方がMicrosoft.AspNet.Mvc.Controller
基本クラスから継承されています。
クライアント側からメソッドにデータを送信するには、以下のコードがうまく動作するはずです。
//Build an object which matches the structure of our view model class
var model = {
Name: "Shyju",
Id: 123,
Tags: [{ Id: 12, Code: "C" }, { Id: 33, Code: "Swift" }]
};
$.ajax({
type: "POST",
data: JSON.stringify(model),
url: "../product/save",
contentType: "application/json"
}).done(function(res) {
console.log('res', res);
// Do something with the result :)
});
モデル バインディングは一部のプロパティでは機能しますが、すべてでは機能しません。なぜでしょうか。
Web APIメソッドパラメータを[FromBody]
属性で装飾しない場合
[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
return m;
}
そして、contentTypeプロパティ値を指定せずにモデル(JSON形式ではなく生のJavaScriptオブジェクト)を送信します。
$.ajax({
type: "POST",
data: model,
url: "../product/save"
}).done(function (res) {
console.log('res', res);
});
モデル バインディングは、モデル上のフラット プロパティに対して機能しますが、型が複雑なプロパティや別の型であるプロパティに対しては機能しません。この場合、Id
およびName
プロパティはパラメーターに適切にバインドされますm
が、Tags
プロパティは空のリストになります。
$.post
短いバージョンを使用している場合、リクエストの送信時にデフォルトの Content-Type が使用されるため、同じ問題が発生します。
$.post("../product/save", model, function (res) {
//res contains the markup returned by the partial view
console.log('res', res);
});