Seit dem Upgrade auf RC für WebAPI habe ich ein merkwürdiges Problem beim Aufrufen von POST auf meinem WebAPI. Ich bin sogar zu der Basisversion zurückgekehrt, die für ein neues Projekt generiert wurde. So:
public void Post(string value)
{
}
und Anruf von Fiddler:
Header:
User-Agent: Fiddler
Host: localhost:60725
Content-Type: application/json
Content-Length: 29
Body:
{
"value": "test"
}
Beim Debuggen wird der Zeichenfolge "Wert" niemals zugewiesen. Es ist einfach immer NULL. Hat jemand dieses Problem?
(Ich habe das Problem zum ersten Mal bei einem komplexeren Typ gesehen.)
Das Problem ist nicht nur an ASP.NET MVC 4 gebunden, sondern tritt auch nach der RC-Installation für ein neues ASP.NET MVC 3-Projekt auf
c#
.net
asp.net-web-api
asp.net-web-api-routing
ianrathbone
quelle
quelle
Antworten:
Da Sie nur einen Parameter haben, können Sie versuchen, ihn mit dem
[FromBody]
Attribut zu dekorieren , oder die Methode so ändern, dass ein DTO mit Wert als Eigenschaft akzeptiert wird, wie hier vorgeschlagen: MVC4 RC WebApi-ParameterbindungUPDATE: Die offizielle ASP.NET-Site wurde heute mit einer hervorragenden Erklärung aktualisiert: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 1
Kurz gesagt, wenn Sie einen einzelnen einfachen Typ im Body senden, senden Sie nur den Wert, dem ein Gleichheitszeichen (=) vorangestellt ist, z. B. body:
=test
quelle
=
vor mir hat bei mir nie funktioniert, bis ich Jims Rat in seinem Kommentar befolgt habe (nicht als JSON-Objekt) und es funktioniert hat. Das ist der Schlüssel! Ich mag es wirklich nicht, wie wählerisch WebAPI ist.:(
). Sie sollten wirklich Unterstützung für das Format hinzufügen, das die Leute erwarten, dass es akzeptiert.Ich habe mir heute den Kopf darüber gekratzt.
Meine Lösung besteht darin , den HTTP-Stack
[FromBody]
in a zu ändern und imHttpRequestMessage
Wesentlichen nach oben zu verschieben.In meinem Fall sende ich Daten über die Leitung, die gezippt ist. Json wird dann base64'd. All dies von einer Android App.
Die ursprüngliche Signatur meines Webendpunkts sah folgendermaßen aus
[FromBody]
:Meine Lösung für dieses Problem bestand darin, wieder ein
HttpRequestMessage
für die Signatur meines Endpunkts zu verwenden.Mit dieser Codezeile können Sie dann auf die Postdaten zugreifen:
Dies funktioniert und ermöglicht Ihnen den Zugriff auf die unberührten Rohdaten. Sie müssen nicht mit dem Geiger herumspielen, der am Anfang Ihrer Zeichenfolge ein = -Zeichen setzt oder den Inhaltstyp ändert.
Nebenbei habe ich zunächst versucht, einer der obigen Antworten zu folgen, nämlich den Inhaltstyp in "Inhaltstyp: application / x-www-form-urlencoded" zu ändern. Für Rohdaten ist dies ein schlechter Rat, da dadurch + Zeichen entfernt werden.
Ein base64-String, der so beginnt: "MQ0AAB + LCAAAAAA" endet also wie folgt: "MQ0AAB LCAAAAAA"! Nicht was du willst.
Ein weiterer Vorteil der Verwendung
HttpRequestMessage
besteht darin, dass Sie von Ihrem Endpunkt aus auf alle http-Header zugreifen können.quelle
HttpRequestMessage request
in der Methodensignatur nicht, da Sie diese immer schon haben. Im Methodenkörper kann auf dasRequest
Objekt zugegriffen werden. zBRequest.Content.ReadAsStringAsync().Result;
Ich habe dies gerade mit Fiddler geschehen lassen. Das Problem war, dass ich nicht angegeben hatte
Content-Type
.Versuchen Sie, einen Header für
Content-Type
in Ihre POST-Anfrage aufzunehmen.Alternativ müssen Sie gemäß den Kommentaren unten möglicherweise einen JSON-Header einfügen
quelle
contentType: "application/x-www-form-urlencoded; charset=UTF-8"
, für ein vollständiges Beispiel siehe Complete Cient and ServerIch bin auch auf dieses Problem gestoßen, und so habe ich mein Problem gelöst
Webapi-Code:
Client-Code:
quelle
some value
,data
ist er null.Ich habe verwendet
Postman
und den gleichen Fehler gemacht. Ich habe dasvalue
Objekt als json anstelle des Strings übergebenOffensichtlich ist der obige falsch, wenn der API-Parameter vom Typ string ist.
Übergeben Sie den String einfach in doppelte Anführungszeichen im API-Text:
quelle
JSON.stringify
verursacht wurde mein[frombody]
seinnull
. Nachdem das Datenfeld auf einen Zeichenfolgenwert (dh eine JSON-Zeichenfolge) gesetzt wurde, funktionierte es.Versuchen Sie, eine Klasse als Datenmodell zu erstellen, und senden Sie dann ein JSON-Objekt mit Eigenschaften, die mit den Eigenschaften Ihrer Datenmodellklasse übereinstimmen. (Hinweis: Ich habe dies getestet und es funktioniert mit der neuesten MVC 4 RC 2012, die ich heute heruntergeladen habe.)
Das folgende JSON-Objekt wird im HTTP-POST-Text gesendet. Der Inhaltstyp ist application / json
Ich glaube, der Grund, warum Sie eine Datenmodellklasse erstellen müssen, liegt darin, dass angenommen wird, dass einfache Werte aus den URL-Parametern stammen und dass ein einzelner komplexer Wert aus dem Body stammt. Sie haben die
[FromBody]
und[FromUrl]
Attribute, aber die Verwendung[FromBody] string value
hat bei mir immer noch nicht funktioniert. Es scheint, als würden sie immer noch viele Fehler beheben, daher bin ich mir sicher, dass sich dies in Zukunft ändern wird.Bearbeiten: XML muss im Körper funktionieren. Der Standard-XML-Serializer wurde anstelle von XmlSerializer in DataContractSerializer geändert. Das Einfügen der folgenden Zeile in meine Global.asax-Datei hat dieses Problem behoben ( Referenz )
quelle
Nach einigen Versuchen denke ich, dass das Standardverhalten korrekt ist und es nichts zu hacken gibt.
Der einzige Trick ist: Wenn Ihr Argument für die Post-Methode
string
wie folgt lautet , sollten Sie eine einfache Zeichenfolge mit doppelten Anführungszeichen im Textkörper senden (wenn Sie Ajax oder Postman verwenden), z.Andernfalls sollte eine JSON-Zeichenfolge im Post-Body ohne äußere doppelte Anführungszeichen und maskierte innere Anführungszeichen in die Modellklasse (den Argumenttyp) analysiert werden können, z.
{"a":1, "b":2}
quelle
Ich habe seit einigen Minuten nach einer Lösung für dieses Problem gesucht, daher werde ich meine Lösung teilen.
Wenn Sie ein Modell veröffentlichen, muss Ihr Modell einen leeren / Standardkonstruktor haben, andernfalls kann das Modell offensichtlich nicht erstellt werden. Seien Sie vorsichtig beim Refactoring. ;)
quelle
Das hat bei mir funktioniert:
Erstellen Sie eine C # DTO-Klasse mit einer Eigenschaft für jedes Attribut, das Sie von jQuery / Ajax übergeben möchten
Definieren Sie die Web-API-Methode:
Rufen Sie die Web-API als solche auf:
quelle
Für diejenigen, die das gleiche Problem mit Swagger oder Postman haben wie ich, erhalten Sie immer noch einen Nullwert, wenn Sie ein einfaches Attribut als Zeichenfolge in einem Beitrag übergeben, auch wenn der "ContentType" angegeben ist.
Nur vorbei:
MyValue
Wird in der Steuerung als null erhalten.
Aber wenn Sie bestehen:
"MyValue"
Der Wert wird richtig.
Die Zitate machten hier den Unterschied. Dies gilt natürlich nur für Swagger und Postman. In einer Frontend-App mit Angular sollte dies beispielsweise vom Framework automatisch behoben werden.
quelle
Ich hatte das gleiche Problem und stellte fest, dass das Problem beim Ändern des Inhaltstyps in "application / json" nicht behoben wurde. "Application / json; charset = utf-8" funktionierte jedoch.
quelle
Ich hatte ein ähnliches Problem, bei dem das Anforderungsobjekt für meine Web-API-Methode immer null war. Ich habe festgestellt, dass die Web-API dies als HTTP-GET und nicht als POST behandelte, da dem Namen der Controller-Aktion das Präfix "Get" vorangestellt wurde. Nach dem Umbenennen der Controller-Aktion funktioniert sie nun wie vorgesehen.
quelle
Mit Angular konnte ich Daten in diesem Format übergeben:
Und in Web API Controler:
Alternativ könnte ich auch JSON-Daten wie folgt posten:
Akzeptieren Sie im Controller einen Klassentyp wie den folgenden:
So oder so funktioniert es, wenn Sie eine etablierte öffentliche Klasse in der API haben, dann poste JSON, andernfalls poste '=' + JSON.stringify ({..: ..., ..: ...})
quelle
In meinem Fall war das Problem, dass der Parameter eine Zeichenfolge und kein Objekt war. Ich habe den Parameter in JObject von Newsoft.Json geändert und es funktioniert.
quelle
Zeile hinzufügen
protected void Application_Start()
Bis zum Ende der Funktion in Global.asax.cs wurde ein ähnliches Problem für mich in ASP.NET MVC3 behoben.quelle
Wenn Sie einen DataContractSerializer für Ihren XML-Formatierer oder JSON-Formatierer verwenden, müssen Sie ihn entfernen. Ich hatte dies in meiner WebApiConfig-Datei:
Ich kommentiere einfach aus
jsonFormatter.UseDataContractJsonSerializer = true;
und mein Eingabeparameter ist nicht mehr null. Vielen Dank an 'Despertar' für den Hinweis.quelle
Wenn Sie sich über Ihren gesendeten JSON sicher sind, müssen Sie Ihre API sorgfältig verfolgen:
Microsoft.AspNet.WebApi.Tracing
Paket installierenconfig.EnableSystemDiagnosticsTracing();
in derWebApiConfig
Klasse insideRegister
Methode hinzu.Schauen Sie sich nun die Debug-Ausgabe an und Sie werden wahrscheinlich einen ungültigen
ModelState
Protokolleintrag finden.Wenn
ModelState
es ungültig ist, finden Sie möglicherweise die wahre Ursache inErrors
:Niemand kann eine solche Ausnahme erraten:
quelle
Ich hatte das gleiche Problem, null als Parameter zu erhalten, aber es hing mit großen Objekten zusammen. Es stellte sich heraus, dass das Problem mit der maximalen Länge des IIS zusammenhängt. Es kann in web.config konfiguriert werden.
Ich frage mich, warum die Web-API den Fehler unterdrückt und Nullobjekte an meine APIs sendet. Ich habe den Fehler mit Microsoft.AspNet.WebApi.Tracing gefunden.
quelle
JSON.stringify (...) hat meine Probleme gelöst
quelle
Ich weiß, dass dies keine Antwort auf diese Frage ist, aber ich bin darauf gestoßen, als ich nach einer Lösung für mein Problem gesucht habe.
In meinem Fall wurde der komplexe Typ nicht gebunden, aber ich habe keinen POST durchgeführt, sondern einen GET mit Querystring-Parametern. Die Lösung bestand darin, [FromUri] zum Argument hinzuzufügen:
quelle
Ich hatte das gleiche Problem in Fiddler. Ich hatte bereits
Content-Type: application/json; charset=utf-8
oderContent-Type: application/json
im Anforderungsheader.Mein Anfragetext war ebenfalls eine einfache Zeichenfolge, und in Fiddler hatte ich geschrieben :
{'controller':'ctrl'}
. Dies machte den String-Parameter in meiner POST-Methode zunull
.Fix : Denken Sie daran, Anführungszeichen zu verwenden, um eine Zeichenfolge anzuzeigen. Das heißt, ich habe es durch Schreiben behoben
"{'controller':'ctrl'}"
. (Hinweis: Verwenden Sie beim Schreiben von JSON entweder Apostrophe oder schließen Sie die Anführungszeichen wie folgt an :)"{\"controller\":\"ctrl\"}"
.quelle
Der einfachste Weg, mit einfachen JSON-Objekten umzugehen, die ich an MVC 6 übergebe, besteht darin, den Typ des Post-Parameters wie NewtonSoft jObject abzurufen:
quelle
[FromBody] object body, [FromHeader(Name="Content-Type")] string bodyMediaType
) könnte besser funktionieren, da die ÜberprüfungbodyMediaType == "application.json"
vor dem Gießen des Körpers an JObject eine Möglichkeit für Alternativen bietet.Die beste Lösung für mich ist das vollständige HTTP wie folgt:
und dann Deserialisieren der Zeichenfolge für das Objekt, das Sie im Post-Body erwarten. Für mich ist WS_OpenSession eine Klasse, die Sitzungs-ID, Benutzer und Schlüssel enthält.
Von dort aus können Sie das param-Objekt verwenden und auf seine Eigenschaften zugreifen.
Sehr sehr effektiv.
Ich habe gesagt, von dieser URL bezogen:
http://bizcoder.com/posting-raw-json-to-web-api
quelle
Bei komplexen Typen versucht die Web-API, den Wert mithilfe eines Medientyp-Formatierers aus dem Nachrichtentext zu lesen.
Bitte überprüfen Sie, ob Sie ein
[Serializable]
Attribut für Ihre Modellklasse haben.Entfernen Sie das Attribut, um festzustellen, ob es funktioniert. Das hat bei mir funktioniert.
quelle
Ich bin etwas spät zur Party, aber jeder, der über einen NULL-Wert stolpert, der bei Verwendung eines Controllers übergeben wurde, fügt einfach "=" an der Vorderseite Ihrer POST-Anfrage hinzu.
Der Controller hat auch einen NULL-Wert übergeben, als ich die Anwendung / json Content-Type verwendet habe. Beachten Sie den folgenden Inhaltstyp "application / x-www-form-urlencoded". Der Rückgabetyp von der API ist jedoch "application / json".
quelle
Es spielt keine Rolle, welche Art von Wert Sie veröffentlichen möchten. Fügen Sie ihn einfach in Anführungszeichen ein, um ihn als Zeichenfolge zu erhalten. Nicht für komplexe Typen.
Javascript:
c #:
quelle
Wenn Sie die Annotation [FromBody] einfügen und ein Dto-Objekt als Parameter für Ihre Methode haben und die Daten immer noch nicht verarbeiten können, überprüfen Sie die Eigenschaften und Felder Ihres DTO.
Ich hatte das gleiche Problem, bei dem mein DTO null wurde. Ich fand den Grund dafür, dass eine der Eigenschaften auf ein Objekt zeigte, das nicht serialisiert werden kann :( was dazu führt, dass der Medienformatierer die Daten nicht analysiert. Daher war das Objekt immer null. Ich hoffe, es hilft auch anderen
quelle
Überprüfen Sie Ihre Datentypen. Der Dotnet-Modellordner konvertiert einen Float nicht in eine Ganzzahl (und ich gehe von anderen verwandten Konzepten aus). Dadurch wird das gesamte Modell abgelehnt.
Wenn Sie json wie diesen haben:
aber Ihr c # -Modell sieht folgendermaßen aus:
Der Modellordner lehnt das Modell ab und Sie erhalten null.
quelle
Ich bin ziemlich spät dran, hatte aber ähnliche Probleme und nach einem Tag, an dem ich viele Antworten hier durchgesehen und Hintergrundinformationen erhalten habe, habe ich die einfachste / leichteste Lösung gefunden, um einen oder mehrere Parameter an eine Web-API-2-Aktion zurückzugeben folgt:
Dies setzt voraus, dass Sie wissen, wie Sie einen Web-API-Controller / eine Web-API-Aktion mit korrektem Routing einrichten. Weitere Informationen finden Sie unter: https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with -aspnet-web-api / tutorial-your-first-web-api .
Zunächst die Controller-Aktion, diese Lösung erfordert auch die Newtonsoft.Json-Bibliothek.
Client-Seite mit jQuery
Das Hauptproblem, das ich gefunden habe, war sicherzustellen, dass Sie nur einen einzigen Gesamtparameter an die Web-API zurücksenden und sicherstellen, dass dieser keinen Namen hat, sondern nur den Wert.
{ '': dataToSend }
Andernfalls ist Ihr Wert auf der Serverseite null.Damit können Sie einen oder mehrere Parameter in einer JSON-Struktur an die Web-API senden und müssen keine zusätzlichen Objekte serverseitig deklarieren, um komplexe Daten zu verarbeiten. Mit dem JObject können Sie auch alle übergebenen Parameter dynamisch durchlaufen, um die Skalierbarkeit zu vereinfachen, falls sich Ihre Parameter im Laufe der Zeit ändern. Hoffentlich hilft das jemandem, der wie ich Probleme hatte.
quelle
Die korrekte Übergabe einzelner Parameter im Hauptteil an WebAPI funktioniert mit diesem Code
$.post(url, { '': productId }
Und es in Aktion zu fangen
[HttpPost] public ShoppingCartAddRemoveViewModel Delete([FromBody]string value)
Der Schlüssel ist, das Zauberwort 'Wert' zu verwenden. Es kann auch int oder ein primitiver Typ sein. Unabhängig von den Korrekturen des Inhaltstyps oder des Headers. Das Problem ist, dass dieser Code in mvc post action nicht funktioniert.
quelle