web-dev-qa-db-fra.com

Comment puis-je publier un tableau de chaîne sur ASP.NET MVC Controller sans formulaire?

Je crée une petite application pour m'apprendre à utiliser ASP.NET MVC et JQuery, et l'une des pages contient une liste d'éléments dans lesquels certains peuvent être sélectionnés. Ensuite, j'aimerais appuyer sur un bouton et envoyer à mon contrôleur une liste (ou quelque chose d'équivalent) contenant les identifiants des éléments sélectionnés à l'aide de la fonction Post de JQuery.

J'ai réussi à obtenir un tableau avec les identifiants des éléments sélectionnés, et maintenant je veux le poster. Une façon de le faire est d’avoir un formulaire factice dans ma page, avec une valeur cachée, puis de définir la valeur cachée avec les éléments sélectionnés et d’envoyer ce formulaire; cela a l'air cruel, cependant.

Existe-t-il un moyen plus simple d’atteindre cet objectif en envoyant la matrice directement au contrôleur? J'ai essayé différentes choses, mais il semble que le contrôleur ne puisse pas mapper les données qu'il reçoit. Voici le code jusqu'à présent:

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

Et puis mon contrôleur ressemble à ceci

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

Tout ce que j'ai réussi à obtenir est un "null" dans le paramètre du contrôleur ...

Des conseils?

177
rodbv

J'ai modifié ma réponse pour inclure le code d'une application test que j'ai créée.

Mise à jour: jQuery a été mis à jour pour définir le paramètre "traditionnel" sur true afin que cela fonctionne à nouveau (selon la réponse de @DustinDavis).

D'abord le 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
    });
}

Et voici le code dans ma classe de contrôleur:

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

Lorsque j'appelle cette fonction javascript, je reçois une alerte disant "Premier élément de la liste:" élément1 "". J'espère que cela t'aides!

242
MrDustpan

FYI: JQuery a changé la façon dont ils sérialisent les données de publication.

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

Vous devez définir le paramètre "Traditionnel" sur true, sinon

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

sortira comme

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

au lieu de

Values=1&Values=2&Values=3
106
Dustin Davis

Merci à tous pour les réponses. Une autre solution rapide consiste à utiliser la méthode jQuery.param avec le paramètre traditionnel défini sur true pour convertir un objet JSON en chaîne:

$.post("/your/url", $.param(yourJsonObject,true));
24
Evgenii

Ne postez pas les données sous forme de tableau. Pour se lier à une liste, les paires clé/valeur doivent être soumises avec la même valeur pour chaque clé.

Vous ne devriez pas avoir besoin d'un formulaire pour le faire. Vous avez juste besoin d'une liste de paires clé/valeur, que vous pouvez inclure dans l'appel à $ .post.

8
Craig Stuntz

Dans .NET4.5, MVC 5

Javascript:

objet dans JS: enter image description here

mécanisme qui poste.

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

C #

Objets:

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

Manette:

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

Objet reçu:

enter image description here

J'espère que cela vous fait gagner du temps.

6
Matas Vaitkevicius

Une autre implémentation qui fonctionne également avec une liste d'objets, pas seulement des chaînes:

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

En supposant que 'selectedValues' est un tableau d'objets.

Dans le contrôleur, le paramètre est une liste des ViewModels correspondants.

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

Comme j'ai discuté ici ,

si vous souhaitez passer d'un objet JSON personnalisé à une action MVC, vous pouvez utiliser cette solution, elle fonctionne comme un charme.

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

L'avantage réel de cette solution est que vous n'avez pas besoin de définir une nouvelle classe pour chaque combinaison d'arguments. De plus, vous pouvez facilement convertir les objets en leurs types d'origine.

et vous pouvez utiliser une méthode d'assistance comme celle-ci pour faciliter votre travail

public static Dictionary<string, dynamic> GetDic(HttpRequestBase request)
{
    String jsonString = new StreamReader(request.InputStream).ReadToEnd();
    return Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString);
}
1
Mohsen Afshin

Vous pouvez configurer un paramètre global avec

jQuery.ajaxSettings.traditional = true;
0
mr_squall