2017-01-30 9 views
6

Mam aplikację MVC, która zwraca ResultObjekt po przetworzeniu obiektu FormulaData. To odpoczynek API o nazwie poprzez HTTP-PostMVC przekazujący parametr postu do słownika

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

} 

Pytanie: Czy istnieje sposób, aby odczytać wszystkie właściwości z values w Dictionary<string, string> lub IEnumerable<KeyValuePair<string, string>>?

np.

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

powinny wynik w Dictionary<string,string>() lub IEnumerable<KeyValuePair<string, string>>

z wartościami { {"Item1","Value1"}, {"Item2","Value2"}}

Moje poprzednie rozwiązanie pracował z Querystring i HttpGet zamiast HttpPost i odkąd zmienił Request.GetQueryNameValuePairs().ToDictionary(x => x.Key, x => x.Value) już nie działa.


Oto mój obecny - nie tak całkiem rozwiązanie:

[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(); 
} 
+2

Nie można po prostu zdefiniować 'values' param jako 'IDictionary ', chyba że potrzebujesz go powiązanego z twoją klasą FormularData? – Corporalis

+3

@Toshi, 'ResultObjekt GetResult ([FromBody] Dictionary values)' Powinien także działać – Nkosi

+0

@Corporalis nie mogę używać obu? klasa FormularData i słownik? – Toshi

Odpowiedz

8

Jak już wspomniano przez wielu w komentarzach, że idealnie należy zastosować model, który może pomieścić wartości z formularza. Jest to również najczystszy sposób według mojej opinii, ponieważ uważam, że jest bardziej uporządkowany.

Jeśli chcesz uzyskać dostęp do obu w tym samym czasie, najpierw spróbuj przerobić/zrestrukturyzować kod, jeśli to możliwe. Moim zdaniem, dlaczego staram się uzyskać dostęp do surowych danych formularza, gdy jest to już związane z naszym modelem, biorąc pod uwagę, że dane formularza są podzbiorem danych modelu.

Jeśli refaktoryzacja/restrukturyzacja nie jest możliwa i trzeba uzyskać dostęp do obu, istnieje kilka sposobów, aby to zrobić.

  1. Opcja 1: Użyj 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. Opcja 2: Użyj 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"); 
    } 
    

Nadzieja to pomaga.

Aktualizacja: Jak wskazał również przez Lali, czy używasz FormCollection lub Request.Form można przekonwertować do słownika jak: formData.AllKeys.ToDictionary(k => k, v => formData[v]) (niesprawdzone), ponieważ oba są typu NameValueCollection

4

Podczas korzystania odbicie może mieć hit wydajności można przekonwertować model do słownika za pomocą linq z refleksji.

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

Wydajność można poprawić, buforując informacje o nieruchomości zwrócone z GetProperties. Powyższy linq można również przekonwertować na metodę rozszerzenia w celu ponownego użycia w razie potrzeby.

1

Myślę, że utrudniasz sobie życie bez powodu.
Jeśli trzeba traktować swoją klasę jako słowniku prostu zaimplementować operator niejawny jak w poniższym przykładzie

Jeśli chcesz tylko do iteracji na obiekt, można po prostu zaimplementować 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(); 
     } 
    } 
} 
1

Moc Metody rozszerzeń można wykorzystać tutaj.

  1. Określ rozszerzenie dla klasy 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. połączeń ConvertToDictionary() w getResult() jako:

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