Der Post-Parameter ist immer null

197

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

ianrathbone
quelle
Nur um das Problem zu vergrößern - es ist nicht exklusiv für JSON, es passiert auch mit XML.
Ianrathbone
3
Ich habe zwei Tage lang damit gekämpft und nachdem ich jeden Artikel gelesen hatte, den ich darüber finden konnte, stellte sich heraus, dass es so einfach war, die JSON-Zeichenfolge in der WebRequest korrekt zu formatieren: Die Daten müssen mit doppelten Anführungszeichen beginnen und enden, und wenn Sie dann Verwenden Sie einfache Anführungszeichen in Ihren JSON-Daten, damit alles gut funktioniert.
Gineer

Antworten:

101

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-Parameterbindung

UPDATE: 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

Jim Harte
quelle
9
Ich habe dem [FromBody] einen Wirbel gegeben, aber es hatte keine Änderung
ianrathbone
11
Übergeben Sie nur den Wert (dh nicht als JSON-Objekt) und es sollte laut blogs.msdn.com/b/jmstall/archive/2012/04/16/… funktionieren
Jim Harte
8
Das Anhängen =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.
Gitsitgo
16
Das ist so dumm und nervig, dass ich nicht weiß, ob ich die Antwort, die mir bei der Lösung meines Problems geholfen hat, positiv oder negativ bewerten soll ... Warum um alles in der Welt muss sie in diesem Format vorliegen? (Entschuldigung für die Einstellung, nur zu viel Zeit damit verschwendet, und es macht keinen Sinn ... :(). Sie sollten wirklich Unterstützung für das Format hinzufügen, das die Leute erwarten, dass es akzeptiert.
Gdoron unterstützt Monica
6
Vielen Dank! Wie um alles in der Welt sollten wir wissen, dass wir den Parameternamen entfernen müssen, wenn wir nur einen Parameter senden? Welches Vogelhirn kam auf diese Idee?
Jenny O'Reilly
104

Ich habe mir heute den Kopf darüber gekratzt.

Meine Lösung besteht darin , den HTTP-Stack [FromBody]in a zu ändern und im HttpRequestMessageWesentlichen 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]:

Mein ursprünglicher Endpunkt

Meine Lösung für dieses Problem bestand darin, wieder ein HttpRequestMessagefür die Signatur meines Endpunkts zu verwenden.

Geben Sie hier die Bildbeschreibung ein

Mit dieser Codezeile können Sie dann auf die Postdaten zugreifen:

Geben Sie hier die Bildbeschreibung ein

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 HttpRequestMessagebesteht darin, dass Sie von Ihrem Endpunkt aus auf alle http-Header zugreifen können.

Ocean Airdrop
quelle
6
Ausgezeichnete Lösung ... ich habe 9 Stunden gebraucht, um dies zu finden, mein Problem behoben, nachdem ich den [FromBody] -Stringwert entfernt und durch HttpRequestMessage
Kev
1
Klappt wunderbar! Aber gibt es keine Möglichkeit, einen tatsächlichen Parametertyp eines bestimmten Objekts zu verwenden? zB Parameter vom Typ Reihenfolge für eine Web-API-Methode?
Ron Nuni
7
Nur eine Randnotiz, Sie brauchen die HttpRequestMessage requestin der Methodensignatur nicht, da Sie diese immer schon haben. Im Methodenkörper kann auf das RequestObjekt zugegriffen werden. zBRequest.Content.ReadAsStringAsync().Result;
Morvael
Normalerweise liegt dieses Problem daran, dass Ihr JSON-Objekt falsch ist. Ich habe festgestellt, dass dies immer daran liegt, dass der Konstruktor einen ungültigen Typ hat und Json nicht weiß, wie er ihn wie eine Guid in eine Zeichenfolge konvertieren soll. Fügen Sie also entweder den Konverter über Einstellungen hinzu oder fügen Sie einen leeren Konstruktor hinzu, und Sie müssen nicht zu altem Code wie diesem zurückkehren.
Nick Turner
Am einfachsten ist es, das Objekt in eine Zeichenfolge umzuwandeln und es dann zu konvertieren. Der JSON-Fehler wird angezeigt. Überprüfen Sie auch Ihre Header.
Nick Turner
71

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-Typein Ihre POST-Anfrage aufzunehmen.

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

Alternativ müssen Sie gemäß den Kommentaren unten möglicherweise einen JSON-Header einfügen

