Parametr post ma zawsze wartość NULL

197

Od czasu uaktualnienia do wersji RC dla interfejsu WebAPI mam dziwny problem podczas wywoływania POST na moim interfejsie WebAPI. Wróciłem nawet do podstawowej wersji wygenerowanej w nowym projekcie. Więc:

public void Post(string value)
{
}

i dzwoniąc z Fiddlera:

Header:
User-Agent: Fiddler
Host: localhost:60725
Content-Type: application/json
Content-Length: 29

Body:
{
    "value": "test"
}

Podczas debugowania ciąg „wartość” nigdy nie jest przypisywany. Po prostu zawsze jest NULL. Ktoś ma ten problem?

(Pierwszy raz zobaczyłem problem z bardziej złożonym typem)

Problem nie jest związany tylko z ASP.NET MVC 4, ten sam problem występuje dla świeżego projektu ASP.NET MVC 3 po instalacji RC

ianrathbone
źródło
Aby dodać do problemu - nie dotyczy wyłącznie JSON, dzieje się tak również z XML.
ianrathbone
3
Pracowałem nad tym od dwóch dni i po przeczytaniu każdego artykułu, który mogłem o nim znaleźć, okazało się to tak proste, jak prawidłowe sformatowanie ciągu JSON w WebRequest: Dane muszą zaczynać się i kończyć podwójnymi cudzysłowami, a jeśli następnie używaj pojedynczych cudzysłowów w danych JSON, wszystko gra ładnie.
Gineer

Odpowiedzi:

101

Ponieważ masz tylko jeden parametr, możesz spróbować ozdobić go [FromBody]atrybutem lub zmienić metodę, aby zaakceptować DTO z wartością jako właściwość, jak zasugerowałem tutaj: Powiązanie parametrów MVC4 RC WebApi

AKTUALIZACJA: Oficjalna strona ASP.NET została dziś zaktualizowana z doskonałym wyjaśnieniem: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 1

W skrócie, wysyłając pojedynczy prosty typ w treści, wyślij tylko wartość poprzedzoną znakiem równości (=), np. Body:

=test

