I have MVC application that returns a ResultObjekt
after processing a FormulaData
object. That's a rest API called via HTTP-Post
[HttpPost]
[ActionName("GetResult")]
public ResultObjekt GetResult([FromBody]FormularData values)
{
}
Question: Is there a way to read all properties from values
into a Dictionary<string, string>
or a IEnumerable<KeyValuePair<string, string>>
?
e.g.
public class FormularData
{
public string Item1 { get; set; }
public string Item2 { get; set; }
}
should result into a Dictionary<string,string>()
or a IEnumerable<KeyValuePair<string, string>>
with 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)
doesn't work anymore.
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();
}
As already mentioned by many in the comments that ideally one should use a model that can hold the values from the form. This is also the cleanest way as per my opinion, as I find it more structured.
If you need to access both at the same time, first try to refactor/restructure the code if possible. In my opinion why try to access the raw form data when that is already bound to our model, considering 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 couple of ways to do that.
Option1: 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");
}
Option2: 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 also pointed out by Lali, whether you use FormCollection
or Request.Form
, you can convert that into dictionary as: formData.AllKeys.ToDictionary(k => k, v => formData[v])
(untested), as both are of type NameValueCollection
While using reflection may 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 the property info returned from GetProperties
. The above linq can also be converted to an extension method for reuse if desired.
I think you are making your life difficult for no reason.
If you need to treat your class as a dictionary just implement an implicit operator like in the following example
If you just want to iterate on the 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();
}
}
}
The power of Extension methods can be used out here.
Define an extension for 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();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With