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
c#
.net
asp.net-web-api
asp.net-web-api-routing
ianrathbone
źródło
źródło
Odpowiedzi:
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 WebApiAKTUALIZACJA: 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
źródło
=
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.:(
). Naprawdę powinieneś dodać obsługę formatu, który ludzie będą akceptować.Drapałem się nad tym dzisiaj.
Moje rozwiązanie jest zmienić
[FromBody]
DoHttpRequestMessage
zasadniczo 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]
):Rozwiązaniem tego problemu było przywrócenie używania
HttpRequestMessage
podpisu mojego punktu końcowego.Następnie możesz uzyskać dostęp do danych postu za pomocą tego wiersza kodu:
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
HttpRequestMessage
jest to, że uzyskujesz dostęp do wszystkich nagłówków http z poziomu punktu końcowego.źródło
HttpRequestMessage request
podpisu metody, ponieważ zawsze masz go już. W treści metody można uzyskać do niego dostęp naRequest
obiekcie. np.Request.Content.ReadAsStringAsync().Result;
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.Alternatywnie, zgodnie z komentarzami poniżej, może być konieczne dołączenie nagłówka JSON
źródło
contentType: "application/x-www-form-urlencoded; charset=UTF-8"
, aby uzyskać pełny przykład, zobacz Kompletny klient i serwerWpadłem również na ten problem i w ten sposób rozwiązałem swój problem
kod webapi:
kod klienta:
źródło
some value
,data
oznacza to, że jest pusta.Używałem
Postman
i robiłem ten sam błąd .. przekazującvalue
obiekt as json zamiast łańcuchaOczywiś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:
źródło
JSON.stringify
był przekraczany[frombody]
byćnull
. Po ustawieniu pola danych na wartość ciągu (czyli ciąg Json) zadziałało.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).
Poniższy obiekt JSON jest wysyłany w treści HTTP-POST, typ zawartości to application / json
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 value
nadal 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 )
źródło
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
string
podobny 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.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}
źródło
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. ;)
źródło
To działało dla mnie:
Utwórz klasę C # DTO z właściwością dla każdego atrybutu, który chcesz przekazać z jQuery / Ajax
Zdefiniuj metodę interfejsu API sieci Web:
Zadzwoń do interfejsu API jako takiego:
źródło
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.
źródło
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.
źródło
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.
źródło
Dzięki Angular mogłem przekazać dane w tym formacie:
I w Web API Controler:
Ewentualnie mógłbym również opublikować dane JSON w następujący sposób:
I w kontrolerze zaakceptuj typ klasy taki jak ten:
Tak czy inaczej działa, jeśli masz ustanowioną klasę publiczną w API, to opublikuj JSON, w przeciwnym razie opublikuj '=' + JSON.stringify ({..: ..., ..: ...})
źródło
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.
źródło
Dodawanie linii
do końca funkcji
protected void Application_Start()
w Global.asax.cs naprawiłem podobny problem dla mnie w ASP.NET MVC3.źródło
Jeśli używasz DataContractSerializer dla Xml Formatter lub JSON Formatter, musisz się go pozbyć. Miałem to w moim pliku WebApiConfig:
Po prostu komentuję,
jsonFormatter.UseDataContractJsonSerializer = true;
a mój parametr wejściowy nie jest już pusty. Dzięki „Despertar” za udzielenie mi wskazówki.źródło
Jeśli masz pewność co do wysłanego JSON, musisz dokładnie prześledzić API:
Microsoft.AspNet.WebApi.Tracing
pakietconfig.EnableSystemDiagnosticsTracing();
wWebApiConfig
klasie wewnątrzRegister
metody.Teraz spójrz na wynik debugowania, a prawdopodobnie znajdziesz nieprawidłowy
ModelState
wpis w dzienniku.Jeśli
ModelState
jest nieprawidłowy, prawdziwą przyczynę możesz znaleźć wErrors
:Nikt nawet nie zgadnie takiego wyjątku:
źródło
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.
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.
źródło
JSON.stringify (...) rozwiązał moje problemy
źródło
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:
źródło
Miałem ten sam problem w Fiddler. Mam już
Content-Type: application/json; charset=utf-8
lubContent-Type: application/json
w 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\"}"
.źródło
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:
źródło
[FromBody] object body, [FromHeader(Name="Content-Type")] string bodyMediaType
) może działać lepiej, ponieważ sprawdzaniebodyMediaType == "application.json"
przed rzutowaniem treści na JObject stwarza okazję do alternatyw.Najlepszym rozwiązaniem dla mnie jest przejście na pełny HTTP, jak poniżej:
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
źródło
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.
źródło
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”.
źródło
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:
do#:
źródło
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
źródło
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:
ale twój model c # wygląda następująco:
segregator modelu odrzuci model, a otrzymasz wartość zerową.
źródło
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.
Po stronie klienta za pomocą jQuery
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.
źródło
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.
źródło