Publicación de datos JSON a través de jQuery a la acción del controlador ASP .NET MVC 4

Tengo problemas para pasar un objeto JSON complejo a una acción de controlador MVC 4. Como el contenido de JSON es variable, no quiero que MVC asigne propiedades / elementos individuales de JSON a los parámetros en la lista de parámetros del método de acción. Solo quiero obtener los datos como un solo parámetro de cadena JSON en la acción del controlador.

Aquí está la firma de mi método de acción:

[HttpPost] [ValidateInput(false)] public string ConvertLogInfoToXml(string jsonOfLog) 

Y aquí está mi bash de publicar algunos datos JSON, desde mi navegador:

  data = {prop: 1, myArray: [1, "two", 3]}; //'data' is much more complicated in my real application json = {jsonOfLog: data}; $.ajax({ type: 'POST', url: "Home/ConvertLogInfoToXml", data: JSON.stringify(json), success: function (returnPayload) { console && console.log ("request succeeded"); }, error: function (xhr, ajaxOptions, thrownError) { console && console.log ("request failed"); }, dataType: "xml", contentType: "application/json", processData: false, async: false }); 

Cuando llego a mi punto de interrupción al comienzo del método ConvertLogInfoToXML, jsonOfLog es nulo.

Si cambio la variable ‘json’ se establece en JavaScript para que la propiedad jsonOfLog sea una cadena simple, por ejemplo:

 json = { jsonOfLog: "simple string" }; 

luego cuando se toca mi punto de corte al comienzo del método ConvertLogInfoToXML, jsonOfLog es el valor de la cadena (por ejemplo, “cadena simple”).

Traté de cambiar el tipo del parámetro jsonOfLog en el método de acción para que sea de tipo objeto:

  [HttpPost] [ValidateInput(false)] public string ConvertLogInfoToXml(object jsonOfLog) 

Ahora, con el código JavaScript original (donde paso un objeto ‘data’ más complejo), jsonOfLog obtiene el valor de {object}. Pero el depurador no muestra más detalles en una ventana de observación, y no sé qué métodos puedo usar para operar en esta variable.

¿Cómo paso datos JSON a un controlador MVC, donde los datos pasados ​​son un objeto complejo codificado?

Gracias, Notre

El problema es su dataType y el formato de su parámetro de data . Acabo de probar esto en una caja de arena y las siguientes obras:

DO#

  [HttpPost] public string ConvertLogInfoToXml(string jsonOfLog) { return Convert.ToString(jsonOfLog); } 

javascript

   

Preste especial atención a los data , al enviar texto, debe enviar una variable que coincida con el nombre de su parámetro. No es bonito, pero obtendrá su codiciada cadena sin formatear.

Al ejecutar esto, jsonOfLog se ve así en la función del servidor:

  jsonOfLog "{\"prop\":1,\"myArray\":[1,\"two\",3]}" string 

