Desde que actualicé a RC para WebAPI, tengo un problema realmente extraño cuando llamo a POST en mi WebAPI. Incluso he vuelto a la versión básica generada en un nuevo proyecto. Entonces:
public void Post(string value)
{
}
y llamando desde Fiddler:
Header:
User-Agent: Fiddler
Host: localhost:60725
Content-Type: application/json
Content-Length: 29
Body:
{
"value": "test"
}
Cuando depuro, la cadena "valor" nunca se asigna a. Siempre es NULL. ¿Alguien tiene este problema?
(Primero vi el problema con un tipo más complejo)
El problema no solo está vinculado a ASP.NET MVC 4, el mismo problema ocurre para un nuevo proyecto ASP.NET MVC 3 después de la instalación de RC
c#
.net
asp.net-web-api
asp.net-web-api-routing
ianrathbone
fuente
fuente
Respuestas:
Como solo tiene un parámetro, puede intentar decorarlo con el
[FromBody]
atributo o cambiar el método para aceptar un DTO con valor como propiedad, como sugerí aquí: enlace de parámetro MVC4 RC WebApiACTUALIZACIÓN: El sitio oficial de ASP.NET se actualizó hoy con una excelente explicación: https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part- 1
En pocas palabras, al enviar un solo tipo simple en el cuerpo, envíe solo el valor prefijado con un signo igual (=), por ejemplo, cuerpo:
=test
fuente
=
en el frente nunca funcionó para mí, hasta que seguí el consejo de Jim en su comentario (no como un objeto JSON) y funcionó. Esta es la clave! Realmente no me gusta lo exigente que es WebAPI.:(
). Realmente debería agregar soporte para el formato que la gente espera que acepte.Me he estado rascando la cabeza por esto hoy.
Mi solución es cambiar el
[FromBody]
a unHttpRequestMessage
, esencialmente subiendo la pila HTTP.En mi caso, estoy enviando datos a través del cable que está comprimido json que luego es base64'd. Todo esto desde una aplicación de Android.
La firma original de mi punto final web se veía así (usando
[FromBody]
):Mi solución para este problema fue volver a usar a
HttpRequestMessage
para la firma de mi punto final.Luego puede obtener acceso a los datos de publicación utilizando esta línea de código:
Esto funciona y le permite acceder a los datos de publicación sin tocar sin procesar. No tiene que perder el tiempo con Fiddler poniendo un signo = al comienzo de su cadena o cambiando el tipo de contenido.
Como comentario aparte, primero intenté seguir una de las respuestas anteriores, que era cambiar el tipo de contenido a: "Content-Type: application / x-www-form-urlencoded". Para los datos sin procesar, este es un mal consejo porque elimina los caracteres +.
Entonces, una cadena base64 que comienza así: "MQ0AAB + LCAAAAAA" termina así "MQ0AAB LCAAAAAA". No es lo que quieres.
Otro beneficio del uso
HttpRequestMessage
es que obtiene acceso a todos los encabezados http desde su punto final.fuente
HttpRequestMessage request
firma del método, ya que siempre tiene esto. En el cuerpo del método se puede acceder en elRequest
objeto. por ejemploRequest.Content.ReadAsStringAsync().Result;
Acabo de hacer que esto ocurra usando Fiddler. El problema era que no había especificado
Content-Type
.Intente incluir un encabezado para
Content-Type
en su solicitud POST.Alternativamente, según los comentarios a continuación, es posible que deba incluir un encabezado JSON
fuente
contentType: "application/x-www-form-urlencoded; charset=UTF-8"
, para ver un ejemplo completo, vea Completo cliente y servidorTambién me encontré con este problema, y así es como lo resolví.
código webapi:
codigo del cliente:
fuente
some value
, entoncesdata
es nulo.Estaba usando
Postman
y estaba cometiendo el mismo error ... pasando elvalue
objeto como json en lugar de cadenaClaramente el anterior está mal cuando el parámetro api es de tipo cadena.
Entonces, simplemente pase la cadena entre comillas dobles en el cuerpo de la API:
fuente
JSON.stringify
estaba causando que mi[frombody]
sernull
. Después de configurar el campo de datos en un valor de cadena (que es una cadena json) funcionó.Intente crear una clase para que sirva como modelo de datos, luego envíe un objeto JSON con propiedades que coincidan con las propiedades de su clase de modelo de datos. (Nota: he probado esto y funciona con el MVC 4 RC 2012 más reciente que acabo de descargar hoy).
El siguiente objeto JSON se envía en el cuerpo HTTP-POST, el tipo de contenido es application / json
Creo que la razón por la que debe crear una clase de modelo de datos es porque se supone que los valores simples provienen de los parámetros de url, y se supone que un solo valor complejo proviene del cuerpo. Ellos tienen el
[FromBody]
[FromUrl]
atributos y , pero usando[FromBody] string value
aún no funcionó para mí. Parece que todavía están resolviendo muchos errores, así que estoy seguro de que esto cambiará en el futuro.Editar: Tengo XML para trabajar en el cuerpo. El serializador XML predeterminado se cambió a DataContractSerializer en lugar de XmlSerializer. Poner la siguiente línea en mi archivo Global.asax solucionó este problema ( referencia )
fuente
Después de algunos intentos, creo que el comportamiento predeterminado es correcto y no hay nada que piratear.
El único truco es: si el argumento de su método de publicación es el
string
siguiente, debe enviar una cadena simple con comillas dobles en el cuerpo (cuando usa ajax o cartero), por ejemplo,De lo contrario, si envía una cadena json en el cuerpo de la publicación sin comillas dobles externas y comillas internas escapadas, entonces debería poder analizarse en la clase de modelo (el tipo de argumento), por ejemplo,
{"a":1, "b":2}
fuente
Estaba buscando una solución a este problema durante algunos minutos, así que compartiré mi solución.
Si publica un modelo, su modelo debe tener un constructor vacío / predeterminado, de lo contrario, el modelo no se puede crear, obviamente. Tenga cuidado al refactorizar. ;)
fuente
Esto funcionó para mí:
Cree una clase C # DTO, con una propiedad para cada atributo que desee pasar de jQuery / Ajax
Defina el método de la API web:
Llame a la API web como tal:
fuente
Para aquellos que tienen el mismo problema con Swagger o Postman como yo, si está pasando un atributo simple como cadena en una publicación, incluso con el "ContentType" especificado, aún obtendrá un valor nulo.
Pasando solo:
MyValue
Entrará en el controlador como nulo.
Pero si pasas:
"MyValue"
El valor será correcto.
Las citas hicieron la diferencia aquí. Por supuesto, esto es solo para Swagger y Postman. Por ejemplo, en una aplicación Frontend que usa Angular, el marco debería resolverlo automáticamente.
fuente
Tuve el mismo problema y descubrí que al cambiar el Tipo de contenido a "application / json" no solucionó el problema. Sin embargo, "application / json; charset = utf-8" funcionó.
fuente
Tuve un problema similar en el que el objeto de solicitud para mi método de API web siempre era nulo. Noté que, dado que el nombre de la acción del controlador tenía el prefijo "Get", la API web trató esto como un HTTP GET en lugar de un POST. Después de cambiar el nombre de la acción del controlador, ahora funciona según lo previsto.
fuente
Con Angular, pude pasar datos en este formato:
Y en Web API Controler:
Alternativamente, también podría publicar datos JSON como este:
Y, en el controlador, acepte un tipo de clase como este:
De cualquier manera funciona, si tiene una clase pública establecida en la API, publique JSON, de lo contrario, publique '=' + JSON.stringify ({..: ..., ..: ...})
fuente
En mi caso, el problema era que el parámetro era una cadena y no un objeto, cambié el parámetro para que fuera JObject de Newsoft.Json y funciona.
fuente
Agregar línea
hasta el final de la función
protected void Application_Start()
en Global.asax.cs solucionó un problema similar para mí en ASP.NET MVC3.fuente
Si está utilizando un DataContractSerializer para su formateador Xml o JSON, debe deshacerse de él. Tenía esto en mi archivo WebApiConfig:
Simplemente comento
jsonFormatter.UseDataContractJsonSerializer = true;
y mi parámetro de entrada ya no es nulo. Gracias a 'Despertar' por darme una pista.fuente
Si está seguro acerca de su JSON enviado, debe rastrear su API con cuidado:
Microsoft.AspNet.WebApi.Tracing
paqueteconfig.EnableSystemDiagnosticsTracing();
en laWebApiConfig
clase dentroRegister
método.Ahora mire la salida de depuración y probablemente encontrará un inválido
ModelState
entrada de registro .Si
ModelState
no es válido, puede encontrar la verdadera causa en suErrors
:Nadie puede adivinar tal excepción:
fuente
Tuve el mismo problema de obtener un valor nulo como parámetro, pero estaba relacionado con objetos grandes. Resultó que el problema estaba relacionado con la longitud máxima de IIS. Se puede configurar en web.config.
Me pregunto por qué la API web eliminó el error y envía objetos nulos a mis API. Encontré el error usando Microsoft.AspNet.WebApi.Tracing.
fuente
JSON.stringify (...) resolvió mis problemas
fuente
Sé que esta no es una respuesta a esta pregunta, pero la encontré cuando buscaba una solución a mi problema.
En mi caso, el tipo complejo no estaba vinculado pero no estaba haciendo una POST, estaba haciendo un GET con parámetros de cadena de consulta. La solución fue agregar [FromUri] al argumento:
fuente
Tuve el mismo problema en Fiddler. Ya tenía
Content-Type: application/json; charset=utf-8
oContent-Type: application/json
en el encabezado de la solicitud.Mi solicitud cuerpo era también una cadena sencilla, y en Fiddler me había escrito:
{'controller':'ctrl'}
. Esto hizo que el parámetro de cadena en mi método POST seanull
.Solución : recuerde utilizar comillas, lo que indica una cadena. Es decir, lo arreglé escribiendo
"{'controller':'ctrl'}"
. (Nota: cuando escriba JSON, asegúrese de usar apóstrofes o escape de las comillas como esta:)"{\"controller\":\"ctrl\"}"
.fuente
La forma más simple que encontré para tratar con un objeto JSON simple que paso a MVC 6 es obtener el tipo del parámetro de publicación como NewtonSoft jObject:
fuente
[FromBody] object body, [FromHeader(Name="Content-Type")] string bodyMediaType
) podría funcionar mejor ya que la comprobaciónbodyMediaType == "application.json"
antes de enviar el cuerpo a JObject ofrece una oportunidad para alternativas.La mejor solución para mí es HTTP completo como se muestra a continuación:
y luego deserializar la cadena al objeto que espera en el cuerpo de la publicación. Para mí, WS_OpenSession es una clase que contenía sessionid, usuario y clave.
Desde allí puede usar el objeto param y acceder a sus propiedades.
Muy muy efectivo.
Dije que proviene de esta url:
http://bizcoder.com/posting-raw-json-to-web-api
fuente
Para los tipos complejos, la API web intenta leer el valor del cuerpo del mensaje, utilizando un formateador de tipo multimedia.
Por favor, compruebe si tiene alguna
[Serializable]
atributo que decore su clase de modelo.Elimine el atributo para ver si funciona. Esto funcionó para mí.
fuente
Llego un poco tarde a la fiesta, pero cualquiera que tropiece con un valor NULL pasado cuando usa un controlador simplemente agrega "=" al frente de su solicitud POST.
El controlador también pasó un valor NULL cuando usé la aplicación / json Content-Type. Observe el tipo de contenido "application / x-www-form-urlencoded" a continuación. Sin embargo, el tipo de retorno de la API es "application / json".
fuente
no importa qué tipo de valor desee publicar, solo enciérrelo entre comillas, para obtenerlo como una cadena. No para tipos complejos.
javascript:
C#:
fuente
Si coloca la anotación [FromBody] y tiene un objeto Dto como parámetro para su método y aún no puede obtener los datos, comience a buscar en las propiedades y campos de su DTO.
Tuve este mismo problema, donde mi DTO se estaba volviendo nulo. Descubrí que la razón era que una de las propiedades apuntaba a un objeto que no se puede serializar :( lo que hace que el formateador de medios no pueda analizar los datos. Por lo tanto, el objeto siempre fue nulo. Espero que ayude a otros también
fuente
Verifique sus tipos de datos. La carpeta del modelo dotnet no convertirá un flotante en un entero (y supongo que otros conceptos relacionados). Esto hará que todo el modelo sea rechazado.
Si tienes json así:
pero su modelo de C # se ve así:
la carpeta modelo rechazará el modelo y obtendrá nulo.
fuente
Llegué bastante tarde a esto, pero tuve problemas similares y después de un día de analizar muchas de las respuestas aquí y obtener antecedentes, encontré la solución más fácil / liviana para transferir uno o más parámetros a una API Web 2 La acción es como sigue:
Esto supone que usted sabe cómo configurar un controlador / acción de API web con el enrutamiento correcto, si no, consulte: https://docs.microsoft.com/en-us/aspnet/web-api/overview/getting-started-with -aspnet-web-api / tutorial-your-first-web-api .
Primero la Acción del controlador, esta solución también requiere la biblioteca Newtonsoft.Json.
Lado del cliente usando jQuery
El problema clave que encontré fue asegurarme de que solo envíe un único parámetro general de vuelta a la API web y asegúrese de que no tenga un nombre, solo el valor; de lo
{ '': dataToSend }
contrario, su valor será nulo en el lado del servidor.Con esto, puede enviar uno o varios parámetros a la API web en una estructura JSON y no necesita declarar ningún objeto adicional del lado del servidor para manejar datos complejos. JObject también le permite iterar dinámicamente sobre todos los parámetros pasados permitiendo una escalabilidad más fácil si sus parámetros cambian con el tiempo. Espero que eso ayude a alguien que estaba luchando como yo.
fuente
El paso correcto de un solo parámetro en el cuerpo a WebAPI funciona con este código
$.post(url, { '': productId }
Y atraparlo en acción
[HttpPost] public ShoppingCartAddRemoveViewModel Delete([FromBody]string value)
La clave es usar la palabra mágica 'valor'. También puede ser int, o algún tipo primitivo. No importa el tipo de contenido o las correcciones de encabezado, Mess es que este código no funciona en la acción posterior de mvc.
fuente