2008-11-26 4 views
88

Mon code actuel ressemble à ceci. Comment puis-je transmettre mon tableau au contrôleur et quel type de paramètres mon action de contrôleur doit-elle accepter?Comment publier un tableau d'objets complexes avec JSON, jQuery à 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"); 
}; 

Ma méthode d'action du contrôleur ressemble

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets) 

Répondre

83

J'ai trouvé une solution. J'utilise une solution de . Steve Gentile, jQuery and ASP.NET MVC – sending JSON to an Action – Revisited

Code ma vue ASP.NET MVC ressemble:

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

et mon action contrôleur est décoré avec un Attri personnalisés BUTE

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

Code pour l'attribut personnalisé peut être trouvé here (le lien est rompu maintenant).

Parce que le lien est rompu c'est le code pour le 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 est de Json.NET

Lien: Serializing and Deserializing JSON with Json.NET

+0

Beau travail ici! – jeffreypriebe

+0

Ça a l'air génial - Les liens du blog et des codes d'attributs personnalisés ne fonctionnent plus - pouvez-vous republier? – littlechris

+4

Cette solution nécessite des modifications côté client et côté serveur. Je sais que vous aviez besoin de cela il y a longtemps, mais je peux aussi fournir un lien vers une approche différente, qui utilise un simple plugin jQuery permettant de convertir n'importe quel objet Javascript en un formulaire que le classeur par défaut comprend et le modèle lie aux paramètres. Aucun filtre requis. http://erraticdev.blogspot.com/2010/12/sending-complex-json-objects-to-aspnet.html Je ne sais pas comment vous avez résolu les erreurs de validation mais j'ai une solution pour cela aussi: http://erraticdev.blogspot.com/2010/11/handling-validation-errors-on-ajax.html –

8

Vers la seconde moitié de Create REST API using ASP.NET MVC that speaks both JSON and plain XML, pour citer:

Maintenant, nous devons accepter la charge utile JSON et XML, délivré par HTTP POST. Parfois, votre client peut vouloir télécharger une collection d'objets en une fois pour un traitement par lots. Ainsi, ils peuvent télécharger des objets en utilisant le format JSON ou XML. Il n'y a pas de support natif dans ASP.NET MVC pour analyser automatiquement les fichiers JSON ou XML publiés et les mapper automatiquement vers les paramètres Action. Alors, je l'ai écrit un filtre qu'il fait. »

Il met alors en oeuvre un filtre d'action qui mappe le JSON aux objets C# avec le code indiqué.

+0

J'écrivais juste mon anwser. Mais je vais le poster de toute façon ;-) – JSC

+0

Yah, on dirait que Steve Gentile a aussi lu le post d'Omar! – anonymous

+0

Ouais j'ai aussi lu le post d'Omar – JSC

7

premier téléchargement de code JavaScript, JSON2.js, cela nous aidera à sérialiser l'objet dans une chaîne.

Dans mon exemple, je signale les lignes d'une jqGrid via 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"); 
      } 
     } 
    }); 

maintenant sur le contrôleur:

[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); 
    } 

Créer une classe JsonFilter (grâce à la référence 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; 
      } 
     } 
    } 

Créer une autre classe de sorte que le filtre peut analyser la chaîne JSON à l'objet manipulable réelle: Cette comissionsJS de classe sont toutes les lignes de mon 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; } 
    } 

J'espère que cet exemple aide à illustrer comment publier un objet complexe.

+0

Réponse de facto! ; D –

22

Filtres d'action, jquery stringify, bleh ...

Peter, cette fonctionnalité est originaire de MVC. C'est une des choses qui rendent MVC si génial.

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

Et dans l'action,

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

fonctionne comme un charme:

enter image description here

Si vous utilisez jQuery 1.4+, alors vous voulez regarder dans cadre traditionnel mode:

jQuery.ajaxSettings.traditional = true; 

Comme décrit ici: http://www.dovetailsoftware.com/blogs/kmiller/archive/2010/02/24/jquery-1-4-breaks-asp-net-mvc-actions-with-array-parameters

Cela fonctionne même pour les objets complexes. Si vous êtes intéressé, vous devriez regarder dans la documentation MVC sur la liaison de modèle: http://msdn.microsoft.com/en-us/library/dd410405.aspx

+1

vous avez peut-être raison, mais le classeur modèle JSON est nouveau pour MVC3 et la question a été posée en 2008 alors que ce n'était pas supporté. Cela vaut la peine d'être mentionné dans votre réponse. –

+3

Comment est-ce un exemple de passage d'un tableau d'objets complexes? – DuckMaestro

+0

Ce n'est pas le cas mais l'exemple s'applique toujours (MVC 3+). Tant que les noms de vos paramètres correspondent au modèle que vous attendez, vous n'aurez aucun problème. –

10

Dans .NET4.5, MVC 5 pas besoin de widgets.

Javascript:

objet

dans JS: mécanisme enter image description here

qui fait poste.

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

C#

Objets:

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; } 
} 

Controller:

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

objet reçu:

enter image description here

Espérons que cela vous fasse gagner du temps.

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

    } 
Questions connexes