El encabezado HTTP POST:

 Key Value Request POST /Home/ConvertLogInfoToXml HTTP/1.1 Accept text/plain, */*; q=0.01 Content-Type application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With XMLHttpRequest Referer http://localhost:50189/ Accept-Language en-US Accept-Encoding gzip, deflate User-Agent Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0) Host localhost:50189 Content-Length 42 DNT 1 Connection Keep-Alive Cache-Control no-cache Cookie EnableSSOUser=admin 

El cuerpo HTTP POST:

 jsonOfLog={"prop":1,"myArray":[1,"two",3]} 

El encabezado de respuesta:

 Key Value Cache-Control private Content-Type text/html; charset=utf-8 Date Fri, 28 Jun 2013 18:49:24 GMT Response HTTP/1.1 200 OK Server Microsoft-IIS/8.0 X-AspNet-Version 4.0.30319 X-AspNetMvc-Version 4.0 X-Powered-By ASP.NET X-SourceFiles =?UTF-8?B?XFxwc2ZcaG9tZVxkb2N1bWVudHNcdmlzdWFsIHN0dWRpbyAyMDEyXFByb2plY3RzXE12YzRQbGF5Z3JvdW5kXE12YzRQbGF5Z3JvdW5kXEhvbWVcQ29udmVydExvZ0luZm9Ub1htbA==?= 

El cuerpo de respuesta:

 {"prop":1,"myArray":[1,"two",3]} 

Creo que encontrarás tu respuesta si te refieres a esta publicación: ¿ Deserializar JSON en el objeto dynamic C #?

Hay varias formas de lograr lo que quieres aquí. El enfoque System.Web.Helpers.Json (algunas respuestas abajo) parece ser el más simple.

VERSIÓN VB.NET

Bueno, acabo de pasar varias horas buscando un método viable para publicar múltiples parámetros en una API WEB MVC 4, pero la mayoría de lo que encontré fue para una acción ‘GET’ o simplemente no funcionó. Sin embargo, finalmente funcioné y pensé en compartir mi solución.

  1. Use paquetes NuGet para descargar JSON-js json2 y Json.NET . Pasos para instalar paquetes NuGet:

    (1) En Visual Studio, vaya a Sitio web > Administrar paquetes de NuGet … enter image description here

    (2) Escriba json (o algo JSON-js json2 ) en la barra de búsqueda y busque JSON-js json2 y Json.NET . Al hacer doble clic en ellos se instalarán los paquetes en el proyecto actual. enter image description here

    (3) NuGet colocará automáticamente el archivo json en ~/Scripts/json2.min.js en el directorio de su proyecto. Busque el archivo json2.min.js y arrástrelo / suéltelo en el encabezado de su sitio web. Nota : para obtener instrucciones sobre la instalación de archivos .js (javascript), lea esta solución .

  2. Crea un objeto de clase que contenga los parámetros deseados. Lo usará para acceder a los parámetros en el controlador API. Código de ejemplo:

     Public Class PostMessageObj Private _body As String Public Property body As String Get Return _body End Get Set(value As String) _body = value End Set End Property Private _id As String Public Property id As String Get Return _id End Get Set(value As String) _id = value End Set End Property End Class 
  3. Luego configuramos el controlador de la API web MVC 4 real que vamos a utilizar para la acción POST. En él, utilizaremos Json.NET para deserializar el objeto de cadena cuando se publique. Recuerde usar los espacios de nombres apropiados. Continuando con el ejemplo anterior, aquí está mi código:

     Public Sub PostMessage( ByVal newmessage As String) Dim t As PostMessageObj = Newtonsoft.Json.JsonConvert.DeserializeObject(Of PostMessageObj)(newmessage) Dim body As String = t.body Dim i As String = t.id End Sub 
  4. Ahora que tenemos nuestro controlador API configurado para recibir nuestro objeto JSON codificado, podemos llamar la acción POST libremente desde el lado del cliente usando $ .ajax; Continuando con el ejemplo anterior, aquí está mi código (reemplace localhost + rootpath apropiadamente):

     var url = 'http:///api/Offers/PostMessage'; var dataType = 'json' var data = 'nothn' var tempdata = { body: 'this is a new message...Ip sum lorem.', id: '1234' } var jsondata = JSON.stringify(tempdata) $.ajax({ type: "POST", url: url, data: { '': jsondata}, success: success(data), dataType: 'text' }); 

Como puede ver, básicamente estamos construyendo el objeto JSON, convirtiéndolo en una cadena, pasándolo como un único parámetro y luego reconstruyéndolo a través del framework JSON.NET. No incluí un valor de retorno en nuestro controlador API, así que simplemente coloqué un valor de cadena arbitrario en la función success() .


Notas del autor

Esto se hizo en Visual Studio 2010 utilizando ASP.NET 4.0, WebForms, VB.NET y MVC 4 Web API Controller. Para cualquier persona que tenga problemas para integrar MVC 4 Web API con VS2010, puede descargar el parche para hacerlo posible. Puede descargarlo desde el Centro de descarga de Microsoft.

Aquí hay algunas referencias adicionales que ayudaron (principalmente en C #):

  • Usar jQuery para publicar parámetros FromBody
  • Envío de objeto JSON a la API web
  • Y, por supuesto, la respuesta de J Torres fue la última pieza del rompecabezas.

// objeto json simple en asp.net mvc

 var model = {"Id": "xx", "Name":"Ravi"}; $.ajax({ url: 'test/[ControllerName]', type: "POST", data: model, success: function (res) { if (res != null) { alert("done."); } }, error: function (res) { } }); //model in c# public class MyModel { public string Id {get; set;} public string Name {get; set;} } //controller in asp.net mvc public ActionResult test(MyModel model) { //now data in your model } 

Hace algunos meses me encontré con una situación extraña en la que también necesitaba enviar una fecha con formato Json a mi controlador. Esto es lo que se me ocurrió después de sacarme el pelo:

Mi clase se ve así:

 public class NodeDate { public string nodedate { get; set; } } public class NodeList1 { public List nodedatelist { get; set; } } 

y mi código c # de la siguiente manera:

  public string getTradeContribs(string Id, string nodedates) { //nodedates = @"{""nodedatelist"":[{""nodedate"":""01/21/2012""},{""nodedate"":""01/22/2012""}]}"; // sample Json format System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer(); NodeList1 nodes = (NodeList1)ser.Deserialize(nodedates, typeof(NodeList1)); string thisDate = ""; foreach (var date in nodes.nodedatelist) { // iterate through if needed... thisDate = date.nodedate; } } 

y así pude deserializar mi nodedates parámetro de objeto Json en el objeto “nodos”; naturalmente, por supuesto, utilizando la clase “NodeList1” para que funcione.

Espero que esto ayude …. Bob

Bueno, mi lado del cliente (un archivo cshtml) estaba usando DataTables para mostrar una grilla (ahora usando el control Infragistics, que son geniales). Y una vez que el usuario hizo clic en la fila, capturé el evento de la fila y la fecha asociada con ese registro para volver al servidor y hacer solicitudes adicionales para intercambios, etc. Y no, NO lo he codificado. ..

Los DataTables def comenzaron como esto (dejando un montón de cosas), y el evento click se ve abajo donde PUSH en mi objeto Json:

  oTablePf = $('#pftable').dataTable({ // INIT CODE "aaData": PfJsonData, 'aoColumnDefs': [ { "sTitle": "Pf Id", "aTargets": [0] }, { "sClass": "**td_nodedate**", "aTargets": [3] } ] }); $("#pftable").delegate("tbody tr", "click", function (event) { // ROW CLICK EVT!! var rownum = $(this).index(); var thisPfId = $(this).find('.td_pfid').text(); // Find Port Id and Node Date var thisDate = $(this).find('.td_nodedate').text(); //INIT JSON DATA var nodeDatesJson = { "nodedatelist":[] }; // omitting some code here... var dateArry = thisDate.split("/"); var nodeDate = dateArry[2] + "-" + dateArry[0] + "-" + dateArry[1]; nodeDatesJson.nodedatelist.push({ nodedate: nodeDate }); getTradeContribs(thisPfId, nodeDatesJson); // GET TRADE CONTRIBUTIONS });