176

WebAPI コントローラーに複数のパラメーターを投稿しようとしています。1 つのパラメーターは URL からのもので、もう 1 つは本文からのものです。ここにURLがあります: /offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/

これが私のコントローラーコードです:

public HttpResponseMessage Put(Guid offerId, OfferPriceParameters offerPriceParameters)
{
    //What!?
    var ser = new DataContractJsonSerializer(typeof(OfferPriceParameters));
    HttpContext.Current.Request.InputStream.Position = 0;
    var what = ser.ReadObject(HttpContext.Current.Request.InputStream);

    return new HttpResponseMessage(HttpStatusCode.Created);
}

本文の内容は JSON です。

{
    "Associations":
    {
        "list": [
        {
            "FromEntityId":"276774bb-9bd9-4bbd-a7e7-6ed3d69f196f",
            "ToEntityId":"ed0d2616-f707-446b-9e40-b77b94fb7d2b",
            "Types":
            {
                "list":[
                {
                    "BillingCommitment":5,
                    "BillingCycle":5,
                    "Prices":
                    {
                        "list":[
                        {
                            "CurrencyId":"274d24c9-7d0b-40ea-a936-e800d74ead53",
                            "RecurringFee":4,
                            "SetupFee":5
                        }]
                    }
                }]
            }
        }]
    }
}

offerPriceParametersデフォルトのバインディングがコントローラーの引数にバインドできない理由は何ですか? 常に null に設定されます。しかし、を使用して本体からデータを回復できDataContractJsonSerializerます。

引数の属性も使用しようとしましたFromBodyが、どちらも機能しません。

4

12 に答える 12

101
[HttpPost]
public string MyMethod([FromBody]JObject data)
{
    Customer customer = data["customerData"].ToObject<Customer>();
    Product product = data["productData"].ToObject<Product>();
    Employee employee = data["employeeData"].ToObject<Employee>();
    //... other class....
}

参照の使用

using Newtonsoft.Json.Linq;

JQuery Ajax のリクエストを使用する

var customer = {
    "Name": "jhon",
    "Id": 1,
};
var product = {
    "Name": "table",
    "CategoryId": 5,
    "Count": 100
};
var employee = {
    "Name": "Fatih",
    "Id": 4,
};

var myData = {};
myData.customerData = customer;
myData.productData = product;
myData.employeeData = employee;

$.ajax({
    type: 'POST',
    async: true,
    dataType: "json",
    url: "Your Url",
    data: myData,
    success: function (data) {
        console.log("Response Data ↓");
        console.log(data);
    },
    error: function (err) {
        console.log(err);
    }
});
于 2016-05-18T11:20:35.417 に答える
67

ネイティブの WebAPI は、複数の POST パラメーターのバインドをサポートしていません。Colin が指摘しているように、彼が参照している私のブログ投稿で概説されている多くの制限があります。

カスタム パラメーター バインダーを作成することによる回避策があります。これを行うコードは見苦しく複雑ですが、ブログに詳細な説明とともにコードを投稿しました。ここでプロジェクトにプラグインする準備ができています。

複数の単純な POST 値を ASP.NET Web API に渡す

于 2013-01-19T10:35:14.760 に答える
32

属性ルーティングが使用されている場合は、[FromUri] および [FromBody] 属性を使用できます。

例:

[HttpPost()]
[Route("api/products/{id:int}")]
public HttpResponseMessage AddProduct([FromUri()] int id,  [FromBody()] Product product)
{
  // Add product
}
于 2015-07-10T15:22:01.940 に答える
24

HttpPost メソッドで Json オブジェクトを渡し、動的オブジェクトでパースします。それは正常に動作します。これはサンプルコードです:

ウェブアピ:

[HttpPost]
public string DoJson2(dynamic data)
{
   //whole:
   var c = JsonConvert.DeserializeObject<YourObjectTypeHere>(data.ToString()); 

   //or 
   var c1 = JsonConvert.DeserializeObject< ComplexObject1 >(data.c1.ToString());

   var c2 = JsonConvert.DeserializeObject< ComplexObject2 >(data.c2.ToString());

   string appName = data.AppName;
   int appInstanceID = data.AppInstanceID;
   string processGUID = data.ProcessGUID;
   int userID = data.UserID;
   string userName = data.UserName;
   var performer = JsonConvert.DeserializeObject< NextActivityPerformers >(data.NextActivityPerformers.ToString());

   ...
}

