Wie poste ich ein Array komplexer Objekte mit JSON, jQuery in ASP.NET MVC Controller?

92

Mein aktueller Code sieht wie folgt aus. Wie kann ich mein Array an den Controller übergeben und welche Parameter muss meine Controller-Aktion akzeptieren?

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

Meine Controller-Aktionsmethode sieht so aus

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets)
JSC
quelle

Antworten:

84

Ich habe eine Lösung gefunden. Ich verwende eine Lösung von Steve Gentile, jQuery und ASP.NET MVC, die JSON an eine überarbeitete Aktion sendet .

Mein ASP.NET MVC-Ansichtscode sieht folgendermaßen aus:

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

und meine Controller-Aktion ist mit einem benutzerdefinierten Attribut versehen

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

Code für das benutzerdefinierte Attribut finden Sie hier (der Link ist jetzt defekt).

Da die Verbindung unterbrochen ist, ist dies der Code für das 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 stammt von Json.NET

Link: Serialisieren und Deserialisieren von JSON mit Json.NET

JSC
quelle
Sieht gut aus - Der Blogbeitrag und die benutzerdefinierten Attributcode-Links funktionieren nicht mehr - können Sie erneut posten?
Littlechris
4
Diese Lösung erfordert Änderungen auf Client- und Serverseite. Ich weiß, dass Sie dies vor langer Zeit benötigt haben, aber ich kann auch einen Link zu einem anderen Ansatz bereitstellen, der ein einfaches jQuery-Plugin verwendet, mit dem jedes Javascript-Objekt in eine Form konvertiert werden kann, die der Standardmodellbinder versteht und das Modell an Parameter bindet. Keine Filter erforderlich. erraticdev.blogspot.com/2010/12/… Ich weiß nicht, wie Sie Validierungsfehler gelöst haben, aber ich habe auch eine Lösung dafür: erraticdev.blogspot.com/2010/11/…
Robert Koritnik
3
Können Sie die Quelle / Herkunft von JavaScriptConvert.DeserializeObject angeben?
Matthieu
Es ist die Newtonsoft Json-Bibliothek. Wenn Sie den Nuget-Paketmanager öffnen und nach Newtonsoft suchen, wird sie für Sie angezeigt (jetzt, da es 2016 ist). Wahrscheinlich ist das jetzt offensichtlich, aber für den Fall, dass sich jemand wundert.
Robb Sadler
22

Aktionsfilter, jquery stringify, bleh ...

Peter, diese Funktionalität ist in MVC integriert. Das ist eines der Dinge, die MVC so großartig machen.

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

Und in der Aktion,

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

Klappt wunderbar:

Geben Sie hier die Bildbeschreibung ein

Wenn Sie jQuery 1.4+ verwenden, sollten Sie die Einstellung des traditionellen Modus untersuchen:

jQuery.ajaxSettings.traditional = true;

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

Dies funktioniert sogar bei komplexen Objekten. Wenn Sie interessiert sind, sollten Sie die MVC-Dokumentation zur Modellbindung lesen: http://msdn.microsoft.com/en-us/library/dd410405.aspx

Levitikon
quelle
1
Sie haben vielleicht Recht, aber der JSON-Modellordner ist neu in MVC3 und die Frage wurde 2008 gestellt, als dies nicht unterstützt wurde. Es wäre erwähnenswert in Ihrer Antwort.
Piotr Owsiak
3
Wie ist dies ein Beispiel für die Übergabe eines Arrays komplexer Objekte ?
DuckMaestro
Es ist nicht, aber das Beispiel gilt immer noch (MVC 3+). Solange Ihre Parameternamen mit dem erwarteten Modell übereinstimmen, treten keine Probleme auf.
J. Mitchell
Der Schlüssel hier besteht darin, ein JSON-Objekt mit dem Methodenparameternamen ("ids") zu erstellen und dann das Array komplexer Objekte darin zu platzieren. Wenn Sie außerdem den dritten Parameter auf "true" setzen, kümmern Sie sich um den herkömmlichen Modus.
redwards510
11

In .NET4.5, MVC 5keine Notwendigkeit für Widgets.

Javascript:

Objekt in JS: Geben Sie hier die Bildbeschreibung ein

Mechanismus, der postet.

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

C #

Objekte:

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

Regler:

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

Objekt erhalten:

Geben Sie hier die Bildbeschreibung ein

Hoffe das spart dir etwas Zeit.

Matas Vaitkevicius
quelle
8

In der zweiten Hälfte von Create REST API mit ASP.NET MVC, das sowohl JSON als auch einfaches XML spricht , um Folgendes zu zitieren:

Jetzt müssen wir JSON- und XML-Nutzdaten akzeptieren, die über HTTP POST bereitgestellt werden. Manchmal möchte Ihr Kunde möglicherweise eine Sammlung von Objekten auf einmal für die Stapelverarbeitung hochladen. Sie können also Objekte im JSON- oder XML-Format hochladen. In ASP.NET MVC gibt es keine native Unterstützung zum automatischen Parsen von veröffentlichtem JSON oder XML und zum automatischen Zuordnen zu Aktionsparametern. Also habe ich einen Filter geschrieben, der das macht. "

Anschließend implementiert er einen Aktionsfilter, der den JSON C # -Objekten mit angezeigtem Code zuordnet.

anonym
quelle
Ich habe gerade meine Antwort geschrieben. Aber ich werde es trotzdem
JSC
7

Laden Sie zuerst diesen JavaScript-Code JSON2.js herunter, mit dessen Hilfe wir das Objekt in eine Zeichenfolge serialisieren können.

In meinem Beispiel poste ich die Zeilen eines jqGrid über 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");
            }
        }
    });

Jetzt auf dem 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);
    }

Erstellen Sie eine JsonFilter-Klasse (dank JSC-Referenz).

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

Erstellen Sie eine weitere Klasse, damit der Filter die JSON-Zeichenfolge auf das tatsächlich manipulierbare Objekt analysieren kann: Diese Klasse comissionsJS sind alle Zeilen meines 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; }
    }

Ich hoffe, dieses Beispiel hilft zu veranschaulichen, wie ein komplexes Objekt gepostet wird.

Sanchitos
quelle
0

Oh mein Gott. Ich muss nichts Besonderes tun. Gehen Sie in Ihrem Post-Bereich wie folgt vor:

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

Verwenden Sie im Server Folgendes:

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

Dieser Link hilft Ihnen dabei ...

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

    }
JsonW
quelle