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)

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


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


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.


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.


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.


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

    }

-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ć ...

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.