JSON POSTデータをオブジェクトとしてWeb APIメソッドに渡すにはどうすればいいですか? 質問する

JSON POSTデータをオブジェクトとしてWeb APIメソッドに渡すにはどうすればいいですか? 質問する

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-Typeajax リクエストのヘッダーを調べると、値が として設定されていることがわかります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);
});

おすすめ記事