2008-11-26 25 views
88

Mi código actual tiene el siguiente aspecto. ¿Cómo puedo pasar mi matriz al controlador y qué tipo de parámetros debe aceptar mi acción de controlador?Cómo publicar una matriz de objetos complejos con JSON, jQuery a ASP.NET MVC Controller?

function getplaceholders() { 
    var placeholders = $('.ui-sortable'); 
    var result = new Array(); 
    placeholders.each(function() { 
     var ph = $(this).attr('id'); 
     var sections = $(this).find('.sort'); 
     var section; 

     sections.each(function(i, item) { 
      var sid = $(item).attr('id'); 

      result.push({ 'SectionId': sid, 'Placeholder': ph, 'Position': i }); 
     }); 
    }); 
    alert(result.toString()); 
    $.post(
     '/portal/Designer.mvc/SaveOrUpdate', 
     result, 
     function(data) { 
      alert(data.Result); 
     }, "json"); 
}; 

Mi método de acción del controlador se parece

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets) 

Respuesta

83

he encontrado una solución. Yo uso una solución de . Steve gentil, jQuery and ASP.NET MVC – sending JSON to an Action – Revisited

mi ASP.NET MVC código de la vista se parece a:

function getplaceholders() { 
     var placeholders = $('.ui-sortable'); 
     var results = new Array(); 
     placeholders.each(function() { 
      var ph = $(this).attr('id'); 
      var sections = $(this).find('.sort'); 
      var section; 

      sections.each(function(i, item) { 
       var sid = $(item).attr('id'); 
       var o = { 'SectionId': sid, 'Placeholder': ph, 'Position': i }; 
       results.push(o); 
      }); 
     }); 
     var postData = { widgets: results }; 
     var widgets = results; 
     $.ajax({ 
      url: '/portal/Designer.mvc/SaveOrUpdate', 
      type: 'POST', 
      dataType: 'json', 
      data: $.toJSON(widgets), 
      contentType: 'application/json; charset=utf-8', 
      success: function(result) { 
       alert(result.Result); 
      } 
     }); 
    }; 

y mi controlador de acción está decorado con un attri personalizados bute Código

[JsonFilter(Param = "widgets", JsonDataType = typeof(List<PageDesignWidget>))] 
public JsonResult SaveOrUpdate(List<PageDesignWidget> widgets 

para el atributo personalizado se puede encontrar here (el enlace está roto ahora).

Debido a que el vínculo se rompe este es el código para el JsonFilterAttribute

public class JsonFilter : ActionFilterAttribute 
{ 
    public string Param { get; set; } 
    public Type JsonDataType { get; set; } 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) 
     { 
      string inputContent; 
      using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream)) 
      { 
       inputContent = sr.ReadToEnd(); 
      } 
      var result = JsonConvert.DeserializeObject(inputContent, JsonDataType); 
      filterContext.ActionParameters[Param] = result; 
     } 
    } 
} 

JsonConvert.DeserializeObject es de Json.NET

Enlace: Serializing and Deserializing JSON with Json.NET

+0

¡Buen trabajo aquí! – jeffreypriebe

+0

Se ve muy bien: la publicación de blog y los enlaces de código de atributo personalizado ya no funcionan. ¿Se puede volver a publicar? – littlechris

+4

Esta solución requiere cambios en el lado del cliente y del servidor. Sé que necesitabas esto hace mucho tiempo, pero también puedo proporcionar un enlace a un enfoque diferente, que usa un plugin jQuery simple que hace posible convertir cualquier objeto Javascript en un formulario que el encuadernador de modelo predeterminado comprenda y el modelo se vincule a los parámetros. No se necesitan filtros http://erraticdev.blogspot.com/2010/12/sending-complex-json-objects-to-aspnet.html No sé cómo resolvió los errores de validación, pero también tengo una solución para eso: http://erraticdev.blogspot.com/2010/11/handling-validation-errors-on-ajax.html –

8

Hacia la segunda mitad del Create REST API using ASP.NET MVC that speaks both JSON and plain XML, para citar:

Ahora tenemos que aceptar JSON y XML de carga útil, emitido a través de HTTP POST. En ocasiones, es posible que su cliente desee cargar una colección de objetos de una vez para el procesamiento por lotes. Por lo tanto, pueden cargar objetos utilizando el formato JSON o XML. No existe soporte nativo en ASP.NET MVC para analizar automáticamente JSON o XML publicados y asignar automáticamente a los parámetros de Acción. Por lo tanto, escribí un filtro que lo hace ".

A continuación, implementa un filtro de acción que mapea el JSON a objetos de C# con el código que se muestra.

+0

Estaba escribiendo mi awser. Pero lo publicaré de todos modos ;-) – JSC

+0

¡Yah, parece que Steve Gentile también leyó la publicación de Omar! – anonymous

+0

Sí, también he leído la publicación de Omar – JSC

7

Primero descarga el código JavaScript, JSON2.js, eso nos ayudará a serializar el objeto en una cadena.

En mi ejemplo les dejo las filas de una jqGrid a través de Ajax:

var commissions = new Array(); 
    // Do several row data and do some push. In this example is just one push. 
    var rowData = $(GRID_AGENTS).getRowData(ids[i]); 
    commissions.push(rowData); 
    $.ajax({ 
     type: "POST", 
     traditional: true, 
     url: '<%= Url.Content("~/") %>' + AREA + CONTROLLER + 'SubmitCommissions', 
     async: true, 
     data: JSON.stringify(commissions), 
     dataType: "json", 
     contentType: 'application/json; charset=utf-8', 
     success: function (data) { 
      if (data.Result) { 
       jQuery(GRID_AGENTS).trigger('reloadGrid'); 
      } 
      else { 
       jAlert("A problem ocurred during updating", "Commissions Report"); 
      } 
     } 
    }); 

Ahora en el controlador:

[HttpPost] 
    [JsonFilter(Param = "commissions", JsonDataType = typeof(List<CommissionsJs>))] 
    public ActionResult SubmitCommissions(List<CommissionsJs> commissions) 
    { 
     var result = dosomething(commissions); 
     var jsonData = new 
     { 
      Result = true, 
      Message = "Success" 
     }; 
     if (result < 1) 
     { 
      jsonData = new 
      { 
       Result = false, 
       Message = "Problem" 
      }; 
     } 
     return Json(jsonData); 
    } 

crear una clase JsonFilter (gracias a la referencia JSC).

public class JsonFilter : ActionFilterAttribute 
    { 
     public string Param { get; set; } 
     public Type JsonDataType { get; set; } 
     public override void OnActionExecuting(ActionExecutingContext filterContext) 
     { 
      if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) 
      { 
       string inputContent; 
       using (var sr = new StreamReader(filterContext.HttpContext.Request.InputStream)) 
       { 
        inputContent = sr.ReadToEnd(); 
       } 
       var result = JsonConvert.DeserializeObject(inputContent, JsonDataType); 
       filterContext.ActionParameters[Param] = result; 
      } 
     } 
    } 

crear otra clase por lo que el filtro se puede analizar la cadena JSON al objeto manipulable real: Este comissionsJS clase son todas las filas de mi jqGrid.

public class CommissionsJs 
    { 
     public string Amount { get; set; } 

     public string CheckNumber { get; set; } 

     public string Contract { get; set; } 
     public string DatePayed { get; set; } 
     public string DealerName { get; set; } 
     public string ID { get; set; } 
     public string IdAgentPayment { get; set; } 
     public string Notes { get; set; } 
     public string PaymentMethodName { get; set; } 
     public string RowNumber { get; set; } 
     public string AgentId { get; set; } 
    } 

Espero que este ejemplo ayude a ilustrar cómo publicar un objeto complejo.

+0

¡Respuesta de facto! ; D –

22

Filtros de acción, stringify jQuery, bleh ...

Peter, esta funcionalidad es nativa de MVC. Esa es una de las cosas que hace MVC tan bueno.

$.post('SomeController/Batch', { 'ids': ['1', '2', '3']}, function (r) { 
    ... 
}); 

Y en la acción,

[HttpPost] 
public ActionResult Batch(string[] ids) 
{ 
} 

funciona como un encanto:

enter image description here

Si estás usando jQuery 1.4 o superior, entonces usted desee ver en la configuración tradicional modo:

jQuery.ajaxSettings.traditional = true; 

Como se describe aquí: http://www.dovetailsoftware.com/blogs/kmiller/archive/2010/02/24/jquery-1-4-breaks-asp-net-mvc-actions-with-array-parameters

Esto incluso funciona para objetos complejos. Si está interesado, debe consultar la documentación de MVC sobre Encuadernación de modelos: http://msdn.microsoft.com/en-us/library/dd410405.aspx

+1

puede estar en lo cierto, pero la carpeta de modelo JSON es nueva en MVC3 y la pregunta se realizó en 2008 cuando no era compatible. Vale la pena mencionarlo en su respuesta. –

+3

¿Cómo es este un ejemplo de pasar una matriz de _complex objects_? – DuckMaestro

+0

No es pero el ejemplo todavía se aplica (MVC 3+). Siempre que sus nombres de parámetros coincidan con el modelo que espera no tendrá ningún problema. –

10

En .NET4.5, MVC 5 sin necesidad de widgets.

Javascript:

objeto en JS: enter image description here

mecanismo que hace puesto.

$('.button-green-large').click(function() { 
     $.ajax({ 
      url: 'Quote', 
      type: "POST", 
      dataType: "json", 
      data: JSON.stringify(document.selectedProduct), 
      contentType: 'application/json; charset=utf-8', 
     }); 
    }); 

C#

Objetos:

public class WillsQuoteViewModel 
{ 
    public string Product { get; set; } 

    public List<ClaimedFee> ClaimedFees { get; set; } 
} 

public partial class ClaimedFee //Generated by EF6 
{ 
    public long Id { get; set; } 
    public long JourneyId { get; set; } 
    public string Title { get; set; } 
    public decimal Net { get; set; } 
    public decimal Vat { get; set; } 
    public string Type { get; set; } 

    public virtual Journey Journey { get; set; } 
} 

controlador:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Quote(WillsQuoteViewModel data) 
{ 
.... 
} 

objeto recibido:

enter image description here

Espero que esto te ahorre algo de tiempo.

-1
[HttpPost] 
    public bool parseAllDocs([FromBody] IList<docObject> data) 
    { 
     // do stuff 

    } 
Cuestiones relacionadas