ASP.NET MVC4 Web API -sovellus määrittelee post-menetelmän asiakkaan tallentamiseksi. Asiakas välitetään json-muodossa POST-pyynnön rungossa. Asiakas-parametri post-metodissa sisältää nolla-arvoja ominaisuuksille.
Miten tämä korjataan niin, että lähetetyt tiedot välitetään asiakasobjektina?
Jos mahdollista, Content-Type: application/x-www-form-urlencoded olisi käytettävä, koska en tiedä, miten muuttaa sitä Javascript-menetelmässä, joka lähettää lomakkeen.
Controller:
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; }
}
Pyyntö:
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"}
EDIT : 31/10/2017
Sama koodi/lähestymistapa toimii myös Asp.Net Core 2.0:ssa. Merkittävä ero on, asp.net core, sekä web api ohjaimet ja Mvc ohjaimet on yhdistetty yhteen ohjainmalliin. Joten paluutyyppisi voi olla IActionResult
tai jokin sen toteutus (Esim :OkObjectResult
).
Käytä
contentType:"application/json"
Sinun on käytettävä JSON.stringify
-menetelmää muuntamaan se JSON-merkkijonoksi, kun lähetät sen,
Ja mallin sidonta sitoo json-tiedot luokkasi objektiin.
Alla oleva koodi toimii hyvin (testattu)
$(function () {
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
});
});
Tulos
contentType
-ominaisuus kertoo palvelimelle, että lähetämme tiedot JSON-muodossa. Koska lähetimme JSON-tietorakenteen, mallin sitominen tapahtuu oikein.
Jos tarkastelet ajax-pyynnön otsikoita, näet, että Content-Type
-arvoksi on asetettu application/json
.
Jos et määritä contentTypea nimenomaisesti, se käyttää oletussisältötyyppiä, joka on application/x-www-form-urlencoded;
.
Muutettu marraskuussa 2015 muiden kommenteissa esiin tulleiden mahdollisten ongelmien käsittelemiseksi.
Sanotaan, että sinulla on monimutkainen näkymämalli-luokka web api -toimintametodin parametrina näin ollen.
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;}
}
ja web api:n päätepisteesi on seuraavanlainen
public class ProductController : Controller
{
[HttpPost]
public CreateUserViewModel 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;
}
}
Tätä kirjoitettaessa ASP.NET MVC 6 on viimeisin vakaa versio ja MVC6:ssa sekä Web api -ohjaimet että MVC-ohjaimet periytyvät Microsoft.AspNet.Mvc.Controller
-perusluokasta.
Jos haluat lähettää tietoja menetelmään asiakkaan puolelta, alla olevan koodin pitäisi toimia hyvin.
//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 :)
});
Jos et koristele web api -menetelmän parametria [FromBody]
-attribuutilla.
[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
return m;
}
Ja lähetät mallin (raaka javascript-objekti, ei JSON-muodossa) määrittelemättä contentType-ominaisuuden arvoa.
$.ajax({
type: "POST",
data: model,
url: "../product/save"
}).done(function (res) {
console.log('res', res);
});
Mallin sitominen toimii mallin tasomaisille ominaisuuksille, ei ominaisuuksille, joiden tyyppi on monimutkainen/muu tyyppi. Meidän tapauksessamme Id
- ja Name
-ominaisuudet sidotaan asianmukaisesti parametriin m
, mutta Tags
-ominaisuus on tyhjä luettelo.
Sama ongelma ilmenee, jos käytät lyhyttä versiota $.post
, joka käyttää oletusarvoista Content-Type-tyyppiä pyyntöä lähetettäessä.
$.post("../product/save", model, function (res) {
//res contains the markup returned by the partial view
console.log('res', res);
});
POSTin käyttäminen webapissa voi olla hankalaa! Haluaisin lisätä jo oikean vastauksen...
Keskitytään erityisesti POSTiin, koska GETin käsittely on triviaalia. En usko, että monet etsisivät GET-ongelman ratkaisemista webapin avulla. Joka tapauksessa...
Jos kysymyksesi on - MVC Web Api, miten - - Käytä mukautettuja toimintamenetelmän nimiä muut kuin yleiset HTTP-verbit? - Suorittaa useita viestejä? - Postittaa useita yksinkertaisia tyyppejä? - lähettää monimutkaisia tyyppejä jQueryn avulla?
Seuraavat ratkaisut voivat auttaa:
Ensinnäkin, jos haluat käyttää Custom Action Methods -menetelmiä Web API:ssa, lisää web api -reitti seuraavasti:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}");
}
Ja sitten voit luoda toimintametodeja kuten:
[HttpPost]
public string TestMethod([FromBody]string value)
{
return "Hello from http post web api controller: " + value;
}
Nyt, laukaise seuraava jQuery selaimen konsolista
$.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) }
});
Toiseksi, suorittaa useita viestejä, Se on yksinkertaista, luoda useita toimintamenetelmiä ja koristella [HttpPost]-attribuutilla. Käytä [ActionName("MyAction")] määrittääksesi mukautettuja nimiä jne. Tulla jQuery neljännen kohdan alla.
Kolmanneksi, Ensinnäkin, useiden SIMPLE-tyyppien lähettäminen yhdessä toiminnossa ei ole mahdollista. Lisäksi on olemassa erikoismuoto jopa yksittäisen yksinkertaisen tyypin lähettämiseen (sen lisäksi, että parametri välitetään kyselymerkkijonossa tai REST-tyyliin). Tämä oli kohta, joka sai minut hakkaamaan päätäni Rest Clients -ohjelmilla (kuten Fiddler ja Chrome's Advanced REST client extension) ja metsästämään ympäri Internetiä lähes 5 tuntia, kun lopulta seuraava URL-osoite osoittautui hyödylliseksi. Lainaan asiaankuuluvan sisällön, sillä linkki saattaa muuttua kuolleeksi!
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: Huomasitko erityisen syntaksin?
http://forums.asp.net/t/1883467.aspx?The+vastaanotettu+arvo+on+tyhjä+jos+yritän+lähettää+postia+verkkopalveluun.
Joka tapauksessa, päästäänpä tuon tarinan yli. Jatketaan eteenpäin:
Neljänneksi, monimutkaisten tyyppien lähettäminen jQueryn kautta, tietenkin $.ajax() tulee välittömästi rooliin:
Sanotaan, että toimintamenetelmä hyväksyy Person-olion, jolla on id ja nimi. Joten javascriptistä:
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) }
});
Ja toiminto näyttää seuraavalta:
[HttpPost]
public string TestMethod(Person person)
{
return "Hello from http post web api controller: " + person.Name;
}
Kaikki edellä mainitut asiat toimivat minulle!!! Kippis!
Olen juuri leikkinyt tämän kanssa ja havainnut melko oudon tuloksen. Sanotaan, että sinulla on julkisia ominaisuuksia luokassasi C#:ssa näin:
public class Customer
{
public string contact_name;
public string company_name;
}
niin sinun täytyy tehdä Shyjun ehdottama JSON.stringify-temppu ja kutsua sitä näin:
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
});
Jos kuitenkin määrittelet getterit ja setterit luokallesi näin:
public class Customer
{
public string contact_name { get; set; }
public string company_name { get; set; }
}
niin voit kutsua sitä paljon yksinkertaisemmin:
$.ajax({
type: "POST",
data :customer,
url: "api/Customer"
});
Tämä käyttää HTTP-otsikkoa:
Content-Type:application/x-www-form-urlencoded
En ole aivan varma, mitä tässä tapahtuu, mutta näyttää siltä, että kyseessä on virhe (ominaisuus?) kehyksessä. Oletettavasti eri sidontamenetelmät kutsuvat eri "sovittimia", ja vaikka application/json-sovitin toimii julkisten ominaisuuksien kanssa, lomakkeella koodattujen tietojen sovitin ei toimi.
Minulla ei kuitenkaan ole aavistustakaan, kumpi olisi paras käytäntö.