92 votes

Comment poster un tableau d'objets complexes avec JSON, jQuery à ASP.NET MVC Controller ?

Mon code actuel ressemble à ce qui suit. Comment puis-je transmettre mon tableau au contrôleur et quels types de paramètres mon action de contrôleur doit-elle accepter ?

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

La méthode d'action de mon contrôleur ressemble à

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets)

84voto

JSC Points 2104

J'ai trouvé une solution. J'utilise une solution de Steve Gentile, jQuery et ASP.NET MVC - envoi de JSON à une action - révision .

Mon code de vue ASP.NET MVC ressemble à ceci :

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 de contrôleur est décorée avec un attribut personnalisé

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

Le code pour l'attribut personnalisé peut être trouvé ici (le lien est maintenant rompu).

Le lien étant rompu, voici le code de l'attribut 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 vient de Json.NET.

Lien : Sérialisation et désérialisation de JSON avec Json.NET

0 votes

L'article de blog et les liens vers le code d'attribut personnalisé ne fonctionnent plus - pouvez-vous les réafficher ?

4 votes

Cette solution nécessite des changements du côté du client et du serveur. Je sais que vous en aviez besoin depuis longtemps, mais je peux tout aussi bien vous 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 model binder par défaut comprend et qui lie le modèle aux paramètres. Aucun filtre n'est nécessaire. erraticdev.blogspot.com/2010/12/ Je ne sais pas comment vous avez résolu les erreurs de validation mais j'ai une solution pour cela aussi : erraticdev.blogspot.com/2010/11/

3 votes

Pouvez-vous donner la source/origine de JavaScriptConvert.DeserializeObject ?

22voto

Levitikon Points 2258

Action Filters, jquery stringify, bleh...

Peter, cette fonctionnalité est native à MVC. C'est l'une des choses qui rend 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+, vous devez envisager de définir le mode traditionnel :

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 consulter la documentation MVC sur le Model Binding : http://msdn.microsoft.com/en-us/library/dd410405.aspx

1 votes

Vous avez peut-être raison, mais le liant de modèle JSON est nouveau dans MVC3 et la question a été posée en 2008 alors qu'il n'était pas pris en charge. Il serait bon de le mentionner dans votre réponse.

3 votes

Comment est-ce un exemple de passer un tableau de objets complexes ?

0 votes

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

11voto

LIUFA Points 3642

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

Javascript :

en JS : enter image description here

mécanisme 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; }
}

Contrôleur :

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

Objet reçu :

enter image description here

J'espère que cela vous fera gagner du temps.

8voto

anonymous Points 4000

Vers la seconde moitié du Créez une API REST à l'aide d'ASP.NET MVC qui parle à la fois de JSON et de XML simple. , à citer :

Nous devons maintenant accepter les charges utiles JSON et XML, livrées via HTTP POST. Parfois, votre client peut vouloir télécharger une collection d'objets en une seule fois pour un traitement par lots. Il peut donc télécharger des objets au format JSON ou XML. Il n'existe pas de support natif dans ASP.NET MVC pour analyser automatiquement le format JSON ou XML et le mapper automatiquement en paramètres d'action. J'ai donc écrit un filtre qui le fait."

Il implémente ensuite un filtre d'action qui fait correspondre le JSON aux objets C# avec le code indiqué.

0 votes

J'étais juste en train d'écrire ma réponse. Mais je vais quand même la poster ;-)

7voto

Sanchitos Points 2263

Téléchargez d'abord ce code JavaScript, JSON2.js qui nous aidera à sérialiser l'objet en une chaîne de caractères.

Dans mon exemple, j'affiche les lignes d'un fichier 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éez une autre classe pour que le filtre puisse analyser la chaîne JSON pour obtenir l'objet manipulable réel : Cette classe comissionsJS sont toutes les lignes de ma 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 permet d'illustrer la manière d'afficher un objet complexe.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X