El parámetro de publicación siempre es nulo

197

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

ianrathbone
fuente
Solo para agregar al problema: no es exclusivo de JSON, también sucede con XML.
ianrathbone
3
He estado luchando con esto durante dos días y después de leer cada artículo que pude encontrar al respecto, resultó ser tan simple como formatear la cadena JSON correctamente en WebRequest: los datos deben comenzar y terminar con comillas dobles y si luego use comillas simples a lo largo de sus datos json, todo funciona bien.
Gineer

Respuestas:

101

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 WebApi

ACTUALIZACIÓ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

Jim Harte
fuente
9
Le di un giro a [FromBody] pero no hubo cambios
ianrathbone
11
Pase solo el valor (es decir, no como un objeto JSON) y debería funcionar, de acuerdo con blogs.msdn.com/b/jmstall/archive/2012/04/16/…
Jim Harte
8
El apéndice =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.
gitsitgo
16
Esto es tan estúpido y molesto que no sé si votar a favor o en contra la respuesta que me ayudó a resolver mi problema ... ¿Por qué demonios tiene que estar en este formato? (Perdón por la actitud, solo perdí demasiado tiempo en esto, y no tiene ningún sentido ... :(). Realmente debería agregar soporte para el formato que la gente espera que acepte.
Gdoron está apoyando a Mónica
66
¡Gracias! ¿Cómo deberíamos saber que tenemos que eliminar el nombre del parámetro cuando enviamos solo un parámetro? ¿A qué cerebro de pájaro se le ocurrió esta idea?
Jenny O'Reilly
104

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]):

My original endpoint

Mi solución para este problema fue volver a usar a HttpRequestMessagepara la firma de mi punto final.

enter image description here

Luego puede obtener acceso a los datos de publicación utilizando esta línea de código:

enter image description here

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 HttpRequestMessagees que obtiene acceso a todos los encabezados http desde su punto final.

Lanzamiento aéreo del océano
fuente
66
Excelente solución ... me llevó 9 horas encontrar esto, solucioné mi problema después de eliminar el valor de cadena [FromBody] y lo sustituí con HttpRequestMessage
Kev
1
¡Funciona de maravilla! pero ¿no hay una manera de usar un tipo de parámetro real de un determinado objeto? por ejemplo, parámetro de tipo Order para un método de API web?
Ron Nuni
77
Solo una nota al margen, no NECESITA la HttpRequestMessage requestfirma del método, ya que siempre tiene esto. En el cuerpo del método se puede acceder en el Requestobjeto. por ejemploRequest.Content.ReadAsStringAsync().Result;
Morvael el
Por lo general, este problema se debe a que su objeto JSON es incorrecto. He encontrado que esto siempre se debe a que en el constructor tiene un tipo no válido y Json no sabe cómo convertirlo 'Como un Guid en una cadena. Entonces, agregue el convertidor a través de la configuración o agregue un constructor en blanco y no necesita volver al código antiguo como este.
Nick Turner
La forma más fácil es cambiar el objeto a una cadena y luego intentar convertirlo y verá el error JSON. Comprueba también tus encabezados.
Nick Turner
71

Acabo de hacer que esto ocurra usando Fiddler. El problema era que no había especificadoContent-Type .

Intente incluir un encabezado para Content-Typeen su solicitud POST.

Content-Type: application/x-www-form-urlencoded

Alternativamente, según los comentarios a continuación, es posible que deba incluir un encabezado JSON

Content-Type: application/json
Kirk Broadhurst
fuente
11
Tuve un problema similar, excepto que necesitaba configurar Content-Type: application / json
dvallejo
2
Como se especifica en la publicación, ya había agregado Content-Type: application / json
ianrathbone el
2
application / x-www-form-urlencoded no funcionó para mí, Content-Type: application / json sí.
liang
1
Independientemente del tipo de contenido, si solo tiene un parámetro, debe enviar solo el valor sin el nombre del parámetro en el cuerpo de la solicitud. Entonces id = 13 no funcionará. Necesitas enviar 13 solo. Ver la respuesta de Jim.
Jenny O'Reilly
Tuve que usar contentType: "application/x-www-form-urlencoded; charset=UTF-8", para ver un ejemplo completo, vea Completo cliente y servidor
RyBolt el
57

