Jak przekazać dane JSON POST do metody Web API jako obiekt?
ASP.NET aplikacja MVC4 Web API definiuje metodę post do zapisania klienta. Klient jest przekazywany w formacie json w treści żądania POST. Parametr klienta w metodzie post zawiera wartości null dla właściwości.
Jak to naprawić, aby opublikowane dane były przekazywane jako obiekt klienta ?
If possible Content-Type: application / x-www-form-urlencoded should used since I dont know how to change it in javascript method which posts forma.
Kontroler:
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; }
}
Zapytanie:
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"}
9 answers
Edytuj : 31/10/2017
Ten sam kod / podejście będzie działać dla Asp.Net Core 2.0 również. Główną różnicą jest to, że w asp.net core, zarówno Kontrolery web api, jak i kontrolery Mvc są połączone ze sobą w jeden model kontrolera. Więc twój typ powrotu może być IActionResult
lub jedną z jego implementacji (Ex :OkObjectResult
)
Użycie
contentType:"application/json"
Musisz użyć metody JSON.stringify
, Aby przekonwertować go na łańcuch JSON, gdy go wysyłasz,
A segregator modelowy będzie powiązać dane json z obiektem klasy.
Poniższy kod będzie działał poprawnie (testowany)
$(function () {
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
});
});
Wynik
contentType
property informuje serwer, że wysyłamy dane w formacie JSON. Ponieważ wysłaliśmy strukturę danych JSON, powiązanie modelu stanie się prawidłowe.
Jeśli sprawdzisz nagłówki żądania ajax, zobaczysz, że wartość Content-Type
jest ustawiona jako application/json
.
Jeśli nie podasz jawnie contentType, użyje on domyślny typ zawartości, który jest application/x-www-form-urlencoded;
Edycja na Listopad 2015, aby rozwiązać inne możliwe problemy poruszone w komentarzach
Umieszczanie obiektu złożonego
Załóżmy, że masz złożoną klasę modelu widoku jako parametr metody działania web api, taki jak ten
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;}
}
A twój punkt końcowy API jest jak
public class ProductController : Controller
{
[HttpPost]
public CreateUserViewMode 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;
}
}
W chwili pisania tego tekstu, ASP.NET MVC 6 to najnowsza stabilna wersja, A W MVC6 zarówno sterowniki Web api jak i sterowniki MVC są dziedziczone z Microsoft.AspNet.Mvc.Controller
klasy bazowej.
Aby wysłać dane do metody od strony klienta, poniższy kod powinien działać poprawnie
//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 :)
});
Wiązanie modeli działa dla niektórych właściwości, ale nie dla wszystkich ! Dlaczego ?
Jeśli nie ozdobisz parametru metody web api atrybutem [FromBody]
[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
return m;
}
I wysłać model (surowy obiekt javascript, Nie w formacie JSON) bez podania wartości właściwości contentType
$.ajax({
type: "POST",
data: model,
url: "../product/save"
}).done(function (res) {
console.log('res', res);
});
Oprawa modelarska sprawdzi się w mieszkaniu właściwości w modelu, a nie Właściwości, w których typ jest złożony/inny typ. W naszym przypadku właściwości Id
i Name
będą odpowiednio powiązane z parametrem m
, ale właściwość Tags
będzie pustą listą.
Ten sam problem wystąpi, jeśli używasz skróconej wersji $.post
, która użyje domyślnego typu zawartości podczas wysyłania żądania.
$.post("../product/save", model, function (res) {
//res contains the markup returned by the partial view
console.log('res', res);
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 21:51:49
Praca z postem w webapi może być trudna! Chciałbym dodać do już poprawnej odpowiedzi..
Skupi się na poście, ponieważ radzenie sobie z GETEM jest trywialne. Nie sądzę, aby wielu szukało rozwiązania problemu z GET with webapis. W każdym razie..
Jeśli twoje pytanie dotyczy-w MVC Web Api, jak - - używać niestandardowych nazw metod akcji innych niż ogólne czasowniki HTTP? - Wykonać kilka postów? - Po wielu prostych typów? - Po złożeniu typów poprzez jQuery?
W takim razie pomocne mogą być następujące rozwiązania:
Po pierwsze, aby użyć własnych metod działania W Web API, dodaj trasę web api jako:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}");
}
I wtedy można tworzyć metody akcji takie jak:
[HttpPost]
public string TestMethod([FromBody]string value)
{
return "Hello from http post web api controller: " + value;
}
Teraz odpal poniższy jQuery z konsoli przeglądarki
$.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) }
});
Po drugie, aby wykonać wiele postów , jest to proste, utworzyć wiele metod akcji i udekorować za pomocą [HttpPost] attrib. Użyj [ActionName("MyAction")], aby przypisać własne nazwy, itd. Pojawi się w jQuery w czwartym punkcie poniżej
Po trzecie, po pierwsze, umieszczanie wielu typów prostych w jednej akcji nie jest możliwe. Ponadto istnieje specjalny format do wysyłania nawet pojedynczego prostego typu (poza przekazaniem parametru w łańcuchu zapytania lub stylu REST). To był punkt, który sprawił, że walnąłem się w głowę z Klientami Rest (takimi jak Fiddler i rozszerzenie Advanced Rest client Chrome) i polowałem po Internecie przez prawie 5 godzin kiedy w końcu, poniższy URL okazał się pomocny. Zacytuje odpowiednią treść Dla linku może okazać się martwy!
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: zauważyłeśosobliwą składnię ?
Http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api
W każdym razie, zapomnijmy o tej historii. Idąc dalej:Czwarty, wysyłanie typów złożonych przez jQuery, ofcourse,$.ajax() wkrótce pojawi się w roli:
Niech mówimy, że metoda akcji akceptuje obiekt Person, który ma id i nazwę. Tak, z 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) }
});
A akcja będzie wyglądała następująco:
[HttpPost]
public string TestMethod(Person person)
{
return "Hello from http post web api controller: " + person.Name;
}
[6]}wszystkie powyższe, zadziałały dla mnie!! Zdrowie!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-03 13:59:31
Po prostu bawiłem się tym i odkryłem dość dziwny wynik. Powiedzmy, że masz publiczne właściwości na swojej klasie w C# w ten sposób:
public class Customer
{
public string contact_name;
public string company_name;
}
Więc musisz zrobić JSON.stringify trick zgodnie z sugestią Shyju i nazywaj go tak:
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
});
Jeśli jednak zdefiniujesz gettery i settery na swojej klasie w następujący sposób:
public class Customer
{
public string contact_name { get; set; }
public string company_name { get; set; }
}
Wtedy możesz nazwać to znacznie prościej:
$.ajax({
type: "POST",
data :customer,
url: "api/Customer"
});
Używa nagłówka HTTP:
Content-Type:application/x-www-form-urlencoded
Nie jestem do końca pewien, co tu się dzieje, ale to wygląda jak bug (feature?) w ramach. Prawdopodobnie różne metody wiązania wywołują różne "adaptery" i podczas gdy adapter dla aplikacji/json działa z właściwościami publicznymi, ten dla zakodowanych danych nie działa.]} Nie mam pojęcia, co można by uznać za najlepszą praktykę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-21 15:49:46
Użyj JSON.stringify () aby uzyskać ciąg znaków w formacie JSON, upewnij się, że podczas wykonywania wywołania AJAX przekazujesz niżej wymienione atrybuty:
- contentType: 'application / json'
- dataType: 'json'
Poniżej znajduje się kod give jquery do wywołania ajax post do asp.net web api:
var product =
JSON.stringify({
productGroup: "Fablet",
productId: 1,
productName: "Lumia 1525 64 GB",
sellingPrice: 700
});
$.ajax({
URL: 'http://localhost/api/Products',
type: 'POST',
contentType: 'application/json',
dataType: 'json',
data: product,
success: function (data, status, xhr) {
alert('Success!');
},
error: function (xhr, status, error) {
alert('Update Error occurred - ' + error);
}
});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-02 23:36:29
Upewnij się, że usługa WebAPI oczekuje silnie wpisanego obiektu o strukturze pasującej do JSON, który przekazujesz. I upewnij się, że dodajesz JSON, który publikujesz.
Oto Mój JavaScript (za pomocą AngluarJS):
$scope.updateUserActivity = function (_objuserActivity) {
$http
({
method: 'post',
url: 'your url here',
headers: { 'Content-Type': 'application/json'},
data: JSON.stringify(_objuserActivity)
})
.then(function (response)
{
alert("success");
})
.catch(function (response)
{
alert("failure");
})
.finally(function ()
{
});
A oto mój Kontroler WebAPI:
[HttpPost]
[AcceptVerbs("POST")]
public string POSTMe([FromBody]Models.UserActivity _activity)
{
return "hello";
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-22 16:07:33
Poniższy kod zwraca dane w formacie json, zamiast XML-Web API 2 :-
Umieść następującą linię w globalnym.plik asax
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-22 09:19:54
@model MVCClient.Models.ProductDetails
@{
ViewBag.Title = "ProductDetails";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("#Save").click(function () {
var ProductDetails = new Object();
ProductDetails.ProductName = $("#txt_productName").val();
ProductDetails.ProductDetail = $("#txt_desc").val();
ProductDetails.Price= $("#txt_price").val();
$.ajax({
url: "http://localhost:24481/api/Product/addProduct",
type: "Post",
dataType:'JSON',
data:ProductDetails,
success: function (data) {
alert('Updated Successfully');
//window.location.href = "../Index";
},
error: function (msg) { alert(msg); }
});
});
});
</script>
<h2>ProductDetails</h2>
<form id="form1" method="post">
<fieldset>
<legend>ProductDetails</legend>
<div class="editor-label">
@Html.LabelFor(model => model.ProductName)
</div>
<div class="editor-field">
<input id="txt_productName" type="text" name="fname">
@Html.ValidationMessageFor(model => model.ProductName)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.ProductDetail)
</div>
<div class="editor-field">
<input id="txt_desc" type="text" name="fname">
@Html.ValidationMessageFor(model => model.ProductDetail)
</div>
<div class="editor-label">
@Html.LabelFor(model => model.Price)
</div>
<div class="editor-field">
<input id="txt_price" type="text" name="fname">
@Html.ValidationMessageFor(model => model.Price)
</div>
<p>
<input id="Save" type="button" value="Create" />
</p>
</fieldset>
</form>
<div>
@Html.ActionLink("Back to List", "Index")
</div>
</form>
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-07 13:03:23
Microsoft dał dobry przykład:
Https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-1
Najpierw Zatwierdź żądanie
if (ModelState.IsValid)
A następnie użyć danych seryjnych.
Content = new StringContent(update.Status)
Tutaj 'Status' jest polem typu complex. Serializacja jest wykonywana przez. Net, nie musisz się o to martwić.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-22 13:51:07
1) Po stronie klienta możesz wysłać http.post request in string like below
var IndexInfo = JSON.stringify(this.scope.IndexTree);
this.$http.post('../../../api/EvaluationProcess/InsertEvaluationProcessInputType', "'" + IndexInfo + "'" ).then((response: any) => {}
2) Następnie w kontrolerze web api możesz go deserializować
public ApiResponce InsertEvaluationProcessInputType([FromBody]string IndexInfo)
{
var des = (ApiReceivedListOfObjects<TempDistributedIndex>)Newtonsoft.Json.JsonConvert.DeserializeObject(DecryptedProcessInfo, typeof(ApiReceivedListOfObjects<TempDistributedIndex>));}
3) twoja klasa ApiReceivedListOfObjects powinna być taka jak poniżej
public class ApiReceivedListOfObjects<T>
{
public List<T> element { get; set; }
}
4)Upewnij się, że Twój serializowany łańcuch znaków (IndexInfo tutaj) będzie podobny do poniższej struktury przed JsonConvert.Polecenie DeserializeObject w Kroku 2
var resp = @"
{
""element"": [
{
""A"": ""A Jones"",
""B"": ""500015763""
},
{
""A"": ""B Smith"",
""B"": ""504986213""
},
{
""A"": ""C Brown"",
""B"": ""509034361""
}
]
}";
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-04 12:37:49