it-swarm.com.de

WebAPI Multiple Put/Post-Parameter

Ich versuche, mehrere Parameter auf einem WebAPI-Controller bereitzustellen. Ein Parameter stammt von der URL und der andere vom Hauptteil. Hier ist die URL: /offers/40D5E19D-0CD5-4FBD-92F8-43FDBB475333/prices/

Hier ist mein Controller-Code:

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);
}

Der Inhalt des Körpers ist in 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
                        }]
                    }
                }]
            }
        }]
    }
}

Gibt es eine Idee, warum die Standardbindung nicht an das Argument offerPriceParameters meines Controllers binden kann? Es ist immer auf null gesetzt. Aber ich bin in der Lage, die Daten vom Körper mit der DataContractJsonSerializer wiederherzustellen.

Ich versuche auch das FromBody-Attribut des Arguments zu verwenden, aber es funktioniert auch nicht.

121
Normand Bedard

Die WebAPI-Komponente unterstützt nicht die Bindung mehrerer POST - Parameter. Wie Colin darauf hinweist, gibt es eine Reihe von Einschränkungen, die in meinen blog post he-Verweisen aufgeführt sind.

Es gibt eine Problemumgehung, indem Sie einen benutzerdefinierten Parameterordner erstellen. Der Code dafür ist hässlich und kompliziert, aber ich habe Code zusammen mit einer ausführlichen Erklärung in meinem Blog veröffentlicht, der hier in ein Projekt eingefügt werden kann:

Mehrere einfache POST -Werte an ASP.NET-Web-API übergeben

55
Rick Strahl
[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....
}

mit referance

using Newtonsoft.Json.Linq;

Verwenden Sie Request für 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);
    }
});
47
Fatih GÜRDAL

Das Json-Objekt wurde von der HttpPost-Methode übergeben und in einem dynamischen Objekt analysiert. es funktioniert gut. Dies ist ein Beispielcode:

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

webapi:

[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());

   ...
}

Der komplexe Objekttyp kann Objekt, Array und Wörterbuch sein.

16
Bes Ley

Wenn das Attribut-Routing verwendet wird, können Sie die Attribute [FromUri] und [FromBody] verwenden.

Beispiel: 

[HttpPost()]
[Route("api/products/{id:int}")]
public HttpResponseMessage AddProduct([FromUri()] int id,  [FromBody()] Product product)
{
  // Add product
}
16
Bryan Rayner

Sie können mehrere POST -Parameter zulassen, indem Sie die MultiPostParameterBinding-Klasse unter https://github.com/keith5000/MultiPostParameterBinding verwenden.

Um es zu benutzen:

1) Laden Sie den Code im Ordner Source herunter und fügen Sie ihn Ihrem Web-API-Projekt oder einem anderen Projekt in der Projektmappe hinzu.

2) Verwenden Sie das Attribut [MultiPostParameters] für die Aktionsmethoden, die mehrere POST -Parameter unterstützen müssen.

[MultiPostParameters]
public string DoSomething(CustomType param1, CustomType param2, string param3) { ... }

3) Fügen Sie diese Zeile in Global.asax.cs der Application_Start-Methode an einer beliebigen Stelle vorher dem Aufruf von GlobalConfiguration.Configure (WebApiConfig.Register) hinzu:

GlobalConfiguration.Configuration.ParameterBindingRules.Insert(0, MultiPostParameterBinding.CreateBindingForMarkedParameters);

4) Lassen Sie Ihre Parameter die Parameter als Eigenschaften eines Objekts übergeben. Ein Beispiel für ein JSON-Objekt für die DoSomething(param1, param2, param3)-Methode ist:

{ param1:{ Text:"" }, param2:{ Text:"" }, param3:"" }

Beispiel JQuery:

$.ajax({
    data: JSON.stringify({ param1:{ Text:"" }, param2:{ Text:"" }, param3:"" }),
    url: '/MyService/DoSomething',
    contentType: "application/json", method: "POST", processData: false
})
.success(function (result) { ... });

