ASP.NET MVC4 Web API-Anwendung definiert post-Methode, um Kunden zu speichern. Der Kunde wird im json-Format im POST-Anforderungskörper übergeben. Der Kundenparameter in der Post-Methode enthält Nullwerte für Eigenschaften.
Wie kann dies behoben werden, so dass gepostete 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 kann, die das Formular postet.
Steuerung:
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"}
EDIT : 31/10/2017
Der gleiche Code/Ansatz wird auch für Asp.Net Core 2.0 funktionieren. Der Hauptunterschied besteht darin, dass in asp.net core sowohl Web-Api-Controller als auch Mvc-Controller zu einem einzigen Controller-Modell zusammengeführt werden. Ihr Rückgabetyp könnte also IActionResult
oder eine seiner Implementierungen sein (z.B. OkObjectResult
)
Verwenden Sie
contentType:"application/json"
Sie müssen die Methode JSON.stringify
verwenden, um sie in einen JSON-String zu konvertieren, wenn Sie sie senden,
Und der Modellbinder wird die JSON-Daten an Ihr Klassenobjekt binden.
Der folgende Code funktioniert gut (getestet)
$(function () {
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
});
});
Ergebnis
Die Eigenschaft "contentType" teilt dem Server mit, dass wir die Daten im JSON-Format senden. Da wir eine JSON-Datenstruktur gesendet haben, wird die Modellbindung ordnungsgemäß erfolgen.
Wenn Sie sich die Kopfzeilen der Ajax-Anfrage ansehen, können Sie sehen, dass der "Content-Type"-Wert auf "application/json" gesetzt ist.
Wenn Sie contentType nicht explizit angeben, wird der Standardinhaltstyp "application/x-www-form-urlencoded" verwendet.
Änderung vom November 2015, um andere mögliche Probleme zu beheben, die in den Kommentaren angesprochen wurden
Nehmen wir an, Sie haben eine komplexe Ansichtsmodellklasse als Parameter Ihrer Web-Api-Aktionsmethode wie folgt
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 folgt
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;
}
}
*Zum Zeitpunkt der Erstellung dieses Artikels ist ASP.NET MVC 6 die neueste stabile Version und in MVC6 erben sowohl Web-Api-Controller als auch MVC-Controller von der Basisklasse "Microsoft.AspNet.Mvc.Controller".
Um Daten von der Client-Seite an die Methode zu senden, sollte der folgende Code gut funktionieren
//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 :)
});
Wenn Sie den Parameter der Web-Api-Methode nicht mit dem Attribut [FromBody]
ausschmücken
[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
return m;
}
Und senden Sie das Modell (rohes Javascript-Objekt, nicht im JSON-Format) ohne Angabe der contentType-Eigenschaft Wert
$.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, deren Typ komplex/ein anderer Typ ist. In unserem Fall werden die Eigenschaften "ID" und "Name" ordnungsgemäß an den Parameter "m" gebunden, aber die Eigenschaft "Tags" wird eine leere Liste sein.
Das gleiche Problem tritt auf, wenn Sie die Kurzversion "$.post" verwenden, die beim Senden der Anfrage den Standard-Content-Type verwendet.
$.post("../product/save", model, function (res) {
//res contains the markup returned by the partial view
console.log('res', res);
});
Arbeiten mit POST in webapi kann knifflig sein! Möchte die bereits richtige Antwort hinzufügen...
Wird speziell auf POST konzentrieren, wie der Umgang mit GET ist trivial. Ich glaube nicht, dass viele würden suchen rund um für die Lösung eines Problems mit GET mit webapis. Wie auch immer...
Wenn Ihre Frage ist - In MVC Web Api, wie zu - Verwenden Sie benutzerdefinierte Aktion Methodennamen andere als die generische HTTP-Verben? - Führen Sie mehrere Beiträge? - Mehrere einfache Typen posten? - Komplexe Typen über jQuery posten?
Dann können die folgenden Lösungen helfen:
Erstens, um Benutzerdefinierte Aktionsmethoden in der Web-API zu verwenden, fügen Sie eine Web-Api-Route als:
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;
}
Rufen Sie nun in der Konsole Ihres Browsers das folgende jQuery auf
$.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 [HttpPost]-Attribut zu dekorieren. Verwenden Sie den [ActionName("MyAction")], um benutzerdefinierte Namen zuzuweisen, etc. Auf jQuery wird im vierten Punkt weiter unten eingegangen
Drittens: Zunächst einmal ist es nicht möglich, mehrere SIMPLE Typen in einer einzigen Aktion zu buchen. Außerdem gibt es ein besonderes Format, um auch nur einen einfachen Typ zu posten (abgesehen von der Übergabe des Parameters im Query-String oder im REST-Stil). Das war der Punkt, an dem ich mir mit Rest Clients (wie Fiddler und Chrome's Advanced REST Client Extension) den Kopf zerbrochen habe und fast 5 Stunden lang im Web herumgesucht habe, bis sich schließlich die folgende URL als hilfreich erwies. Wird der relevante Inhalt für den Link zitieren könnte tot werden!
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: Haben Sie die besonders Syntax bemerkt?
Wie auch immer, lassen Sie uns diese Geschichte hinter uns lassen. Wir machen weiter:
Viertens, Posting komplexer Typen über jQuery, natürlich, $.ajax() wird prompt in die Rolle kommen:
Nehmen wir an, die Action-Methode nimmt ein Person-Objekt an, das eine ID und einen Namen hat. Also, von 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 sieht dann so aus:
[HttpPost]
public string TestMethod(Person person)
{
return "Hello from http post web api controller: " + person.Name;
}
All das hat bei mir funktioniert! Prost!
I've gerade mit diesem gespielt und entdeckte ein eher seltsames Ergebnis. Angenommen, Sie haben öffentliche Eigenschaften auf Ihre Klasse in C# wie folgt:
public class Customer
{
public string contact_name;
public string company_name;
}
dann müssen Sie den JSON.stringify-Trick anwenden, wie von Shyju vorgeschlagen, und ihn wie folgt 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 in Ihrer Klasse wie folgt definieren:
public class Customer
{
public string contact_name { get; set; }
public string company_name { get; set; }
}
dann können Sie sie viel einfacher aufrufen:
$.ajax({
type: "POST",
data :customer,
url: "api/Customer"
});
Dies verwendet den HTTP-Header:
Content-Type:application/x-www-form-urlencoded
Ich bin mir nicht ganz sicher, was hier passiert, aber es sieht nach einem Fehler (Feature?) im Framework aus. Vermutlich rufen die verschiedenen Bindungsmethoden unterschiedliche Adapter auf, und während der Adapter für application/json mit öffentlichen Eigenschaften funktioniert, funktioniert der für formularcodierte Daten nicht.
Ich habe keine Ahnung, was als beste Praxis angesehen werden würde, obwohl.