MVC passing post parameter to dictionary

I have an MVC application that returns ResultObjekt after processing a FormulaData object. This is an API for relaxing through HTTP Post

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

Question: Is there a way to read all the properties from values in a Dictionary<string, string> or IEnumerable<KeyValuePair<string, string>> ?

eg.

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

should result in Dictionary<string,string>() or IEnumerable<KeyValuePair<string, string>>

with the values { {"Item1","Value1"}, {"Item2","Value2"}}

My previous solution worked with Querystring and HttpGet instead of HttpPost , and since I changed, Request.GetQueryNameValuePairs().ToDictionary(x => x.Key, x => x.Value) no longer works.


Here is my current - not so pretty solution:

 [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(); } 
+6
source share
4 answers

As many have already mentioned in the comments, ideally you should use a model that can hold values ​​from a form. This is also the cleanest way, in my opinion, as I find it more structured.

If you need to access both at the same time, first try reorganizing / restructuring the code, if possible. In my opinion, why try to access raw form data when it is already connected with our model, given that the form data is a subset of the model data.

If refactoring / restructuring is not possible and you need to access both, then there are several ways to do this.

  • Option 1: use 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"); } 
  • Option 2: use 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"); } 

Hope this helps.

Update: As Lali also pointed out, whether you FormCollection or Request.Form , you can convert this to an as: formData.AllKeys.ToDictionary(k => k, v => formData[v]) (untested) formData.AllKeys.ToDictionary(k => k, v => formData[v]) , as both have type NameValueCollection

+8
source

When using reflection can have a performance hit, you can convert the model to a dictionary using linq with reflection.

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

performance can be improved by caching property information returned from GetProperties . The aforementioned linq can also be converted to an extension method for reuse if necessary.

+4
source

I think you make your life difficult for no reason.
If you need to consider your class as a dictionary, just implement the implicit operator, as in the following example

If you just want to iterate over an object, you can just implement 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
source

Here you can use the power of extension methods.

  • Define an extension for the FormularData class:

      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; } } 
  • Call ConvertToDictionary () in GetResult () as:

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

Source: https://habr.com/ru/post/1014554/


All Articles