También me encontré con este problema, y ​​así es como lo resolví.

código webapi:

public void Post([FromBody] dynamic data)
{
    string value = data.value;
    /* do stuff */
}

codigo del cliente:

$.post( "webapi/address", { value: "some value" } );
Jorge
fuente
1
Esto funciona si el cliente está enviando JSON. Si estoy enviando un valor simple como la cadena some value, entonces dataes nulo.
brianestey
fácil, cambie su código de cliente para devolver un objeto js.
George
Manera genial y limpia de obtener datos de JSON
Wouter Vanherck
Si está enviando json, entonces var json = JsonConvert.SerializeObject (data);
dvallejo
41

Estaba usando Postmany estaba cometiendo el mismo error ... pasando el valueobjeto como json en lugar de cadena

{
    "value": "test"
}

Claramente 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:

"test"
JerryGoyal
fuente
2
Este era mi problema, y ​​probablemente la solución real a la pregunta. Cadena codificada JSON-A tiene cotizaciones
Kyle W
1
También encontré este problema en Postman. Resulta que elegí erróneamente "datos de formulario" en lugar de "sin formato" para Body cuando Content-Type está configurado como application / json. Puede consultar las capturas de pantalla de zzyykk123456 en Issues of aspnet Github: github.com/aspnet/Home/issues/2202
Chun Lin
Esto funcionó para mí. Usando Swagger (swashbuckle) tengo que configurar el Tipo de contenido: application / json y usar comillas dobles.
John Henckel
1
Exactamente mi problema, pero tengo que tener en cuenta que en las solicitudes de Ajax debe hacer 'datos: JSON.stringify ("YourString")'
Amir Hossein Ahmadi
1
@AmirHosseinAhmadi Acabo de encontrar esto en ajax y vi que el uso real JSON.stringifyestaba causando que mi [frombody]ser null. Después de configurar el campo de datos en un valor de cadena (que es una cadena json) funcionó.
Nexaspx
19

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).

public HttpResponseMessage Post(ValueModel model)
{
    return Request.CreateResponse<string>(HttpStatusCode.OK, "Value Recieved: " + model.Value);
}

public class ValueModel
{
    public string Value { get; set; }
}

El siguiente objeto JSON se envía en el cuerpo HTTP-POST, el tipo de contenido es application / json

{ "value": "In MVC4 Beta you could map to simple types like string, but testing with RC 2012 I have only been able to map to DataModels and only JSON (application/json) and url-encoded (application/x-www-form-urlencoded body formats have worked. XML is not working for some reason" }

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 )

GlobalConfiguration.Configuration.Formatters.XmlFormatter.UseXmlSerializer = true;
Despertar
fuente
esto funcionó para mí con request.ContentType = "application / json; charset = UTF-8";
Arvind Krmar
15

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 stringsiguiente, debe enviar una cadena simple con comillas dobles en el cuerpo (cuando usa ajax o cartero), por ejemplo,

//send "{\"a\":1}" in body to me, note the outer double quotes
[HttpPost("api1")]
public String PostMethod1([FromBody]string value)
{
    return "received " + value; //  "received {\"a\":1}"
}

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}

public class MyPoco{
    public int a;
    public int b;
}

//send {"a":1, "b":2} in body to me
[HttpPost("api2")]
public String PostMethod2([FromBody]MyPoco value)
{
    return "received " + value.ToString();  //"received your_namespace+MyPoco"
}
León
fuente
11

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. ;)

chrjs
fuente
Refactorizar es exactamente lo que me mordió aquí, ¡gracias por el consejo!
Alan
10