Jim Harte
źródło
9
Dałem wir [FromBody], ale to się nie zmieniło
ianrathbone
11
Przekaż tylko wartość (tj. Nie jako obiekt JSON) i powinna działać, zgodnie z blogs.msdn.com/b/jmstall/archive/2012/04/16/…
Jim Harte
8
Dołączenie =z przodu nigdy dla mnie nie działało, dopóki nie zastosowałem się do rad Jima w jego komentarzu (nie jako obiektu JSON) i zadziałało. To jest klucz! Naprawdę nie podoba mi się, jak wybredna jest funkcja WebAPI.
gitsitgo
16
To jest tak głupie i denerwujące, że nie wiem, czy głosować, czy głosować odpowiedź, która pomogła mi rozwiązać mój problem ... Dlaczego, u licha, musi być w tym formacie? (Przepraszam za to podejście, po prostu zmarnowałem na to zbyt wiele czasu i nie ma to żadnego sensu ... :(). Naprawdę powinieneś dodać obsługę formatu, który ludzie będą akceptować.
gdoron wspiera Monikę
6
Dzięki! Skąd, u licha, powinniśmy wiedzieć, że musimy usunąć nazwę parametru, wysyłając tylko jeden parametr? Który móżdżek wpadł na ten pomysł?
Jenny O'Reilly
104

Drapałem się nad tym dzisiaj.

Moje rozwiązanie jest zmienić [FromBody]Do HttpRequestMessagezasadniczo porusza się stos HTTP.

W moim przypadku przesyłam dane przez drut, który jest spakowany json, który jest następnie base64'd. Wszystko to z aplikacji na Androida.

Oryginalny podpis mojego internetowego punktu końcowego wyglądał następująco (przy użyciu [FromBody]):

Mój oryginalny punkt końcowy

Rozwiązaniem tego problemu było przywrócenie używania HttpRequestMessagepodpisu mojego punktu końcowego.

wprowadź opis zdjęcia tutaj

Następnie możesz uzyskać dostęp do danych postu za pomocą tego wiersza kodu:

wprowadź opis zdjęcia tutaj

Działa to i umożliwia dostęp do nieprzetworzonych nieprzetworzonych danych postu. Nie musisz zadzierać ze skrzypkiem umieszczającym znak = na początku łańcucha lub zmieniającym typ zawartości.

Nawiasem mówiąc, najpierw spróbowałem zastosować jedną z powyższych odpowiedzi, która polegała na zmianie typu zawartości na: „Typ zawartości: aplikacja / x-www-form-urlencoded”. W przypadku surowych danych jest to zła rada, ponieważ usuwa znaki +.

Tak więc ciąg base64, który zaczyna się w ten sposób: „MQ0AAB + LCAAAAAA” kończy się tak, jak ten „MQ0AAB LCAAAAAA”! Nie to, czego chcesz.

Kolejną zaletą korzystania HttpRequestMessagejest to, że uzyskujesz dostęp do wszystkich nagłówków http z poziomu punktu końcowego.

Ocean Airdrop
źródło
6
Doskonałe rozwiązanie ... znalezienie tego zajęło mi 9 godzin, rozwiązałem problem po usunięciu wartości ciągu [FromBody] i zastąpiłem go HttpRequestMessage
Kev
1
Działa jak marzenie! ale czy nie ma sposobu na użycie rzeczywistego typu parametru określonego obiektu? np. parametr typu Zamówienie na metodę interfejsu API?
Ron Nuni,
7
Na marginesie, nie POTRZEBUJESZ HttpRequestMessage requestpodpisu metody, ponieważ zawsze masz go już. W treści metody można uzyskać do niego dostęp na Requestobiekcie. np.Request.Content.ReadAsStringAsync().Result;
Morvael
Zwykle ten problem wynika z niepoprawności obiektu JSON. Odkryłem, że zawsze tak jest, ponieważ w konstruktorze ma niepoprawny typ, a Json nie wie, jak go przekonwertować „Jak Guid na łańcuch”. Dodaj konwerter za pomocą ustawień lub dodaj pusty konstruktor i nie musisz wracać do starego kodu w ten sposób.
Nick Turner
Najprostszym sposobem jest przełączenie obiektu na ciąg znaków, a następnie próba jego konwersji, a zobaczysz błąd JSON. Sprawdź też, czy masz nagłówki.
Nick Turner
71

Właśnie tak się stało przy użyciu Fiddler. Problem polegał na tym, że nie sprecyzowałem Content-Type.

Spróbuj dołączyć nagłówek do Content-Typeżądania POST.

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

Alternatywnie, zgodnie z komentarzami poniżej, może być konieczne dołączenie nagłówka JSON

Content-Type: application/json
Kirk Broadhurst
źródło
11
Miałem podobny problem, tyle że musiałem ustawić Content-Type: application / json
dvallejo
2
Jak określono w poście - już dodałem Content-Type: application / json
ianrathbone
2
application / x-www-form-urlencoded nie działał dla mnie, Content-Type: application / json nie.
liang
1
Bez względu na typ zawartości, jeśli masz tylko jeden parametr, musisz wysłać tylko wartość bez nazwy parametru w treści żądania. Więc id = 13 nie będzie działać. Musisz wysłać 13 samodzielnie. Zobacz odpowiedź Jima.
Jenny O'Reilly
Musiałem użyć contentType: "application/x-www-form-urlencoded; charset=UTF-8", aby uzyskać pełny przykład, zobacz Kompletny klient i serwer
RyBolt
57

Wpadłem również na ten problem i w ten sposób rozwiązałem swój problem

kod webapi:

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

kod klienta:

$.post( "webapi/address", { value: "some value" } );
Jerzy
źródło
1
Działa to, jeśli klient wysyła JSON. Jeśli przesyłam prostą wartość, taką jak ciąg some value, dataoznacza to, że jest pusta.
brianestey
łatwo, zmień kod klienta, aby odesłać obiekt js.
George
Świetny i czysty sposób na uzyskanie danych z JSON
Wouter Vanherck
Jeśli wysyłasz json, to var json = JsonConvert.SerializeObject (data);
dvallejo
41

Używałem Postmani robiłem ten sam błąd .. przekazując valueobiekt as json zamiast łańcucha

{
    "value": "test"
}

Oczywiście powyższe jest błędne, gdy parametr api jest typu string.

Więc po prostu przekaż ciąg w podwójnych cudzysłowach w treści interfejsu API:

"test"
JerryGoyal
źródło
2
To był mój problem i prawdopodobnie prawdziwe rozwiązanie tego pytania. Ciąg zakodowany w JSON zawiera cytaty
Kyle W
1
Ten problem również spotkałem na liście Postman. Okazuje się, że błędnie wybrałem „form-data” zamiast „raw” dla Body, gdy Content-Type jest ustawiony na application / json. Możesz zapoznać się z zrzutami ekranu zzyykk123456 w wydaniach aspnet Github: github.com/aspnet/Home/issues/2202
Chun Lin
To zadziałało dla mnie. Za pomocą Swagger (swashbuckle) muszę ustawić typ zawartości: application / json i użyć podwójnych cudzysłowów.
John Henckel
1
Dokładnie mój problem, ale muszę zauważyć, że w żądaniach Ajax powinieneś robić „data: JSON.stringify („ YourString ”)”
Amir Hossein Ahmadi
1
@AmirHosseinAhmadi właśnie napotkał to na AJAX i zobaczyłem, że rzeczywiście przy JSON.stringifybył przekraczany [frombody]być null. Po ustawieniu pola danych na wartość ciągu (czyli ciąg Json) zadziałało.
Nexaspx
19

Spróbuj utworzyć klasę, która będzie służyć jako model danych, a następnie wyślij obiekt JSON o właściwościach pasujących do właściwości klasy modelu danych. (Uwaga: przetestowałem to i działa z najnowszym MVC 4 RC 2012, który właśnie pobrałem dzisiaj).

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

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

Poniższy obiekt JSON jest wysyłany w treści HTTP-POST, typ zawartości to 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" }

Uważam, że powodem, dla którego musisz utworzyć klasę modelu danych, jest to, że zakłada się, że proste wartości pochodzą z parametrów adresu URL, a pojedyncza wartość złożona pochodzi z treści. Mają atrybuty [FromBody]i [FromUrl], ale używanie [FromBody] string valuenadal nie działało dla mnie. Wygląda na to, że wciąż pracują nad wieloma błędami, więc jestem pewien, że to się zmieni w przyszłości.

Edycja: Gotowy XML do pracy w ciele. Domyślny serializator XML został zmieniony na DataContractSerializer zamiast XmlSerializer. Umieszczenie następującego wiersza w moim pliku Global.asax rozwiązało ten problem ( odniesienie )

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Despertar
źródło
działało to dla mnie z request.ContentType = "application / json; charset = UTF-8";
Arvind Krmar
15

Po kilku próbach myślę, że domyślne zachowanie jest prawidłowe i nie ma nic do zhakowania.

Jedyną sztuczką jest: jeśli argument metody post jest stringpodobny do poniższego, powinieneś wysłać zwykły ciąg znaków z podwójnymi cudzysłowami w treści (gdy używasz ajax lub listonosza), np.

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

W przeciwnym razie, jeśli wyślesz ciąg json w treści postu bez zewnętrznych podwójnych cudzysłowów i unikniesz wewnętrznych cudzysłowów, wówczas powinno być możliwe ich przeanalizowanie do klasy modelu (typ argumentu), np.{"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
źródło
11

Przez kilka minut szukałem rozwiązania tego problemu, więc podzielę się moim rozwiązaniem.

Jeśli opublikujesz model, Twój model musi mieć pustego / domyślnego konstruktora, w przeciwnym razie model oczywiście nie będzie mógł zostać utworzony. Zachowaj ostrożność podczas refaktoryzacji. ;)

chrjs
źródło
Refaktoryzacja jest dokładnie tym, co mnie tu ugryzło, dzięki za wskazówkę!
Alan
10

To działało dla mnie:

  1. Utwórz klasę C # DTO z właściwością dla każdego atrybutu, który chcesz przekazać z jQuery / Ajax

    public class EntityData
    {
        public string Attr1 { get; set; }
        public string Attr2 { get; set; }
    }
  2. Zdefiniuj metodę interfejsu API sieci Web:

    [HttpPost()]
    public JObject AddNewEntity([FromBody] EntityData entityData)
    {
  3. Zadzwoń do interfejsu API jako takiego:

    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
źródło
Dzięki za opublikowanie tego, próbowałem wielu próbek, ale to zadziałało dla mnie!
Satbir
10

Dla tych, którzy mają ten sam problem ze Swaggerem lub Listonoszem, jak ja, jeśli przekazujesz prosty atrybut jako ciąg w poście, nawet z określonym „ContentType”, nadal otrzymasz wartość zerową.

Przechodząc tylko:

MyValue

Dostanie się do kontrolera jako zerowy.

Ale jeśli zdasz:

„MyValue”

Wartość się poprawi.

Cytaty zrobiły różnicę tutaj. Oczywiście dotyczy to tylko Swaggera i Listonosza. Na przykład w aplikacji Frontend używającej Angulara powinno to zostać rozwiązane automatycznie przez framework.

dvc.junior
źródło
6

Miałem ten sam problem i stwierdziłem, że zmiana typu zawartości na „application / json” nie rozwiązała problemu. Jednak „application / json; charset = utf-8” działało.

byobgyn
źródło
Tak, interfejs API sieci Web nie przekształca się z postaci szeregowej bez charset = utf-8. blog.codenamed.nl/2015/05/12/…
Sam Rueby
4

Miałem podobny problem, w którym obiekt żądania mojej metody interfejsu API sieci Web był zawsze zerowy. Zauważyłem, że ponieważ nazwa działania kontrolera była poprzedzona przedrostkiem „Get”, interfejs API sieci Web traktował to raczej jako HTTP GET, a nie POST. Po zmianie nazwy akcji kontrolera działa teraz zgodnie z przeznaczeniem.

Richard Pursehouse
źródło
3

Dzięki Angular mogłem przekazać dane w tym formacie:

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

I w 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"];
   ......

Ewentualnie mógłbym również opublikować dane JSON w następujący sposób:

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

I w kontrolerze zaakceptuj typ klasy taki jak ten:

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

     ....
    }

Tak czy inaczej działa, jeśli masz ustanowioną klasę publiczną w API, to opublikuj JSON, w przeciwnym razie opublikuj '=' + JSON.stringify ({..: ..., ..: ...})

Jog
źródło
3

W moim przypadku problem polegał na tym, że parametr był łańcuchem, a nie obiektem, zmieniłem parametr na JObject z Newsoft.Json i działa.

syb
źródło
2

Dodawanie linii

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

do końca funkcji protected void Application_Start()w Global.asax.cs naprawiłem podobny problem dla mnie w ASP.NET MVC3.

Sergey Kudriavtsev
źródło
Dzięki za pomoc, ale niestety nie pomogła. Na razie będę trzymać linię, bo to i tak może pomóc!
ianrathbone
Aby dodać te same problemy, pojawiają się, gdy publikuję XML
ianrathbone
2

Jeśli używasz DataContractSerializer dla Xml Formatter lub JSON Formatter, musisz się go pozbyć. Miałem to w moim pliku WebApiConfig:

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

Po prostu komentuję, jsonFormatter.UseDataContractJsonSerializer = true;a mój parametr wejściowy nie jest już pusty. Dzięki „Despertar” za udzielenie mi wskazówki.

Amir Chatrbahr
źródło
2

Jeśli masz pewność co do wysłanego JSON, musisz dokładnie prześledzić API:

  1. Zainstaluj Microsoft.AspNet.WebApi.Tracingpakiet
  2. Dodaj config.EnableSystemDiagnosticsTracing();w WebApiConfigklasie wewnątrz Registermetody.

Teraz spójrz na wynik debugowania, a prawdopodobnie znajdziesz nieprawidłowy ModelStatewpis w dzienniku.

Jeśli ModelStatejest nieprawidłowy, prawdziwą przyczynę możesz znaleźć w Errors:

Nikt nawet nie zgadnie takiego wyjątku:

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
źródło
Uratowałeś mi życie. Otrzymanie wartości NULL jako modelu i po zainstalowaniu pakietu okazało się, że mój JSON ma nieprawidłowy format.
Khizar Iqbal
2

Miałem ten sam problem z uzyskaniem wartości null jako parametru, ale dotyczyło to dużych obiektów. Okazało się, że problem dotyczył maksymalnej długości IIS. Można go skonfigurować w pliku web.config.

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

Zastanawiam się, dlaczego interfejs API sieci Web pomijał błąd i wysyła obiekty zerowe do moich interfejsów API. Znalazłem błąd przy użyciu Microsoft.AspNet.WebApi.Tracing.

mohghaderi
źródło
2

JSON.stringify (...) rozwiązał moje problemy

ragnarswanson
źródło
1

Wiem, że to nie jest odpowiedź na to pytanie, ale natknąłem się na nie, szukając rozwiązania mojego problemu.

W moim przypadku typ złożony nie był związany, ale nie robiłem testu POST, robiłem GET z parametrami zapytania. Rozwiązaniem było dodanie [FromUri] do arg:

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
źródło
Jest tak, ponieważ treść żądania jest ignorowana (a czasami powoduje błąd) podczas korzystania z GET. Powodem, dla którego teraz działa, jest b / c przekazujesz parametry w ciągu zapytania, a twoje ciało jest puste, jak powinno być na GET
RyBolt
1

Miałem ten sam problem w Fiddler. Mam już Content-Type: application/json; charset=utf-8lub Content-Type: application/jsonw nagłówku żądania.

Moja prośba ciało było również zwykły sznurek, aw Skrzypek miałem napisane: {'controller':'ctrl'}. To spowodowało, że parametr string w mojej metodzie POST był null.

Poprawka : pamiętaj, aby używać znaków cudzysłowu, wskazując w ten sposób ciąg znaków. To znaczy, naprawiłem to pisząc "{'controller':'ctrl'}". (Uwaga: pisząc JSON, użyj apostrofów lub unikaj cudzysłowów w następujący sposób:) "{\"controller\":\"ctrl\"}".

gosr
źródło
Musiałem zrobić to samo w Postman. Ale nie muszę tego robić, kiedy dzwonię do serwisów Spring. Wygląda na problem po stronie .Net.
Malcolm McRoberts
1

Najprostszym sposobem, w jaki udało mi się poradzić sobie z prostym obiektem JSON, który przekazuję do MVC 6, jest uzyskanie typu parametru post, takiego jak jObject NewtonSoft:

public ActionResult Test2([FromBody] jObject str)
{
        return Json(new { message = "Test1 Returned: "+ str }); ;
}
Pini Cheyni
źródło
Test ( [FromBody] object body, [FromHeader(Name="Content-Type")] string bodyMediaType) może działać lepiej, ponieważ sprawdzanie bodyMediaType == "application.json"przed rzutowaniem treści na JObject stwarza okazję do alternatyw.
VladH
1

Najlepszym rozwiązaniem dla mnie jest przejście na pełny HTTP, jak poniżej:

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

a następnie deserializowanie ciągu do obiektu, którego oczekujesz w treści postu. Dla mnie WS_OpenSession to klasa zawierająca sessionid, user i key.

Możesz stamtąd użyć obiektu param i uzyskać dostęp do jego właściwości.

Bardzo, bardzo skuteczny.

Powiedziałem, że pochodzą z tego adresu:

http://bizcoder.com/posting-raw-json-to-web-api

albertdadze
źródło
1

W przypadku typów złożonych interfejs API sieci Web próbuje odczytać wartość z treści wiadomości za pomocą formatera typu nośnika.

Sprawdź, czy masz [Serializable]atrybut dekorujący klasę modelu.

Usuń atrybut, aby zobaczyć, czy działa. To zadziałało dla mnie.

jaiveeru
źródło
1

Jestem trochę spóźniony na imprezę, ale każdy, kto natknie się na wartość NULL, przeszedł podczas używania kontrolera, po prostu dodaj „=” na początku żądania POST.

Kontroler również przekazał wartość NULL, gdy użyłem aplikacji / json Content-Type. Zwróć uwagę na treść typu „application / x-www-form-urlencoded” poniżej. Typem zwracanym z interfejsu API jest jednak „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
źródło
1

nie ma znaczenia, jaki typ wartości chcesz opublikować, po prostu umieść go w cudzysłowie, aby uzyskać go jako ciąg. Nie dla złożonych typów.

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

do#:

    public class NamedController : ApiController
    {
        [HttpPost]
        public int NamedMethod([FromBody] string value)
        {
            return value == null ? 1 : 0;
        }
    }
Dymit Opochicki
źródło
1

Jeśli umieścisz adnotację [FromBody] i masz obiekt Dto jako parametr w swojej metodzie i nadal nie możesz uzyskać danych, zacznij przeglądać właściwości i pola swojego DTO.

Miałem ten sam problem, gdy moje DTO zbliżało się do zera. Znalazłem przyczynę tego, że jedna z właściwości wskazywała na obiekt, którego nie można zserializować :( co powoduje, że formatyzator multimediów nie może przeanalizować danych. W ten sposób obiekt zawsze był pusty. Mam nadzieję, że pomaga również innym

Ma AlTaiar
źródło
1

Sprawdź dokładnie swoje typy danych. Spoiwo modelu dotnet nie przekształci liczby zmiennoprzecinkowej na liczbę całkowitą (i zakładam, że istnieją inne powiązane pojęcia). Spowoduje to odrzucenie całego modelu.

Jeśli masz JSON w ten sposób:

{
    "shoeSize": 10.5
}

ale twój model c # wygląda następująco:

class Shoe{
    public int shoeSize;
}

segregator modelu odrzuci model, a otrzymasz wartość zerową.

TwitchBronBron
źródło
1

Spóźniłem się z tym, ale miałem podobne problemy i po całym dniu przeszukiwania wielu odpowiedzi tutaj i zdobywania tła znalazłem najłatwiejsze / najlżejsze rozwiązanie, aby przekazać jeden lub więcej parametrów do Web API 2 Działanie jest takie jak następuje:

Zakłada się, że wiesz, jak skonfigurować kontroler / działanie interfejsu API sieci Web z prawidłowym routingiem, jeśli nie, patrz: https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with -aspnet-web-api / tutorial-your-first-web-api .

Najpierw działanie kontrolera, to rozwiązanie wymaga również biblioteki Newtonsoft.Json.

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

Po stronie klienta za pomocą 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
 });

