1. ホーム
  2. javascript

[解決済み] Web API メソッドに json の POST データをオブジェクトとして渡すにはどうすればよいですか?

2022-03-17 05:05:48

質問

ASP.NET MVC4 Web APIアプリケーションでは、顧客を保存するためにpostメソッドを定義しています。 顧客は、POSTリクエストボディにjson形式で渡されます。 postメソッドのCustomerパラメータは、プロパティにNULL値を含んでいます。

投稿されたデータが顧客オブジェクトとして渡されるようにするには、どのように修正すればよいですか?

フォームを投稿するjavascriptのメソッドで変更する方法が分からないので、できればContent-Type: application/x-www-form-urlencodedを使用したいです。

コントローラです。

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"}

解決方法は?

EDIT : 31/10/2017

同じコード/アプローチで Asp.Net Core 2.0 と同じです。大きな違いは、asp.net core では、Web API コントローラと Mvc コントローラの両方が、単一のコントローラモデルに統合されていることです。そのため、戻り値の型は IActionResult またはその実装(例. 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データ構造を送信しているので、モデルバインディングは適切に行われます。

ajaxリクエストのヘッダを調べると Content-Type という値が設定されています。 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);
});

モデルバインディングは、モデル上のフラットなプロパティに対して機能し、タイプが複雑な/別のタイプであるプロパティには機能しません。私たちの場合 IdName プロパティは、パラメータ m しかし Tags プロパティは空リストになります。

ショートバージョンで使用する場合も同様の問題が発生します。 $.post これはリクエストを送信する際にデフォルトのContent-Typeを使用します。

$.post("../product/save", model, function (res) {
    //res contains the markup returned by the partial view
    console.log('res', res);
});