Jak mogę wysłać tablicę ciągów do kontrolera ASP.NET MVC bez formularza?

185

Tworzę małą aplikację do nauki ASP.NET MVC i JQuery, a jedna ze stron to lista elementów, w których można wybrać niektóre. Następnie chciałbym nacisnąć przycisk i wysłać do mojego kontrolera Listę (lub coś równoważnego) zawierającą identyfikatory wybranych elementów, używając funkcji Post JQuery.

Udało mi się uzyskać tablicę z identyfikatorami wybranych elementów, a teraz chcę to opublikować. Jednym ze sposobów, w jaki mogę to zrobić, jest umieszczenie na mojej stronie fałszywego formularza z ukrytą wartością, a następnie ustawienie ukrytej wartości dla wybranych elementów i opublikowanie tego formularza; jednak wygląda to nieładnie.

Czy istnieje prostszy sposób na osiągnięcie tego celu, wysyłając tablicę bezpośrednio do kontrolera? Próbowałem kilku różnych rzeczy, ale wygląda na to, że kontroler nie może zmapować odbieranych danych. Oto kod do tej pory:

function generateList(selectedValues) {
   var s = {
      values: selectedValues //selectedValues is an array of string
   };
   $.post("/Home/GenerateList", $.toJSON(s), function() { alert("back") }, "json");
}

A potem mój kontroler wygląda tak

public ActionResult GenerateList(List<string> values)
{
    //do something
}

Wszystko, co udało mi się uzyskać, to „null” w parametrze kontrolera ...

Jakieś wskazówki?

rodbv
źródło
Chociaż możesz uzyskać dostęp do tych samych danych, używającRequest["values[]"]
Tocco

Odpowiedzi:

247

Zmodyfikowałem swoją odpowiedź, aby uwzględnić kod aplikacji testowej, którą zrobiłem.

Aktualizacja: Zaktualizowałem jQuery, aby ustawić „tradycyjne” ustawienie na true, więc to zadziała ponownie (zgodnie z odpowiedzią @DustinDavis).

Najpierw javascript:

function test()
{
    var stringArray = new Array();
    stringArray[0] = "item1";
    stringArray[1] = "item2";
    stringArray[2] = "item3";
    var postData = { values: stringArray };

    $.ajax({
        type: "POST",
        url: "/Home/SaveList",
        data: postData,
        success: function(data){
            alert(data.Result);
        },
        dataType: "json",
        traditional: true
    });
}

A oto kod w mojej klasie kontrolera:

public JsonResult SaveList(List<String> values)
{
    return Json(new { Result = String.Format("Fist item in list: '{0}'", values[0]) });
}

Kiedy wywołuję tę funkcję javascript, pojawia się komunikat „Pierwszy element na liście:„ item1 ””. Mam nadzieję że to pomoże!

MrDustpan
źródło
3
Dobrze, że znalazłem tę odpowiedź, teraz jestem w stanie wysłać tablicę Guida, a Action odbiera je na Listę <Guid>. Dzięki
Tx3
43
Należy tu zwrócić uwagę na dwie ważne rzeczy. 1) dataType: „json” 2.) tradycyjny: prawda. Bez nich tablica łańcuchów nie będzie przekazywana do metod akcji
Thanigainathan
1
Zauważ, że dataType: 'JSON'powoduje to, że jQuery próbuje parsować odpowiedź jako JSON i popełni błąd, jeśli nie jest to prawidłowy JSON.
sennett
8
@Thanigainathan dataType: 'json'jest dla typu zwracanego i nie jest wymagane, aby wysłać tablicę do działania. contentType: "application/json; charset=utf-8", jest tym, ale w niektórych przypadkach takich jak to nie jest wymagane.
Ruchan
1
@emzero usevar postData = { id: 45, [{myClassProp1: 1, myClassProp2: 2}, {}...], anotherParam: "some string" };
Nick M
108

FYI: JQuery zmienił sposób serializacji danych postu.

http://forum.jquery.com/topic/nested-param-serialization

Musisz ustawić „Tradycyjne” ustawienie na „prawda”, w innym przypadku

