Wie kann ich ein Array von Zeichenfolgen ohne Formular an ASP.NET MVC Controller senden?

185

Ich erstelle eine kleine App, um mir ASP.NET MVC und JQuery beizubringen, und eine der Seiten enthält eine Liste von Elementen, in denen einige ausgewählt werden können. Dann möchte ich einen Knopf drücken und eine Liste (oder etwas Ähnliches) an meinen Controller senden, die die IDs der ausgewählten Elemente enthält, und zwar mithilfe der Post-Funktion von JQuery.

Ich habe es geschafft, ein Array mit den IDs der ausgewählten Elemente zu erhalten, und jetzt möchte ich das veröffentlichen. Eine Möglichkeit, dies zu tun, besteht darin, auf meiner Seite ein Dummy-Formular mit einem ausgeblendeten Wert zu haben und dann den ausgeblendeten Wert mit den ausgewählten Elementen festzulegen und dieses Formular zu veröffentlichen. das sieht allerdings mürrisch aus.

Gibt es eine sauberere Möglichkeit, dies zu erreichen, indem das Array direkt an die Steuerung gesendet wird? Ich habe ein paar verschiedene Dinge ausprobiert, aber es sieht so aus, als ob der Controller die empfangenen Daten nicht zuordnen kann. Hier ist der Code bisher:

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

Und dann sieht mein Controller so aus

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

Alles, was ich bekommen habe, ist eine "Null" im Controller-Parameter ...

Irgendwelche Tipps?

rodbv
quelle
Sie können jedoch auf dieselben Daten zugreifen, indem SieRequest["values[]"]
Tocco

Antworten:

246

Ich habe meine Antwort so geändert, dass sie den Code für eine Test-App enthält, die ich erstellt habe.

Update: Ich habe die jQuery aktualisiert, um die 'traditionelle' Einstellung auf true zu setzen, damit dies wieder funktioniert (gemäß der Antwort von @DustinDavis).

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

Und hier ist der Code in meiner Controller-Klasse:

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

Wenn ich diese Javascript-Funktion aufrufe, erhalte ich eine Warnung mit der Aufschrift "Erstes Element in der Liste: 'Element1'". Hoffe das hilft!

MrDustpan
quelle
3
Es ist gut, dass ich diese Antwort gefunden habe. Jetzt kann ich eine Reihe von Guids senden und Action empfängt sie an List <Guid>. Danke
Tx3
43
Hier sind zwei wichtige Dinge zu beachten. 1) Datentyp: "json" 2.) Traditionell: wahr. Ohne sie wird das String-Array nicht an Aktionsmethoden übergeben
Thanigainathan
1
Beachten Sie, dataType: 'JSON'dass jQuery versucht, die Antwort als JSON zu analysieren, und dass ein Fehler auftritt, wenn JSON nicht gültig ist.
Sennett
8
@Thanigainathan the dataType: 'json'ist für den Rückgabetyp und muss kein Array an Action senden. contentType: "application/json; charset=utf-8"ist die eine, aber in einigen Fällen ist dies nicht erforderlich.
Ruchan
1
@emzero verwendenvar postData = { id: 45, [{myClassProp1: 1, myClassProp2: 2}, {}...], anotherParam: "some string" };
Nick M
108

Zu Ihrer Information: JQuery hat die Art und Weise geändert, wie Post-Daten serialisiert werden.

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

Sie müssen die Einstellung "Traditionell" auf "wahr" setzen, andernfalls

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

wird als herauskommen

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

anstatt

Values=1&Values=2&Values=3
Dustin Davis
quelle
8
Dies ist etwas, das mich für eine Weile den Kopf kratzen ließ. Die Einstellung $.ajax({ ..., traditional: true});hilft dabei, zur herkömmlichen Serialisierung zurückzukehren.
juhan_h
Ich brauchte dies, damit eine ASP.NET MVC-Route ein einfaches js-Array von Zeichenfolgenwerten ordnungsgemäß verwendet.
BrandonG
Ihre Antwort ist wirklich hilfreich. Ich habe die gleiche Situation, aber es ist mit ints. Wenn ich es benutze traditional: true, funktioniert es. Ihre Antwort und Ihr Link erklären das Warum . Es funktioniert auch, wenn ich es benutze type: "POST", ohne es zu benutzen traditional: true. Warum ist das so? Könnten Sie bitte näher darauf eingehen? Zu Ihrer Information Ich benutze Asp.Net Mvc.
Barnes
Gibt es in ASP.NET eine Möglichkeit, ein anonymes Array wie dieses ohne Indizes zu analysieren? Werte [] = 1 & Werte [] = 2 & Werte [] = 3
Charles Owen
24

Vielen Dank an alle für die Antworten. Eine weitere schnelle Lösung besteht darin, die Methode jQuery.param mit dem traditionellen Parameter true zu verwenden, um das JSON-Objekt in einen String zu konvertieren:

$.post("/your/url", $.param(yourJsonObject,true));
Evgenii
quelle
Funktioniert gut und passt perfekt zu mir, da ich $ .post () anstelle von $ .ajax () verwende. Danke !
Nach dem
9

Veröffentlichen Sie die Daten nicht als Array. Um an eine Liste zu binden, sollten die Schlüssel / Wert-Paare für jeden Schlüssel mit demselben Wert gesendet werden.

Sie sollten dazu kein Formular benötigen. Sie benötigen lediglich eine Liste von Schlüssel / Wert-Paaren, die Sie in den Aufruf von $ .post aufnehmen können.

Craig Stuntz
quelle
3
Vielen Dank. Die aktualisierte URL lautet: haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Wiebe Tijsma
6

In .NET4.5,MVC 5

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
4

Eine weitere Implementierung, die auch mit der Liste von Objekten arbeitet, nicht nur mit Zeichenfolgen:

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

Angenommen, 'selectedValues' ist ein Array von Objekten.

In der Steuerung ist der Parameter eine Liste der entsprechenden ViewModels.

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

Wie ich hier besprochen habe ,

Wenn Sie ein benutzerdefiniertes JSON-Objekt an eine MVC-Aktion übergeben möchten, können Sie diese Lösung verwenden. Sie funktioniert wie ein Zauber.

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

Der eigentliche Vorteil dieser Lösung besteht darin, dass Sie nicht für jede Kombination von Argumenten eine neue Klasse definieren müssen. Außerdem können Sie Ihre Objekte problemlos in ihre ursprünglichen Typen umwandeln.

Sie können eine Hilfsmethode wie diese verwenden, um Ihre Arbeit zu erleichtern:

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
quelle
0

Sie können globale Parameter mit einrichten

jQuery.ajaxSettings.traditional = true;
mr_squall
quelle