it-swarm.com.de

Wie übergebe ich json POST -Daten als Objekt an die Web-API-Methode?

Die ASP.NET MVC4-Web-API-Anwendung definiert die Post-Methode zum Speichern des Kunden. Der Kunde wird im json-Format im Anforderungshauptteil POST übergeben. Der Parameter customer in der post-Methode enthält Nullwerte für Eigenschaften.

Wie kann dies behoben werden, damit die bereitgestellten Daten als Kundenobjekt übergeben werden?

Wenn möglich, sollte Content-Type: application/x-www-form-urlencoded verwendet werden, da ich nicht weiß, wie ich es in der JavaScript-Methode ändern soll, welche Beiträge das Formular bilden.

Regler:

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

Anfrage:

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

EDIT: 31.10.2017

Der gleiche Code/Ansatz funktioniert auch für Asp.Net Core 2.. Der Hauptunterschied besteht darin, dass in asp.net core sowohl Web-API-Controller als auch Mvc-Controller zu einem einzelnen Controllermodell zusammengeführt werden. Ihr Rückgabetyp könnte also IActionResult oder eine seiner Implementierungen sein (Beispiel: OkObjectResult).


Verwenden

contentType:"application/json"

Sie müssen die JSON.stringify -Methode verwenden, um sie beim Senden in eine JSON-Zeichenfolge zu konvertieren.

Und der Model Binder bindet die JSON-Daten an Ihr Klassenobjekt.

Der folgende Code wird gut funktionieren (getestet)

$(function () {
    var customer = {contact_name :"Scott",company_name:"HP"};
    $.ajax({
        type: "POST",
        data :JSON.stringify(customer),
        url: "api/Customer",
        contentType: "application/json"
    });
});

Ergebnis

enter image description here

Die Eigenschaft contentType teilt dem Server mit, dass wir die Daten im JSON-Format senden. Da wir eine JSON-Datenstruktur gesendet haben, erfolgt die Modellbindung ordnungsgemäß.

Wenn Sie die Header der Ajax-Anforderung überprüfen, können Sie feststellen, dass der Wert Content-Type auf application/json festgelegt ist.

Wenn Sie contentType nicht explizit angeben, wird der Standardinhaltstyp application/x-www-form-urlencoded; verwendet.


Bearbeiten Sie am November 2015, um andere mögliche Probleme zu beheben, die in Kommentaren angesprochen wurden.

Ein komplexes Objekt veröffentlichen

Angenommen, Sie haben eine komplexe Ansichtsmodellklasse als Parameter für die Web-API-Aktionsmethode

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

und Ihr Web-API-Endpunkt ist wie

public class ProductController : Controller
{
    [HttpPost]
    public CreateUserViewMode 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;
    }
}

Zum Zeitpunkt dieses Schreibens ist ASP.NET MVC 6 die neueste stabile Version. In MVC6 erben sowohl Web-API-Controller als auch MVC-Controller von der Basisklasse Microsoft.AspNet.Mvc.Controller.

Der folgende Code sollte ordnungsgemäß funktionieren, um Daten von Clientseite an die Methode zu senden

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

Modellbindung funktioniert für einige Eigenschaften, aber nicht für alle! Warum ?

Wenn Sie den Parameter der Web-API-Methode nicht mit dem Attribut [FromBody] dekorieren

[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
    return m;
}

Senden Sie das Modell (unformatiertes JavaScript-Objekt, nicht im JSON-Format), ohne den contentType-Eigenschaftswert anzugeben

$.ajax({
    type: "POST",
    data: model,
    url: "../product/save"
}).done(function (res) {
     console.log('res', res);
});

Die Modellbindung funktioniert für die flachen Eigenschaften des Modells, nicht für die Eigenschaften, bei denen der Typ komplex ist, oder für einen anderen Typ. In unserem Fall werden die Eigenschaften Id und Name ordnungsgemäß an den Parameter m gebunden. Die Eigenschaft Tags ist jedoch eine leere Liste.

Dasselbe Problem tritt auf, wenn Sie die Kurzversion $.post verwenden, die beim Senden der Anforderung den Standard-Inhaltstyp verwendet.

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

Das Arbeiten mit POST in Webapi kann schwierig sein! Möchte die schon richtige Antwort ergänzen ..

Konzentriert sich speziell auf POST, da der Umgang mit GET trivial ist. Ich glaube nicht, dass viele nach einer Lösung für ein Problem mit GET mit Webapis suchen würden. Sowieso..

Wenn Ihre Frage lautet: - Wie verwende ich in MVC Web Api - andere Namen für benutzerdefinierte Aktionsmethoden als die generischen HTTP-Verben? - Mehrere Posts ausführen? - Mehrere einfache Typen posten? - Komplexe Typen über jQuery posten?