Content-Type: application/json
Kirk Broadhurst
quelle
11
Ich hatte ein ähnliches Problem, außer dass ich den Inhaltstyp einstellen musste: application / json
dvallejo
2
Wie im Beitrag angegeben - Ich hatte bereits Inhaltstyp hinzugefügt: application / json
ianrathbone
2
application / x-www-form-urlencoded hat bei mir nicht funktioniert, Content-Type: application / json hat funktioniert.
Liang
1
Unabhängig vom Inhaltstyp müssen Sie, wenn Sie nur einen Parameter haben, nur den Wert ohne den Parameternamen im Hauptteil der Anforderung senden. Also wird id = 13 nicht funktionieren. Sie müssen 13 alleine senden. Siehe Jims Antwort.
Jenny O'Reilly
Ich musste verwenden contentType: "application/x-www-form-urlencoded; charset=UTF-8", für ein vollständiges Beispiel siehe Complete Cient and Server
RyBolt
57

Ich bin auch auf dieses Problem gestoßen, und so habe ich mein Problem gelöst

Webapi-Code:

public void Post([FromBody] dynamic data)
{
    string value = data.value;
    /* do stuff */
}

Client-Code:

$.post( "webapi/address", { value: "some value" } );
George
quelle
1
Dies funktioniert, wenn der Client JSON sendet. Wenn ich einen einfachen Wert wie den String sende some value, dataist er null.
Brianestey
Ändern Sie einfach Ihren Client-Code, um ein js-Objekt zurückzusenden.
George
Tolle und saubere Möglichkeit, Daten von JSON zu erhalten
Wouter Vanherck
Wenn Sie json senden, ist var json = JsonConvert.SerializeObject (data);
Dvallejo
41

Ich habe verwendet Postmanund den gleichen Fehler gemacht. Ich habe das valueObjekt als json anstelle des Strings übergeben

{
    "value": "test"
}

Offensichtlich ist der obige falsch, wenn der API-Parameter vom Typ string ist.

Übergeben Sie den String einfach in doppelte Anführungszeichen im API-Text:

"test"
JerryGoyal
quelle
2
Dies war mein Problem und wahrscheinlich die wirkliche Lösung für die Frage. Eine JSON-codierte Zeichenfolge hat Anführungszeichen
Kyle W
1
Ich bin auch auf dieses Problem bei Postman gestoßen. Es stellt sich heraus, dass ich fälschlicherweise "Formulardaten" anstelle von "Rohdaten" für Body gewählt habe, wenn der Inhaltstyp auf application / json eingestellt ist. Sie können sich auf die Screenshots von zzyykk123456 in den Ausgaben von aspnet Github beziehen: github.com/aspnet/Home/issues/2202
Chun Lin
Das hat bei mir funktioniert. Mit Swagger (swashbuckle) muss ich den Inhaltstyp: application / json festlegen und doppelte Anführungszeichen verwenden.
John Henckel
1
Genau mein Problem Aber ich muss beachten, dass Sie in Ajax-Anfragen 'data: JSON.stringify ("YourString")'
Amir Hossein Ahmadi
1
@AmirHosseinAhmadi Ich habe gerade diese auf Ajax und Säge auf , daß tatsächlich verwenden JSON.stringifyverursacht wurde mein [frombody]sein null. Nachdem das Datenfeld auf einen Zeichenfolgenwert (dh eine JSON-Zeichenfolge) gesetzt wurde, funktionierte es.
Nexaspx
19

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.)

public HttpResponseMessage Post(ValueModel model)
{
    return Request.CreateResponse<string>(HttpStatusCode.OK, "Value Recieved: " + model.Value);
}

public class ValueModel
{
    public string Value { get; set; }
}

Das folgende JSON-Objekt wird im HTTP-POST-Text gesendet. Der Inhaltstyp ist application / json

{ "value": "In MVC4 Beta you could map to simple types like string, but testing with RC 2012 I have only been able to map to DataModels and only JSON (application/json) and url-encoded (application/x-www-form-urlencoded body formats have worked. XML is not working for some reason" }

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 valuehat 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 )

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Despertar
quelle
Dies funktionierte bei mir mit request.ContentType = "application / json; charset = UTF-8";
Arvind Krmar
15

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 stringwie folgt lautet , sollten Sie eine einfache Zeichenfolge mit doppelten Anführungszeichen im Textkörper senden (wenn Sie Ajax oder Postman verwenden), z.

//send "{\"a\":1}" in body to me, note the outer double quotes
[HttpPost("api1")]
public String PostMethod1([FromBody]string value)
{
    return "received " + value; //  "received {\"a\":1}"
}

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}

public class MyPoco{
    public int a;
    public int b;
}

//send {"a":1, "b":2} in body to me
[HttpPost("api2")]
public String PostMethod2([FromBody]MyPoco value)
{
    return "received " + value.ToString();  //"received your_namespace+MyPoco"
}
Leon
quelle
11

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

