Come pubblicare un array di oggetti complessi con JSON, jQuery su ASP.NET MVC Controller?


92

Il mio codice attuale è simile al seguente. Come posso passare il mio array al controller e che tipo di parametri deve accettare la mia azione del 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");
};

Il mio metodo di azione del controller è simile

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets)

Risposte:


84

Ho trovato una soluzione. Uso una soluzione di Steve Gentile, jQuery e ASP.NET MVC - invio di JSON a un'azione - rivisitato .

Il mio codice di visualizzazione ASP.NET MVC ha il seguente aspetto:

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

e l'azione del mio controller è decorata con un attributo personalizzato

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

Il codice per l'attributo personalizzato può essere trovato qui (il collegamento è interrotto ora).

Poiché il collegamento è interrotto, questo è il codice per 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 proviene da Json.NET

Collegamento: serializzazione e deserializzazione di JSON con Json.NET


Sembra fantastico - Il post del blog e i link ai codici degli attributi personalizzati non funzionano più - puoi ripubblicare?
littlechris

4
Questa soluzione richiede modifiche sul lato client e server. So che ne avevi bisogno molto tempo fa, ma potrei anche fornire un collegamento a un approccio diverso, che utilizza un semplice plug-in jQuery che consente di convertire qualsiasi oggetto Javascript in un modulo che il raccoglitore di modelli predefinito comprende e il modello si lega ai parametri. Nessun filtro necessario. erraticdev.blogspot.com/2010/12/… Non so come hai risolto gli errori di convalida ma ho una soluzione anche per questo: erraticdev.blogspot.com/2010/11/…
Robert Koritnik

3
Puoi fornire l'origine / origine di JavaScriptConvert.DeserializeObject?
Matthieu,

È la libreria Newtonsoft Json: se apri il gestore di pacchetti nuget e cerchi su Newtonsoft, ti verrà mostrato (ora che è il 2016). Probabilmente questo ora è ovvio, ma nel caso qualcuno se lo stesse chiedendo.
Robb Sadler

22

Filtri azione, jquery stringify, bleh ...

Peter, questa funzionalità è originaria di MVC. Questa è una delle cose che rende MVC così eccezionale.

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

E nell'azione

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

Funziona come un fascino:

inserisci qui la descrizione dell'immagine

Se stai usando jQuery 1.4+, allora vuoi esaminare l'impostazione della modalità tradizionale:

jQuery.ajaxSettings.traditional = true;

Come descritto qui: http://www.dovetailsoftware.com/blogs/kmiller/archive/2010/02/24/jquery-1-4-breaks-asp-net-mvc-actions-with-array-parameters

Funziona anche per oggetti complessi. Se sei interessato, dovresti esaminare la documentazione MVC sul Model Binding: http://msdn.microsoft.com/en-us/library/dd410405.aspx


1
potresti avere ragione, ma il raccoglitore di modelli JSON è nuovo per MVC3 e la domanda è stata posta nel 2008 quando questo non era supportato. Vale la pena menzionarlo nella tua risposta.
Piotr Owsiak

3
In che modo questo è un esempio di passaggio di un array di oggetti complessi ?
DuckMaestro

Non lo è, ma l'esempio è ancora valido (MVC 3+). Finché i nomi dei parametri corrispondono al modello che ti aspetti, non avrai alcun problema.
J. Mitchell

La chiave qui è creare un oggetto JSON con il nome del parametro del metodo ("ids") e quindi inserire l'array di oggetti complessi al suo interno. Inoltre, rendi "vero" il terzo parametro e ti occuperai della modalità tradizionale.
redwards510

11

In .NET4.5, MVC 5non c'è bisogno di widget.

Javascript:

oggetto in JS: inserisci qui la descrizione dell'immagine

meccanismo che fa post.

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

C #

Oggetti:

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

Oggetto ricevuto:

inserisci qui la descrizione dell'immagine

Spero che questo ti faccia risparmiare tempo.


8

Verso la seconda metà della creazione dell'API REST utilizzando ASP.NET MVC che parla sia JSON che XML semplice , per citare:

Ora dobbiamo accettare il payload JSON e XML, fornito tramite HTTP POST. A volte il tuo cliente potrebbe voler caricare una raccolta di oggetti in un colpo solo per l'elaborazione in batch. Quindi, possono caricare oggetti utilizzando il formato JSON o XML. Non è disponibile alcun supporto nativo in ASP.NET MVC per analizzare automaticamente JSON o XML pubblicato e mappare automaticamente ai parametri di azione. Quindi, ho scritto un filtro che lo fa. "

Quindi implementa un filtro di azione che mappa il JSON agli oggetti C # con il codice mostrato.


Stavo solo scrivendo la mia risposta. Ma lo posterò comunque ;-)
JSC

7

Prima scarica questo codice JavaScript, JSON2.js , che ci aiuterà a serializzare l'oggetto in una stringa.

Nel mio esempio sto postando le righe di un jqGrid tramite 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");
            }
        }
    });

Ora sul controller:

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

Crea una classe JsonFilter (grazie al riferimento 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;
            }
        }
    }

Crea un'altra classe in modo che il filtro possa analizzare la stringa JSON sull'oggetto manipolabile effettivo: questa classe comissionsJS sono tutte le righe del mio 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; }
    }

Spero che questo esempio aiuti a illustrare come pubblicare un oggetto complesso.


0

Oh mio Dio. non è necessario fare nulla di speciale. solo nella sezione del tuo post fai come segue:

    $.post(yourURL,{ '': results})(function(e){ ...}

Nel server usa questo:

   public ActionResult MethodName(List<yourViewModel> model){...}

questo link ti aiuta a fare ...


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

    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.