Kluczowym problemem, jaki znalazłem, było upewnienie się, że wysyłasz tylko jeden ogólny parametr z powrotem do interfejsu API sieci Web i upewnij się, że nie ma on nazwy tylko wartość, w { '': dataToSend }przeciwnym razie twoja wartość będzie zerowa po stronie serwera.

Dzięki temu możesz wysłać jeden lub wiele parametrów do interfejsu API sieci Web w strukturze JSON i nie musisz deklarować żadnych dodatkowych obiektów po stronie serwera do obsługi złożonych danych. JObject umożliwia także dynamiczne iterowanie wszystkich przekazywanych parametrów, umożliwiając łatwiejszą skalowalność w przypadku zmiany parametrów w czasie. Mam nadzieję, że to pomaga komuś, kto walczył tak jak ja.

Nathan
źródło
0

Prawidłowe przekazanie pojedynczego parametru w treści do interfejsu WebAPI działa z tym kodem $.post(url, { '': productId }

I łapanie go w akcji [HttpPost] public ShoppingCartAddRemoveViewModel Delete([FromBody]string value)

Kluczem jest użycie magicznego słowa „wartość”. Może to być także int lub jakiś prymitywny typ. Bez względu na rodzaj treści lub poprawki nagłówka Mess jest taki, że ten kod nie działa w akcji post mvc.

Lapenkov Vladimir
źródło