Esto funcionó para mí:

  1. Cree una clase C # DTO, con una propiedad para cada atributo que desee pasar de jQuery / Ajax

    public class EntityData
    {
        public string Attr1 { get; set; }
        public string Attr2 { get; set; }
    }
  2. Defina el método de la API web:

    [HttpPost()]
    public JObject AddNewEntity([FromBody] EntityData entityData)
    {
  3. Llame a la API web como tal:

    var entityData = {
        "attr1": "value1",
        "attr2": "value2"
    };
    
    $.ajax({
        type: "POST",
        url: "/api/YOURCONTROLLER/addnewentity",
        async: true,
        cache: false,
        data: JSON.stringify(entityData),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (response) {
            ...
        }
    });
BigMan73
fuente
Gracias por publicar esto, probé numerosas muestras, ¡pero funcionó para mí!
Sábado
10

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.

dvc.junior
fuente
6

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ó.

byobgyn
fuente
Sí, la API web no se deserializará sin charset = utf-8. blog.codenamed.nl/2015/05/12/…
Sam Rueby
4

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.

Richard Pursehouse
fuente
3

Con Angular, pude pasar datos en este formato:

 data: '=' + JSON.stringify({ u: $scope.usrname1, p: $scope.pwd1 }),
 headers: { 'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8' }

Y en Web API Controler:

    [HttpPost]
    public Hashtable Post([FromBody]string jsonString)
    {
        IDictionary<string, string> data = JsonConvert.DeserializeObject<IDictionary<string, string>>(jsonString);
        string username = data["u"];
        string pwd = data["p"];
   ......

Alternativamente, también podría publicar datos JSON como este:

    data: { PaintingId: 1, Title: "Animal show", Price: 10.50 } 

Y, en el controlador, acepte un tipo de clase como este:

    [HttpPost]
    public string POST(Models.PostModel pm)
    {

     ....
    }

De cualquier manera funciona, si tiene una clase pública establecida en la API, publique JSON, de lo contrario, publique '=' + JSON.stringify ({..: ..., ..: ...})

Yogui
fuente
3

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.

syb
fuente
2

Agregar línea

        ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());

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.

Sergey Kudriavtsev
fuente
Gracias por la ayuda pero desafortunadamente no ayudó. ¡Mantendré la línea por el momento ya que puede ayudar de todos modos!
ianrathbone
Solo para agregar los mismos problemas ocurren cuando
publico
2

Si está utilizando un DataContractSerializer para su formateador Xml o JSON, debe deshacerse de él. Tenía esto en mi archivo WebApiConfig:

public static void Register(HttpConfiguration config)
{
     config.Routes.MapHttpRoute(
           name: "DefaultApi",
           routeTemplate: "api/{controller}/{id}",
           defaults: new { id = RouteParameter.Optional }
     );    

     var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
     jsonFormatter.UseDataContractJsonSerializer = true;
}

Simplemente comento jsonFormatter.UseDataContractJsonSerializer = true;y mi parámetro de entrada ya no es nulo. Gracias a 'Despertar' por darme una pista.

Amir Chatrbahr
fuente
2

Si está seguro acerca de su JSON enviado, debe rastrear su API con cuidado:

  1. Instalar en pc Microsoft.AspNet.WebApi.Tracing paquete
  2. Agregar config.EnableSystemDiagnosticsTracing();en la WebApiConfigclase dentroRegister método.

Ahora mire la salida de depuración y probablemente encontrará un inválido ModelState entrada de registro .

Si ModelStateno es válido, puede encontrar la verdadera causa en suErrors :

Nadie puede adivinar tal excepción:

Could not load file or assembly 'Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Mohsen Afshin
fuente
me salvaste la vida. Al quedar nulo como modelo y después de instalar el paquete, descubrí que mi JSON no está en el formato correcto.
Khizar Iqbal
2

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.

  <system.web>
    <httpRuntime targetFramework="4.7" maxRequestLength="1073741824" />
  </system.web>

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.

mohghaderi
fuente
2

JSON.stringify (...) resolvió mis problemas

ragnarswanson
fuente
1

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:

public class MyController : ApiController
{
    public IEnumerable<MyModel> Get([FromUri] MyComplexType input)
    {
        // input is not null as long as [FromUri] is present in the method arg
    }
}
danludwig
fuente
Esto se debe a que el cuerpo de la solicitud se ignora (y a veces causa un error) cuando se usa GET. La razón por la que funciona ahora es b / c, ahora está pasando parámetros en la cadena de consulta, y su cuerpo está vacío como debería estar en un GET
RyBolt
1

Tuve el mismo problema en Fiddler. Ya tenía Content-Type: application/json; charset=utf-8o Content-Type: application/jsonen 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 sea null.

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\"}".

gosr
fuente
Tenía que hacer lo mismo en Postman. Pero no necesito hacer esto cuando llamo a los servicios de Spring. Parece un problema en el lado .Net.
Malcolm McRoberts
1

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:

public ActionResult Test2([FromBody] jObject str)
{
        return Json(new { message = "Test1 Returned: "+ str }); ;
}
Pini Cheyni
fuente
Test ( [FromBody] object body, [FromHeader(Name="Content-Type")] string bodyMediaType) podría funcionar mejor ya que la comprobación bodyMediaType == "application.json"antes de enviar el cuerpo a JObject ofrece una oportunidad para alternativas.
VladH
1

La mejor solución para mí es HTTP completo como se muestra a continuación:

[Route("api/open")]
[HttpPost]
public async Task<string> open(HttpRequestMessage request)
{
    var json = await request.Content.ReadAsStringAsync();
    JavaScriptSerializer jss = new JavaScriptSerializer();            
    WS_OpenSession param = jss.Deserialize<WS_OpenSession>(json);
    return param.sessionid;
}

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

albertdadze
fuente
1

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í.

jaiveeru
fuente
1

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".

 public static string HttpPostRequest(string url, Dictionary<string, string> postParameters)
    {
        string postData = "=";

        foreach (string key in postParameters.Keys)
        {
            postData += HttpUtility.UrlEncode(key) + "="
                  + HttpUtility.UrlEncode(postParameters[key]) + ",";
        }

        HttpWebRequest myHttpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
        myHttpWebRequest.Method = "POST";

        byte[] data = System.Text.Encoding.ASCII.GetBytes(postData);

        myHttpWebRequest.ContentType = "application/x-www-form-urlencoded";
        myHttpWebRequest.ContentLength = data.Length;

        Stream requestStream = myHttpWebRequest.GetRequestStream();
        requestStream.Write(data, 0, data.Length);
        requestStream.Close();

        HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();

        Stream responseStream = myHttpWebResponse.GetResponseStream();

        StreamReader myStreamReader = new StreamReader(responseStream, System.Text.Encoding.Default);

        string pageContent = myStreamReader.ReadToEnd();

        myStreamReader.Close();
        responseStream.Close();

        myHttpWebResponse.Close();

        return pageContent;
    }
JTStuedle
fuente
1

no importa qué tipo de valor desee publicar, solo enciérrelo entre comillas, para obtenerlo como una cadena. No para tipos complejos.

javascript:

    var myData = null, url = 'api/' + 'Named/' + 'NamedMethod';

    myData = 7;

    $http.post(url, "'" + myData + "'")
         .then(function (response) { console.log(response.data); });

    myData = "some sentence";

    $http.post(url, "'" + myData + "'")
         .then(function (response) { console.log(response.data); });

    myData = { name: 'person name', age: 21 };

    $http.post(url, "'" + JSON.stringify(myData) + "'")
         .then(function (response) { console.log(response.data); });

    $http.post(url, "'" + angular.toJson(myData) + "'")
         .then(function (response) { console.log(response.data); });

C#:

    public class NamedController : ApiController
    {
        [HttpPost]
        public int NamedMethod([FromBody] string value)
        {
            return value == null ? 1 : 0;
        }
    }
Opochitsky Dimitry
fuente
1

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

Tiene AlTaiar
fuente
1

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í:

{
    "shoeSize": 10.5
}

pero su modelo de C # se ve así:

class Shoe{
    public int shoeSize;
}

la carpeta modelo rechazará el modelo y obtendrá nulo.

TwitchBronBron
fuente
1

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.

[HttpPost]
public string PostProcessData([FromBody]string parameters) {
    if (!String.IsNullOrEmpty(parameters)) {
        JObject json = JObject.Parse(parameters);

        // Code logic below
        // Can access params via json["paramName"].ToString();
    }
    return "";
}

Lado del cliente usando jQuery

var dataToSend = JSON.stringify({ param1: "value1", param2: "value2"...});
$.post('/Web_API_URI', { '': dataToSend }).done(function (data) {
     console.debug(data); // returned data from Web API
 });

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.

Nathan
fuente
0

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.

Lapenkov Vladimir
fuente