{ Values : ["1", "2", "3"] }

wyjdzie jako

Values[]=1&Values[]=2&Values[]=3

zamiast

Values=1&Values=2&Values=3
Dustin Davis
źródło
8
To sprawiło, że na chwilę podrapałem się po głowie. ustawienie $.ajax({ ..., traditional: true});pomoże przywrócić tradycyjną serializację.
juhan_h
Potrzebowałem tego, aby trasa ASP.NET MVC poprawnie zużywała prostą tablicę js wartości ciągów.
BrandonG
Twoja odpowiedź jest naprawdę pomocna. Mam taką samą sytuację, ale tak jest z ints. Kiedy używam traditional: true, działa, twoja odpowiedź i link wyjaśnia dlaczego . Działa również, gdy używam type: "POST", bez użycia traditional: true. Dlaczego? Czy możesz prosić o rozwinięcie. Do Twojej wiadomości używam Asp.Net Mvc.
barnes
Czy w ASP.NET istnieje sposób na parsowanie takiej anonimowej tablicy bez indeksów? Wartości [] = 1 i wartości [] = 2 i wartości [] = 3
Charles Owen
24

Dziękuję wszystkim za odpowiedzi. Innym szybkim rozwiązaniem będzie użycie metody jQuery.param z tradycyjnym parametrem ustawionym na true, aby przekonwertować obiekt JSON na ciąg znaków:

$.post("/your/url", $.param(yourJsonObject,true));
Evgenii
źródło
Działa dobrze i doskonale do mnie pasuje, ponieważ używam $ .post () zamiast $ .ajax (). Dziękuję Ci !
AFract
6

w .NET4.5,MVC 5

JavaScript:

obiekt w JS: wprowadź opis zdjęcia 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#

Obiekty:

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 zdjęcia tutaj

Mam nadzieję, że to pozwoli Ci zaoszczędzić trochę czasu.

Matas Vaitkevicius
źródło
4

Kolejna implementacja, która działa również z listą obiektów, a nie tylko ciągami znaków:

JS:

var postData = {};
postData[values] = selectedValues ;

$.ajax({
    url: "/Home/SaveList",
    type: "POST",
    data: JSON.stringify(postData),
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function(data){
        alert(data.Result);
    }
});

Zakładając, że „selectedValues” to Array of Objects.

W kontrolerze parametrem jest lista odpowiednich modeli ViewModels.

public JsonResult SaveList(List<ViewModel> values)
{    
    return Json(new { 
          Result = String.Format("Fist item in list: '{0}'", values[0].Name) 
    });
}
d.popov
źródło
1

Jak omówiono tutaj ,

jeśli chcesz przekazać niestandardowy obiekt JSON do akcji MVC, możesz użyć tego rozwiązania, działa jak urok.

public string GetData() {
  // InputStream contains the JSON object you've sent
  String jsonString = new StreamReader(this.Request.InputStream).ReadToEnd();

  // Deserialize it to a dictionary
  var dic =
    Newtonsoft.Json.JsonConvert.DeserializeObject < Dictionary < String,
    dynamic >> (jsonString);

  string result = "";

  result += dic["firstname"] + dic["lastname"];

  // You can even cast your object to their original type because of 'dynamic' keyword
  result += ", Age: " + (int) dic["age"];

  if ((bool) dic["married"])
    result += ", Married";

  return result;
}

Prawdziwą zaletą tego rozwiązania jest to, że nie trzeba definiować nowej klasy dla każdej kombinacji argumentów, a ponadto można łatwo rzutować obiekty na ich oryginalne typy.

Możesz użyć takiej metody pomocniczej, aby ułatwić sobie pracę:

public static Dictionary < string, dynamic > GetDic(HttpRequestBase request) {
  String jsonString = new StreamReader(request.InputStream).ReadToEnd();
  return Newtonsoft.Json.JsonConvert.DeserializeObject < Dictionary < string, dynamic >> (jsonString);
}
Mohsen Afshin
źródło
0

Możesz ustawić parametr globalny za pomocą

jQuery.ajaxSettings.traditional = true;
mr_squall
źródło