Dann können die folgenden Lösungen helfen:

Fügen Sie zunächst eine Web-API-Route hinzu, um benutzerdefinierte Aktionsmethoden in der Web-API zu verwenden:

public static void Register(HttpConfiguration config)
{
    config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{action}");
}

Und dann können Sie Aktionsmethoden erstellen wie:

[HttpPost]
public string TestMethod([FromBody]string value)
{
    return "Hello from http post web api controller: " + value;
}

Feuern Sie nun die folgende jQuery von Ihrer Browserkonsole aus

$.ajax({
    type: 'POST',
    url: 'http://localhost:33649/api/TestApi/TestMethod',
    data: {'':'hello'},
    contentType: 'application/x-www-form-urlencoded',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

Zweitens, um mehrere Posts auszuführen , ist es einfach, mehrere Aktionsmethoden zu erstellen und mit dem Attribut [HttpPost] zu dekorieren. Verwenden Sie den [ActionName ("MyAction")], um benutzerdefinierte Namen usw. zuzuweisen. Wird im vierten Punkt unten zu jQuery kommen

Drittens ist es zunächst nicht möglich, mehrere EINFACHE Typen in einer einzigen Aktion zu veröffentlichen. Darüber hinaus gibt es ein spezielles Format , um sogar einen einzelnen einfachen Typ zu posten. (abgesehen von der Übergabe des Parameters in der Abfragezeichenfolge oder im REST -Stil). Dies war der Punkt, an dem ich mich mit Rest Clients (wie Fiddler und Chrome's Advanced REST Client Extension) herumschlagen und fast 5 Stunden lang im Internet herumjagen musste, als sich die folgende URL schließlich als hilfreich erwies. Werden die für den Link relevanten Inhalte zitiert, kann dies zum Erliegen kommen!

Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
={"Name":"Turbo Tina","Email":"[email protected]"}

PS: Ist dir die eigentümliche Syntax aufgefallen?

http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api

Wie auch immer, lassen Sie uns über diese Geschichte hinwegkommen. Weitermachen:

Viertens wird das Posten komplexer Typen über jQuery, natürlich, $ .ajax () sofort in die Rolle kommen:

Angenommen, die Aktionsmethode akzeptiert ein Person-Objekt mit einer ID und einem Namen. Also, aus Javascript:

var person = { PersonId:1, Name:"James" }
$.ajax({
    type: 'POST',
    url: 'http://mydomain/api/TestApi/TestMethod',
    data: JSON.stringify(person),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

Und die Aktion wird so aussehen:

[HttpPost]
public string TestMethod(Person person)
{
    return "Hello from http post web api controller: " + person.Name;
}

All das oben Genannte hat für mich funktioniert !! Prost!

68
Vaibhav

Ich habe gerade damit gespielt und ein merkwürdiges Ergebnis entdeckt. Angenommen, Sie haben öffentliche Eigenschaften für Ihre Klasse in C # wie folgt:

public class Customer
{
    public string contact_name;
    public string company_name;
}

dann müssen Sie den von Shyju vorgeschlagenen Trick JSON.stringify ausführen und ihn folgendermaßen aufrufen:

var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
    type: "POST",
    data :JSON.stringify(customer),
    url: "api/Customer",
    contentType: "application/json"
});

Wenn Sie jedoch Getter und Setter für Ihre Klasse wie folgt definieren:

public class Customer
{
    public string contact_name { get; set; }
    public string company_name { get; set; }
}

dann kann man es viel einfacher nennen:

$.ajax({
    type: "POST",
    data :customer,
    url: "api/Customer"
});

Dies verwendet den HTTP-Header:

Content-Type:application/x-www-form-urlencoded

Ich bin nicht ganz sicher, was hier passiert, aber es sieht aus wie ein Bug (Feature?) Im Framework. Vermutlich rufen die verschiedenen Bindungsmethoden verschiedene "Adapter" auf, und während der Adapter für application/json mit öffentlichen Eigenschaften arbeitet, funktioniert der Adapter für formularkodierte Daten nicht.

Ich habe jedoch keine Ahnung, welche Vorgehensweise als best practice angesehen werden würde.

10
Andy

Verwenden Sie die JSON.stringify () Um die Zeichenfolge im JSON-Format abzurufen, stellen Sie sicher, dass Sie beim Ausführen des AJAX -Aufrufs die folgenden Attribute übergeben:

  • contentType: 'application/json'
  • dataType: 'json'

Nachfolgend finden Sie den JQuery-Code zum Ausführen eines Ajax-Post-Aufrufs an die asp.net-Web-API:

var product =
    JSON.stringify({
        productGroup: "Fablet",
        productId: 1,
        productName: "Lumia 1525 64 GB",
        sellingPrice: 700
    });

$.ajax({
    URL: 'http://localhost/api/Products',
    type: 'POST',
    contentType: 'application/json',
    dataType: 'json',
    data: product,
    success: function (data, status, xhr) {
        alert('Success!');
    },
    error: function (xhr, status, error) {
        alert('Update Error occurred - ' + error);
    }
});
1
Dilip Nannaware

Stellen Sie sicher, dass Ihr WebAPI-Dienst ein stark typisiertes Objekt mit einer Struktur erwartet, die der von Ihnen übergebenen JSON entspricht. Stellen Sie sicher, dass Sie den JSON-Code angeben, den Sie veröffentlichen.

Hier ist mein JavaScript (mit AngluarJS):

$scope.updateUserActivity = function (_objuserActivity) {
        $http
        ({
            method: 'post',
            url: 'your url here',
            headers: { 'Content-Type': 'application/json'},
            data: JSON.stringify(_objuserActivity)
        })
        .then(function (response)
        {
            alert("success");
        })
        .catch(function (response)
        {
            alert("failure");
        })
        .finally(function ()
        {
        });

Und hier ist mein WebAPI Controller:

[HttpPost]
[AcceptVerbs("POST")]
public string POSTMe([FromBody]Models.UserActivity _activity)
{
    return "hello";
}
0
scott janson

1) Auf Ihrer Client-Seite können Sie die http.post-Anfrage in der folgenden Zeichenfolge senden

var IndexInfo = JSON.stringify(this.scope.IndexTree);
this.$http.post('../../../api/EvaluationProcess/InsertEvaluationProcessInputType', "'" + IndexInfo + "'" ).then((response: any) => {}

2) Dann können Sie es in Ihrem Web-API-Controller deserialisieren

public ApiResponce InsertEvaluationProcessInputType([FromBody]string IndexInfo)
    {
var des = (ApiReceivedListOfObjects<TempDistributedIndex>)Newtonsoft.Json.JsonConvert.DeserializeObject(DecryptedProcessInfo, typeof(ApiReceivedListOfObjects<TempDistributedIndex>));}

3) Ihre ApiReceivedListOfObjects-Klasse sollte wie folgt aussehen

public class ApiReceivedListOfObjects<T>
    {
        public List<T> element { get; set; }

    }

4) Stellen Sie sicher, dass Ihre serialisierte Zeichenfolge (IndexInfo hier) der folgenden Struktur entspricht, bevor Sie den Befehl JsonConvert.DeserializeObject in Schritt 2 ausführen

var resp = @"
    {
        ""element"": [
        {
            ""A"": ""A Jones"",
            ""B"": ""500015763""
        },
        {
            ""A"": ""B Smith"",
            ""B"": ""504986213""
        },
        {
            ""A"": ""C Brown"",
            ""B"": ""509034361""
        }
        ]
    }";
0

Folgender Code, um Daten im json-Format anstelle der XML-Web-API 2 zurückzugeben: -

Folgende Zeile in die Datei Global.asax einfügen

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
0
UJS
@model MVCClient.Models.ProductDetails

@{
    ViewBag.Title = "ProductDetails";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript">

    $(document).ready(function () {
        $("#Save").click(function () {
            var ProductDetails = new Object();
            ProductDetails.ProductName =  $("#txt_productName").val();
            ProductDetails.ProductDetail = $("#txt_desc").val();
            ProductDetails.Price= $("#txt_price").val();
            $.ajax({
                url: "http://localhost:24481/api/Product/addProduct",
                type: "Post",
                dataType:'JSON',
                data:ProductDetails, 

                success: function (data) {
                    alert('Updated Successfully');
                    //window.location.href = "../Index";
                },
                error: function (msg) { alert(msg); }
            });
        });
    });
    </script>
<h2>ProductDetails</h2>

<form id="form1" method="post">
    <fieldset>
        <legend>ProductDetails</legend>


        <div class="editor-label">
            @Html.LabelFor(model => model.ProductName)
        </div>
        <div class="editor-field">

            <input id="txt_productName" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.ProductName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ProductDetail)
        </div>
        <div class="editor-field">

            <input id="txt_desc" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.ProductDetail)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">

            <input id="txt_price" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.Price)
        </div>



        <p>
            <input id="Save" type="button" value="Create" />
        </p>
    </fieldset>

</form>
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>

</form>



@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}
0
Debendra Dash

Microsoft gab ein gutes Beispiel dafür:

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

Bestätigen Sie zuerst die Anfrage

if (ModelState.IsValid)

und als die serialisierten Daten verwenden.

Content = new StringContent(update.Status)

Hier ist 'Status' ein Feld des komplexen Typs. Die Serialisierung erfolgt über .NET, darüber müssen Sie sich keine Gedanken machen.

0
FrankyHollywood