複合オブジェクト型は、オブジェクト、配列、およびディクショナリです。

ajaxPost:
...
Content-Type: application/json,
data: {"AppName":"SamplePrice",
       "AppInstanceID":"100",
       "ProcessGUID":"072af8c3-482a-4b1c‌​-890b-685ce2fcc75d",
       "UserID":"20",
       "UserName":"Jack",
       "NextActivityPerformers":{
           "39‌​c71004-d822-4c15-9ff2-94ca1068d745":[{
                 "UserID":10,
                 "UserName":"Smith"
           }]
       }}
...
于 2013-01-24T02:35:07.093 に答える
10

素敵な質問とコメント - ここでの返信から多くのことを学びました :)

追加の例として、ボディとルートを混在させることもできることに注意してください。

[RoutePrefix("api/test")]
public class MyProtectedController 
{
    [Authorize]
    [Route("id/{id}")]
    public IEnumerable<object> Post(String id, [FromBody] JObject data)
    {
        /*
          id                                      = "123"
          data.GetValue("username").ToString()    = "user1"
          data.GetValue("password").ToString()    = "pass1"
         */
    }
}

次のように呼び出します。

POST /api/test/id/123 HTTP/1.1
Host: localhost
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer x.y.z
Cache-Control: no-cache

username=user1&password=pass1


enter code here
于 2016-08-24T16:39:40.810 に答える
2

この場合、routeTemplate はどのようになりますか?

この URL を投稿しました:

/offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/

これが機能するためには、次のようなルーティングが期待されますWebApiConfig:

routeTemplate: {controller}/{offerId}/prices/

その他の仮定は次のとおりです。 - あなたのコントローラは と呼ばれOffersControllerます。- リクエスト本文で渡す JSON オブジェクトの型がOfferPriceParameters(派生型ではない) であること起こります)

そして、Filip が述べたように、「0% の受け入れ率」は人々に時間を無駄にしていると思わせる可能性があるため、いくつかの回答を受け入れ始めると、質問に役立ちます。

于 2013-01-19T14:48:51.697 に答える
2

ModelBinding の方法を使用したくない場合は、DTO を使用してこれを行うことができます。たとえば、複合型を受け入れ、BusinessLayer からデータを送信する DataLayer で POST アクションを作成します。UI->API 呼び出しの場合に実行できます。

サンプル DTO を次に示します。教師を生徒に割り当て、複数のレポート/科目を生徒に割り当てます。

public class StudentCurriculumDTO
 {
     public StudentTeacherMapping StudentTeacherMapping { get; set; }
     public List<Paper> Paper { get; set; }
 }    
public class StudentTeacherMapping
 {
     public Guid StudentID { get; set; }
     public Guid TeacherId { get; set; }
 }

public class Paper
 {
     public Guid PaperID { get; set; }
     public string Status { get; set; }
 }

次に、DataLayer のアクションを次のように作成できます。

[HttpPost]
[ActionName("MyActionName")]
public async Task<IHttpActionResult> InternalName(StudentCurriculumDTO studentData)
  {
     //Do whatever.... insert the data if nothing else!
  }

BusinessLayer から呼び出すには:

using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", dataof_StudentCurriculumDTO)
  {
     //Do whatever.... get response if nothing else!
  }

一度に複数の生徒のデータを送信したい場合でも、これは機能します。以下のMyActionように変更します。[FromBody] を記述する必要はありません。WebAPI2 はデフォルトで複合型 [FromBody] を受け取ります。

public async Task<IHttpActionResult> InternalName(List<StudentCurriculumDTO> studentData)

それを呼び出している間、List<StudentCurriculumDTO>データの a を渡します。

using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", List<dataof_StudentCurriculumDTO>)
于 2017-03-20T05:04:51.553 に答える