chrjs
quelle
Refactoring ist genau das, was mich hier gebissen hat, danke für den Tipp!
Alan
10

Das hat bei mir funktioniert:

  1. Erstellen Sie eine C # DTO-Klasse mit einer Eigenschaft für jedes Attribut, das Sie von jQuery / Ajax übergeben möchten

    public class EntityData
    {
        public string Attr1 { get; set; }
        public string Attr2 { get; set; }
    }
  2. Definieren Sie die Web-API-Methode:

    [HttpPost()]
    public JObject AddNewEntity([FromBody] EntityData entityData)
    {
  3. Rufen Sie die Web-API als solche auf:

    var entityData = {
        "attr1": "value1",
        "attr2": "value2"
    };
    
    $.ajax({
        type: "POST",
        url: "/api/YOURCONTROLLER/addnewentity",
        async: true,
        cache: false,
        data: JSON.stringify(entityData),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            ...
        }
    });
BigMan73
quelle
Vielen Dank für die Veröffentlichung, ich habe zahlreiche Beispiele ausprobiert, aber das hat bei mir funktioniert!
Satbir
10

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.

dvc.junior
quelle
6

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.

byobgyn
quelle
Ja, die Web-API wird ohne den Zeichensatz = utf-8 nicht deserialisiert. blog.codenamed.nl/2015/05/12/…
Sam Rueby
4

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.

Richard Pursehouse
quelle
3

Mit Angular konnte ich Daten in diesem Format übergeben:

 data: '=' + JSON.stringify({ u: $scope.usrname1, p: $scope.pwd1 }),
 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' }

Und in Web API Controler:

    [HttpPost]
    public Hashtable Post([FromBody]string jsonString)
    {
        IDictionary<string, string> data = JsonConvert.DeserializeObject<IDictionary<string, string>>(jsonString);
        string username = data["u"];
        string pwd = data["p"];
   ......

Alternativ könnte ich auch JSON-Daten wie folgt posten:

    data: { PaintingId: 1, Title: "Animal show", Price: 10.50 } 

Akzeptieren Sie im Controller einen Klassentyp wie den folgenden:

    [HttpPost]
    public string POST(Models.PostModel pm)
    {

     ....
    }

So oder so funktioniert es, wenn Sie eine etablierte öffentliche Klasse in der API haben, dann poste JSON, andernfalls poste '=' + JSON.stringify ({..: ..., ..: ...})

Yogi
quelle
3

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.

syb
quelle
2

Zeile hinzufügen

        ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());

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.

Sergey Kudriavtsev
quelle
Danke für die Hilfe, aber leider hat es nicht geholfen. Ich werde die Leitung vorerst beibehalten, da dies ohnehin hilfreich sein kann!
Ianrathbone
Nur um die gleichen Probleme hinzuzufügen, treten auf, wenn ich XML
ianrathbone
2

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:

public static void Register(HttpConfiguration config)
{
     config.Routes.MapHttpRoute(
           name: "DefaultApi",
           routeTemplate: "api/{controller}/{id}",
           defaults: new { id = RouteParameter.Optional }
     );    

     var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
     jsonFormatter.UseDataContractJsonSerializer = true;
}

Ich kommentiere einfach aus jsonFormatter.UseDataContractJsonSerializer = true;und mein Eingabeparameter ist nicht mehr null. Vielen Dank an 'Despertar' für den Hinweis.

Amir Chatrbahr
quelle
2

Wenn Sie sich über Ihren gesendeten JSON sicher sind, müssen Sie Ihre API sorgfältig verfolgen:

  1. Microsoft.AspNet.WebApi.TracingPaket installieren
  2. Fügen Sie config.EnableSystemDiagnosticsTracing();in der WebApiConfigKlasse inside RegisterMethode hinzu.

Schauen Sie sich nun die Debug-Ausgabe an und Sie werden wahrscheinlich einen ungültigen ModelStateProtokolleintrag finden.

Wenn ModelStatees ungültig ist, finden Sie möglicherweise die wahre Ursache in Errors:

Niemand kann eine solche Ausnahme erraten:

Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Mohsen Afshin
quelle
du hast mein Leben gerettet. Als Modell null und nach der Installation des Pakets festgestellt, dass mein JSON nicht im richtigen Format vorliegt.
Khizar Iqbal
2

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.

  <system.web>
    <httpRuntime targetFramework="4.7" maxRequestLength="1073741824" />
  </system.web>

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.

Mohghaderi
quelle
2

JSON.stringify (...) hat meine Probleme gelöst

Ragnarswanson
quelle
1

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:

public class MyController : ApiController
{
    public IEnumerable<MyModel> Get([FromUri] MyComplexType input)
    {
        // input is not null as long as [FromUri] is present in the method arg
    }
}
danludwig
quelle
Dies liegt daran, dass der Hauptteil der Anforderung bei Verwendung von GET ignoriert wird (und manchmal einen Fehler verursacht). Der Grund, warum es jetzt funktioniert, ist, dass Sie jetzt Parameter für die Abfragezeichenfolge übergeben und Ihr Körper leer ist, wie es auf einem GET
RyBolt
1

Ich hatte das gleiche Problem in Fiddler. Ich hatte bereits Content-Type: application/json; charset=utf-8oder Content-Type: application/jsonim 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 zu null.

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

gosr
quelle
Ich musste dasselbe bei Postman tun. Aber ich muss das nicht tun, wenn ich Spring Services anrufe. Scheint ein Problem auf der .Net-Seite zu sein.
Malcolm McRoberts
1

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:

public ActionResult Test2([FromBody] jObject str)
{
        return Json(new { message = "Test1 Returned: "+ str }); ;
}
Pini Cheyni
quelle
Test ( [FromBody] object body, [FromHeader(Name="Content-Type")] string bodyMediaType) könnte besser funktionieren, da die Überprüfung bodyMediaType == "application.json"vor dem Gießen des Körpers an JObject eine Möglichkeit für Alternativen bietet.
VladH
1

Die beste Lösung für mich ist das vollständige HTTP wie folgt:

[Route("api/open")]
[HttpPost]
public async Task<string> open(HttpRequestMessage request)
{
    var json = await request.Content.ReadAsStringAsync();
    JavaScriptSerializer jss = new JavaScriptSerializer();            
    WS_OpenSession param = jss.Deserialize<WS_OpenSession>(json);
    return param.sessionid;
}

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

albertdadze
quelle
1

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.

jaiveeru
quelle
1

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

 public static string HttpPostRequest(string url, Dictionary<string, string> postParameters)
    {
        string postData = "=";

        foreach (string key in postParameters.Keys)
        {
            postData += HttpUtility.UrlEncode(key) + "="
                  + HttpUtility.UrlEncode(postParameters[key]) + ",";
        }

        HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
        myHttpWebRequest.Method = "POST";

        byte[] data = System.Text.Encoding.ASCII.GetBytes(postData);

        myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
        myHttpWebRequest.ContentLength = data.Length;

        Stream requestStream = myHttpWebRequest.GetRequestStream();
        requestStream.Write(data, 0, data.Length);
        requestStream.Close();

        HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

        Stream responseStream = myHttpWebResponse.GetResponseStream();

        StreamReader myStreamReader = new StreamReader(responseStream, System.Text.Encoding.Default);

        string pageContent = myStreamReader.ReadToEnd();

        myStreamReader.Close();
        responseStream.Close();

        myHttpWebResponse.Close();

        return pageContent;
    }
JTStuedle
quelle
1

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:

    var myData = null, url = 'api/' + 'Named/' + 'NamedMethod';

    myData = 7;

    $http.post(url, "'" + myData + "'")
         .then(function (response) { console.log(response.data); });

    myData = "some sentence";

    $http.post(url, "'" + myData + "'")
         .then(function (response) { console.log(response.data); });

    myData = { name: 'person name', age: 21 };

    $http.post(url, "'" + JSON.stringify(myData) + "'")
         .then(function (response) { console.log(response.data); });

    $http.post(url, "'" + angular.toJson(myData) + "'")
         .then(function (response) { console.log(response.data); });

c #:

    public class NamedController : ApiController
    {
        [HttpPost]
        public int NamedMethod([FromBody] string value)
        {
            return value == null ? 1 : 0;
        }
    }
Opochitsky Dimitry
quelle
1

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

Hat AlTaiar
quelle
1

Ü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:

{
    "shoeSize": 10.5
}

aber Ihr c # -Modell sieht folgendermaßen aus:

class Shoe{
    public int shoeSize;
}

Der Modellordner lehnt das Modell ab und Sie erhalten null.

TwitchBronBron
quelle
1

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.

[HttpPost]
public string PostProcessData([FromBody]string parameters) {
    if (!String.IsNullOrEmpty(parameters)) {
        JObject json = JObject.Parse(parameters);

        // Code logic below
        // Can access params via json["paramName"].ToString();
    }
    return "";
}

Client-Seite mit jQuery

var dataToSend = JSON.stringify({ param1: "value1", param2: "value2"...});
$.post('/Web_API_URI', { '': dataToSend }).done(function (data) {
     console.debug(data); // returned data from Web API
 });

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.

Nathan
quelle
0

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.

Lapenkov Vladimir
quelle