Besuchen Sie den Link für weitere Details.

Haftungsausschluss: Ich bin direkt mit der verknüpften Ressource verbunden. 

7
Keith

Eine einfache Parameterklasse kann verwendet werden, um mehrere Parameter in einem Beitrag zu übergeben:

public class AddCustomerArgs
{
    public string First { get; set; }
    public string Last { get; set; }
}

[HttpPost]
public IHttpActionResult AddCustomer(AddCustomerArgs args)
{
    //use args...
    return Ok();
}
6
Greg Gum

Schöne Frage und Kommentare - viel aus den Antworten hier gelernt :)

Als zusätzliches Beispiel können Sie auch Körper und Routen, z.

[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"
         */
    }
}

Aufruf wie folgt:

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
4

Wie sieht Ihre routeTemplate für diesen Fall aus?

Sie haben diese URL gepostet:

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

Damit dies funktioniert, würde ich ein solches Routing in Ihrer WebApiConfig erwarten:

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

Andere Annahmen sind: - Ihr Controller heißt OffersController.- das JSON-Objekt, das Sie im Anforderungstext übergeben, ist vom Typ OfferPriceParameters (kein abgeleiteter Typ) - Sie haben keine anderen Methoden auf dem Controller, der den Controller stören könnte (falls dies der Fall ist, kommentieren Sie ihn aus und sehen Sie, was passiert)

Und wie Filip erwähnt hat, würde dies Ihren Fragen helfen, wenn Sie anfangen würden, einige Antworten zu akzeptieren, da 'Akzeptanzrate von 0%' die Leute denken lässt, dass sie ihre Zeit verschwenden

1
Joanna Derks

Sie können die Formulardaten als String erhalten:

    protected NameValueCollection GetFormData()
    {
        string root = HttpContext.Current.Server.MapPath("~/App_Data");
        var provider = new MultipartFormDataStreamProvider(root);

        Request.Content.ReadAsMultipartAsync(provider);

        return provider.FormData;
    }

    [HttpPost]
    public void test() 
    {
        var formData = GetFormData();
        var userId = formData["userId"];

        // todo json stuff
    }

https://docs.Microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-2

0
Martien de Jong

Wenn Sie nicht zu ModelBinding gehen möchten, können Sie DTOs verwenden, um dies für Sie zu tun. Erstellen Sie beispielsweise eine Aktion POST in DataLayer, die einen komplexen Typ akzeptiert und Daten vom BusinessLayer sendet. Sie können dies bei einem UI-> API-Aufruf tun.

Hier sind DTO-Beispiele. Weisen Sie einem Schüler einen Lehrer zu und weisen Sie dem Schüler mehrere Dokumente/Themen zu.

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

Dann kann die Aktion im DataLayer folgendermaßen erstellt werden:

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

So rufen Sie es vom BusinessLayer aus an: 

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

Jetzt funktioniert das immer noch, wenn ich Daten von mehreren Studenten gleichzeitig senden möchte. Ändern Sie die MyAction wie folgt. [FromBody] muss nicht geschrieben werden. WebAPI2 verwendet standardmäßig den komplexen Typ [FromBody]. 

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

und dann während des Aufrufs einen List<StudentCurriculumDTO> von Daten übergeben. 

using (HttpResponseMessage response = await client.PostAsJsonAsync("myendpoint_MyActionName", List<dataof_StudentCurriculumDTO>)
0
sandiejat

Parameter anfordern wie

enter image description here

Web-API-Code sein wie

public class OrderItemDetailsViewModel
{
    public Order order { get; set; }
    public ItemDetails[] itemDetails { get; set; }
}

public IHttpActionResult Post(OrderItemDetailsViewModel orderInfo)
{
    Order ord = orderInfo.order;
    var ordDetails = orderInfo.itemDetails;
    return Ok();
}
0