6 votes

MVC passe le paramètre post à un dictionnaire

J'ai une application MVC qui renvoie un ResultObjekt après avoir traité un FormulaData objet. C'est une API de repos appelée via HTTP-Post.

[HttpPost]
[ActionName("GetResult")]
public ResultObjekt GetResult([FromBody]FormularData values)
{

}

Question : Existe-t-il un moyen de lire toutes les propriétés de values en un Dictionary<string, string> ou un IEnumerable<KeyValuePair<string, string>> ?

par exemple

public class FormularData
{
    public string Item1 { get; set; }
    public string Item2 { get; set; }
}

devrait donner lieu à un Dictionary<string,string>() ou un IEnumerable<KeyValuePair<string, string>>

avec des valeurs { {"Item1","Value1"}, {"Item2","Value2"}}

Ma solution précédente fonctionnait avec Querystring y HttpGet au lieu de HttpPost et depuis que j'ai changé, Request.GetQueryNameValuePairs().ToDictionary(x => x.Key, x => x.Value) ne fonctionne plus.


Voici ma solution actuelle - pas très jolie :

[HttpPost]
[ActionName("GetResult")]
public ResultObjekt GetResult([FromBody]FormularData values)
{
    List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
    if (!string.IsNullOrEmpty(values.Item1))
    {
        list.Add(new KeyValuePair<string, string>("Item1", values.Item1));
    }
    if (!string.IsNullOrEmpty(values.Item2))
    {
        list.Add(new KeyValuePair<string, string>("Item2", values.Item2));
    }
    IEnumerable<KeyValuePair<string, string>> result = list.AsEnumerable();
}

9voto

Sayan Pal Points 2347

Comme cela a déjà été mentionné par de nombreuses personnes dans les commentaires, l'idéal est d'utiliser un modèle qui peut contenir les valeurs du formulaire. C'est aussi la méthode la plus propre à mon avis, car je la trouve plus structurée.

Si vous devez accéder aux deux en même temps, essayez d'abord de refactoriser/restructurer le code si possible. À mon avis, pourquoi essayer d'accéder aux données brutes du formulaire alors qu'elles sont déjà liées à notre modèle, étant donné que les données du formulaire sont un sous-ensemble des données du modèle.

Si le remaniement/restructuration n'est pas possible et que vous devez accéder aux deux, il existe plusieurs façons de le faire.

  1. Option1 : utiliser FormCollection :

    [HttpPost]
    public ResultObjekt GetResult(FormCollection formCol, FormularData model)
    {
        //Note that here both FormCollection and FormularData are used.
        //To get values from FormCollection use something like below:
        var item1 = formCol.Get("Item1");
    }
  2. Option2 : Utiliser Request.Form :

    [HttpPost]
    public ResultObjekt GetResult(FormularData model)
    {
        //To get values from Form use something like below:
        var formData = Request.Form;
        var item1 = formData.Get("Item1");
    }

J'espère que cela vous aidera.

Mise à jour : Comme l'a également souligné Lali que vous utilisiez FormCollection o Request.Form vous pouvez le convertir en dictionnaire : formData.AllKeys.ToDictionary(k => k, v => formData[v]) (non testé), car les deux sont de type NameValueCollection

4voto

Nkosi Points 95895

Bien que l'utilisation de la réflexion puisse avoir un impact sur les performances, vous pouvez convertir le modèle en dictionnaire en utilisant linq avec réflexion.

[HttpPost]
[ActionName("GetResult")]
public ResultObjekt GetResult([FromBody]FormularData values)
{
    var result = values.GetType()
                     .GetProperties()
                     .ToDictionary(pi => pi.Name, pi => (string)pi.GetValue(values));
}

Les performances peuvent être améliorées par la mise en cache des informations sur les propriétés renvoyées par la fonction GetProperties . La linq ci-dessus peut également être convertie en une méthode d'extension pour être réutilisée si on le souhaite.

1voto

George Vovos Points 1049

Je pense que vous vous rendez la vie difficile sans raison.
Si vous devez traiter votre classe comme un dictionnaire, implémentez simplement un opérateur implicite comme dans l'exemple suivant

Si vous voulez simplement itérer sur l'objet, vous pouvez implémenter IEnumerable.

using System;
using System.Collections;
using System.Collections.Generic;

namespace ConsoleApplication5
{
    class Program
    {

        static void Main(string[] args)
        {
            FormularData data = new FormularData() { Item1 = "aa", Item2 = "bb" };
            //Dictionary<string, string> dictionary = data;
            foreach (var item in data)
                Console.WriteLine(item);

            Console.ReadLine();
        }
    }

    public class FormularData : IEnumerable<KeyValuePair<string,string>>
    {
        public string Item1 { get; set; }
        public string Item2 { get; set; }

        public static implicit operator Dictionary<string, string>(FormularData obj)
        {
            var list = new Dictionary<string, string>();
            if (!string.IsNullOrEmpty(obj.Item1))
                list.Add("Item1", obj.Item1);
            if (!string.IsNullOrEmpty(obj.Item2))
                list.Add("Item2", obj.Item2);
            return list;
        }

        public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
        {
            return ((Dictionary<string, string>)this).GetEnumerator();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    }
}

1voto

RRM Points 192

La puissance des méthodes d'extension peut être utilisée ici.

  1. Définir une extension pour la classe FormularData :

             public static class FormularDataExtensions
             {
                public static Dictionary<string, string> ConvertToDictionary(this FormularData formularData)
                {
                  var dictionary = new Dictionary<string, string>();
                  if (!string.IsNullOrEmpty(formularData.Item1))
                      dictionary.Add(nameof(formularData.Item1), formularData.Item1);
                  if (!string.IsNullOrEmpty(formularData.Item2))
                      dictionary.Add(nameof(formularData.Item2), formularData.Item2);
    
                 return dictionary;
                }
             }
  2. Appelez ConvertToDictionary() dans GetResult() comme :

    [HttpPost]
    [ActionName("GetResult")]
    public ResultObjekt GetResult([FromBody]FormularData values)
    {
        var dictionary = values.ConvertToDictionary();
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X