Jak wysłać tablicę złożonych obiektów z JSON, jQuery do kontrolera ASP.NET MVC?

92

Mój obecny kod wygląda następująco. Jak mogę przekazać moją tablicę do kontrolera i jakie parametry musi zaakceptować moja akcja kontrolera?

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

Moja metoda akcji kontrolera wygląda tak

public JsonResult SaveOrUpdate(IList<PageDesignWidget> widgets)
JSC
źródło

Odpowiedzi:

84

Znalazłem rozwiązanie. Używam rozwiązania Steve'a Gentile'a, jQuery i ASP.NET MVC - wysyłam JSON do Action - Revisited .

Mój kod widoku ASP.NET MVC wygląda następująco:

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

a moja akcja kontrolera jest ozdobiona atrybutem niestandardowym

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

Kod atrybutu niestandardowego można znaleźć tutaj (link jest teraz uszkodzony).

Ponieważ łącze jest uszkodzone, jest to kod 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 pochodzi z Json.NET

Link: Serializacja i deserializacja JSON z Json.NET

JSC
źródło
Wygląda świetnie - post na blogu i linki do niestandardowych kodów atrybutów już nie działają - czy możesz opublikować ponownie?
littlechris
4
To rozwiązanie wymaga zmian po stronie klienta i serwera. Wiem, że potrzebowałeś tego dawno temu, ale równie dobrze mogę podać link do innego podejścia, które wykorzystuje prostą wtyczkę jQuery, która umożliwia konwersję dowolnego obiektu Javascript do postaci zrozumiałej przez domyślny spinacz modelu i powiązanie modelu z parametrami. Żadne filtry nie są potrzebne. erraticdev.blogspot.com/2010/12/… Nie wiem, jak rozwiązałeś błędy walidacji, ale mam też na to rozwiązanie: erraticdev.blogspot.com/2010/11/...
Robert Koritnik
3
Czy możesz podać źródło / pochodzenie JavaScriptConvert.DeserializeObject?
Matthieu
Jest to biblioteka Newtonsoft Json - jeśli otworzysz menedżera pakietów NuGet i wyszukasz w Newtonsoft, pojawi się ona dla Ciebie (teraz, gdy jest 2016). Prawdopodobnie jest to teraz oczywiste, ale na wypadek, gdyby ktoś się zastanawiał.
Robb Sadler
22

Filtry akcji, jquery stringify, bleh ...

Peter, ta funkcja jest natywna dla MVC. To jedna z rzeczy, które sprawiają, że MVC jest tak wspaniały.

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

A w akcji

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

Działa jak marzenie:

wprowadź opis obrazu tutaj

Jeśli używasz jQuery 1.4+, chcesz przyjrzeć się ustawianiu trybu tradycyjnego:

jQuery.ajaxSettings.traditional = true;

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

Działa to nawet w przypadku złożonych obiektów. Jeśli jesteś zainteresowany, powinieneś zajrzeć do dokumentacji MVC dotyczącej wiązania modelu: http://msdn.microsoft.com/en-us/library/dd410405.aspx

Levitikon
źródło
1
możesz mieć rację, ale segregator modelu JSON jest nowością w MVC3, a pytanie zostało zadane w 2008 roku, kiedy nie było to obsługiwane. Warto o tym wspomnieć w Twojej odpowiedzi.
Piotr Owsiak
3
Jak to jest przykład przekazywania tablicy złożonych obiektów ?
DuckMaestro
Nie, ale przykład nadal obowiązuje (MVC 3+). Dopóki nazwy parametrów są zgodne z modelem, którego oczekujesz, nie będziesz mieć żadnego problemu.
J. Mitchell
Kluczem jest tutaj utworzenie obiektu JSON z nazwą parametru metody („ids”), a następnie umieszczenie w nim tablicy złożonych obiektów. Dodatkowo ustaw trzeci parametr jako „true”, a zajmiesz się trybem tradycyjnym.
czerwono 510
11

W .NET4.5, MVC 5nie ma potrzeby widgetów.

JavaScript:

obiekt w JS: wprowadź opis obrazu tutaj

mechanizm, który publikuje.

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

DO#

Przedmioty:

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

Kontroler:

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

Obiekt otrzymany:

wprowadź opis obrazu tutaj

Mam nadzieję, że zaoszczędzi ci to trochę czasu.

Matas Vaitkevicius
źródło
8

W kierunku drugiej połowy tworzenia Create REST API przy użyciu ASP.NET MVC, który mówi zarówno w formacie JSON, jak i zwykłym XML , zacytować:

Teraz musimy zaakceptować ładunek JSON i XML dostarczony przez HTTP POST. Czasami klient może chcieć przesłać kolekcję obiektów w jednym ujęciu do przetwarzania wsadowego. Mogą więc przesyłać obiekty w formacie JSON lub XML. W ASP.NET MVC nie ma natywnej obsługi do automatycznego analizowania opublikowanego formatu JSON lub XML i automatycznego mapowania na parametry akcji. Więc napisałem filtr, który to robi ”.

Następnie implementuje filtr akcji, który mapuje JSON na obiekty C # z pokazanym kodem.

anonimowy
źródło
Właśnie pisałem swoją odpowiedź. Ale i tak to opublikuję ;-)
JSC
7

Najpierw pobierz ten kod JavaScript, JSON2.js , który pomoże nam serializować obiekt do postaci ciągu.

W moim przykładzie wysyłam wiersze jqGrid przez 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");
            }
        }
    });

Teraz na kontrolerze:

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

Utwórz klasę JsonFilter (dzięki referencjom 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;
            }
        }
    }

Utwórz inną klasę, aby filtr mógł przeanalizować ciąg JSON do rzeczywistego obiektu, którym można manipulować: Ta klasa comissionsJS to wszystkie wiersze mojego 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; }
    }

Mam nadzieję, że ten przykład pomoże zilustrować, jak opublikować złożony obiekt.

Sanchitos
źródło
-1
    [HttpPost]
    public bool parseAllDocs([FromBody] IList<docObject> data)
    {
        // do stuff

    }
JsonW
źródło
-1

O mój Boże. nie trzeba robić nic specjalnego. tylko w sekcji postów wykonaj następujące czynności:

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

Na serwerze użyj tego:

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

ten link pomoże ci zrobić ...

mahdi moghimi
źródło