Hacemos una verificación completa cada enunciado de nuestra página web con el objetivo de mostrarte en todo momento la información más veraz y actual.
Solución:
EDITAR : 31/10/2017
El mismo código / enfoque funcionará para Asp.Net Core 2.0 así como. La principal diferencia es que, en el núcleo de asp.net, tanto los controladores web api como los controladores Mvc se fusionan en un modelo de controlador único. Entonces su tipo de retorno podría ser IActionResult
o una de sus implementaciones (Ej:OkObjectResult
)
Usar
contentType:"application/json"
Necesitas usar JSON.stringify
método para convertirlo a JSON string Cuando lo envíes,
Y el enlazador de modelos vinculará los datos json a su objeto de clase.
El siguiente código funcionará bien (probado)
$(function ()
var customer = contact_name :"Scott",company_name:"HP";
$.ajax(
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
);
);
Resultado
contentType
La propiedad le dice al servidor que estamos enviando los datos en formato JSON. Dado que enviamos una estructura de datos JSON, la vinculación del modelo se realizará correctamente.
Si inspecciona los encabezados de la solicitud ajax, puede ver que el Content-Type
el valor se establece como application/json
.
Si no especifica contentType explícitamente, utilizará el tipo de contenido predeterminado que es application/x-www-form-urlencoded;
Edite en noviembre de 2015 para abordar otros posibles problemas planteados en los comentarios
Publicar un objeto complejo
Digamos que tiene una clase de modelo de vista compleja como parámetro del método de acción de la API web como este
public class CreateUserViewModel
public int Id set;get;
public string Name set;get;
public List Tags set;get;
public class TagViewModel
public int Id set;get;
public string Code set;get;
y su punto final de API web es como
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;
En el momento de escribir este artículo, ASP.NET MVC 6 es la última versión estable y en MVC6, tanto los controladores de API web como los controladores MVC heredan de Microsoft.AspNet.Mvc.Controller
clase base.
Para enviar datos al método desde el lado del cliente, el siguiente código debería funcionar bien
//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 :)
);
El enlace de modelo funciona para algunas propiedades, ¡pero no para todas! Por qué ?
Si no decora el parámetro del método web api con [FromBody]
attribute
[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
return m;
Y envíe el modelo (objeto javascript sin formato, no en formato JSON) sin especificar el valor de la propiedad contentType
$.ajax(
type: "POST",
data: model,
url: "../product/save"
).done(function (res)
console.log('res', res);
);
El enlace de modelo funcionará para las propiedades planas del modelo, no para las propiedades en las que el tipo es complejo / otro tipo. En nuestro caso, Id
y Name
las propiedades se vincularán correctamente al parámetro m
, Pero el Tags
La propiedad será una lista vacía.
El mismo problema ocurrirá si está utilizando la versión corta, $.post
que utilizará el tipo de contenido predeterminado al enviar la solicitud.
$.post("../product/save", model, function (res)
//res contains the markup returned by the partial view
console.log('res', res);
);
¡Trabajar con POST en webapi puede ser complicado! Me gustaría agregar algo a la respuesta ya correcta.
Se centrará específicamente en POST, ya que tratar con GET es trivial. No creo que muchos busquen resolver un problema con GET con webapis. De todos modos..
Si su pregunta es: en MVC Web Api, cómo: – ¿Usar nombres de métodos de acción personalizados que no sean los verbos HTTP genéricos? – ¿Realizar múltiples publicaciones? – ¿Publicar varios tipos simples? – ¿Publicar tipos complejos a través de jQuery?
Entonces las siguientes soluciones pueden ayudar:
Primero, usar Personalizado Métodos de acción en la API web, agregue una ruta de la API web como:
public static void Register(HttpConfiguration config)
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/controller/action");
Y luego puede crear métodos de acción como:
[HttpPost]
public string TestMethod([FromBody]string value)
return "Hello from http post web api controller: " + value;
Ahora, active el siguiente jQuery desde la consola de su navegador
$.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)
);
Segundo, para realizar múltiples publicaciones, Es simple, crea múltiples métodos de acción y decora con el [HttpPost] attrib. Utilizar el [ActionName(“MyAction”)] para asignar nombres personalizados, etc. Llegará a jQuery en el cuarto punto a continuación
En tercer lugar, en primer lugar, publicar varios SENCILLO tipos en una sola acción no es posible. Además, hay una formato especial para publicar incluso un solo tipo simple (además de pasar el parámetro en la consulta string o estilo REST). Este fue el punto que me hizo golpearme la cabeza con Rest Clients (como Fiddler y la extensión de cliente REST avanzada de Chrome) y buscar en la web durante casi 5 horas cuando, finalmente, la siguiente URL resultó ser de ayuda. ¡Citará el contenido relevante para el enlace que podría volverse muerto!
Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
="Name":"Turbo Tina","Email":"[email protected]
"
PD: Noté el sintaxis peculiar?
http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+ cuando + intento + publicar + en + mi + API + web
De todos modos, superemos esa historia. Hacia adelante:
Cuatro, publicar tipos complejos a través de jQuery, por supuesto, $ .ajax () pronto asumirá el rol:
Digamos que el método de acción acepta un objeto Person que tiene una identificación y un nombre. Entonces, desde 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)
);
Y la acción se verá así:
[HttpPost]
public string TestMethod(Person person)
return "Hello from http post web api controller: " + person.Name;
¡Todo lo anterior funcionó para mí! ¡Salud!
Acabo de jugar con esto y descubrí un resultado bastante extraño. Digamos que tiene propiedades públicas en su clase en C # como esta:
public class Customer
public string contact_name;
public string company_name;
entonces debes hacer el truco JSON.stringify como lo sugiere Shyju y llamarlo así:
var customer = contact_name :"Scott",company_name:"HP";
$.ajax(
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
);
Sin embargo, si define getters y setters en su clase de esta manera:
public class Customer
public string contact_name get; set;
public string company_name get; set;
entonces puedes llamarlo mucho más simplemente:
$.ajax(
type: "POST",
data :customer,
url: "api/Customer"
);
Esto usa el encabezado HTTP:
Content-Type:application/x-www-form-urlencoded
No estoy muy seguro de lo que está sucediendo aquí, pero parece un error (¿característica?) En el marco. Es de suponer que los diferentes métodos de enlace están llamando a diferentes “adaptadores”, y mientras que el adaptador para la aplicación / json uno funciona con propiedades públicas, el de los datos codificados por formulario no lo hace.
Sin embargo, no tengo idea de cuál sería la mejor práctica.