【问题标题】:MVC passing post parameter to a dictionaryMVC 将 post 参数传递给字典
【发布时间】:2017-01-30 13:47:17
【问题描述】:

我的 MVC 应用程序在处理 FormulaData 对象后返回 ResultObjekt。这是一个通过 HTTP-Post 调用的 REST API

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

}

问题:有没有办法将values 中的所有属性读入Dictionary<string, string>IEnumerable<KeyValuePair<string, string>>

例如

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

应该生成Dictionary<string,string>()IEnumerable<KeyValuePair<string, string>>

{ {"Item1","Value1"}, {"Item2","Value2"}}

我之前的解决方案使用QuerystringHttpGet 而不是HttpPost,因为我改变了,Request.GetQueryNameValuePairs().ToDictionary(x => x.Key, x => x.Value) 不再起作用。


这是我目前的 - 不是那么漂亮的解决方案:

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

【问题讨论】:

  • 您能不能只将values 参数定义为IDictionary&lt;string, object&gt;,除非您需要将其绑定到您的FormerData 类?
  • @Toshi, ResultObjekt GetResult([FromBody]Dictionary&lt;string, object&gt; values) 应该也可以工作
  • @Corporalis 我不能同时使用吗? FormularData 类和字典?
  • @Toshi 模型绑定不能这样工作。这是一个或另一个。要么保留你的模型,然后使用反射来构建字典,要么使用字典作为模型。
  • @Toshi,举例说明你打算如何通过模型。

标签: c# asp.net-mvc


【解决方案1】:

正如许多 cmets 中已经提到的,理想情况下应该使用可以保存表单值的模型。根据我的观点,这也是最干净的方式,因为我发现它更有条理。

如果您需要同时访问两者,请首先尝试在可能的情况下重构/重构代码。在我看来,考虑到表单数据是模型数据的子集,为什么要在已经绑定到我们的模型时尝试访问原始表单数据。

如果重构/重组是不可能的,并且您需要同时访问这两者,那么有几种方法可以做到这一点。

  1. 选项1:使用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. 选项2:使用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");
    }
    

希望这会有所帮助。

更新:正如Lali 也指出,无论您使用FormCollection 还是Request.Form,您都可以将其转换为字典:formData.AllKeys.ToDictionary(k =&gt; k, v =&gt; formData[v])(未经测试),因为两者都是类型为NameValueCollection

【讨论】:

    【解决方案2】:

    虽然使用反射可能会影响性能,但您可以使用带有反射的 linq 将模型转换为字典。

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

    可以通过缓存从GetProperties 返回的属性信息来提高性能。如果需要,也可以将上述 linq 转换为扩展方法以供重复使用。

    【讨论】:

      【解决方案3】:

      我认为你无缘无故地让你的生活变得困难。
      如果您需要将您的类视为字典,只需实现一个隐式运算符,如下例所示

      如果你只是想迭代对象,你可以实现 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();
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        扩展方法的威力可以在这里发挥出来。

        1. 为 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. 在 GetResult() 中调用 ConvertToDictionary() 为:

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

        【讨论】:

          猜你喜欢
          • 2016-06-03
          • 2021-12-14
          • 1970-01-01
          • 2011-10-05
          • 1970-01-01
          • 1970-01-01
          • 2011-01-01
          • 1970-01-01
          相关资源
          最近更新 更多