无法使用foreach迭代ViewModel

时间:2015-11-17 13:23:38

标签: c# .net asp.net-mvc

我有一个我创建的ViewModel文件:

public class MyViewModel
{
    public string AString { get; set; }
    public string BString { get; set; }
    public string CString { get; set; }
    public string DString { get; set; }
    public DateTimeOffset ADate { get; set; }
    public DateTimeOffset BDate { get; set; }
}

我正在尝试运行for-each语句来迭代项目,但我正在

  

MyViewModel不包含GetEnumerator

的公开定义

以下是我试图使用它的声明:

public ActionResult MyMethod(MyViewModel model)
{
    foreach(var item in model)
    {
        //add code here
    }
}

我不确定为什么会这样,有人可以帮忙吗?

编辑:ViewModel接受通过AJAX-get调用传递给它的数据。我只是填写必要的字段。我之所以这样做,是因为我不希望有一个接受超过20个内联参数的方法(字符串a,字符串b,字符串c,...)。使一个具有所有可能字段的ViewModel更有意义,并且AJAX调用将相应地填充这些字段。之后我想要做的是将这些值传递给服务,但是必须稍微更改它们才能使用旧服务。

服务期望:

serviceName(ID, GUID, NAME, parameters)
ID - string
GUID - GUID
NAME - string
parameters - new parameter { name = "[model.Name]", value = new List<string>(){ "[model.value]" }}

[model.Name]和[model.Value]通过迭代“如果使用正确的术语”填充我创建的模型来填充这些插槽。

4 个答案:

答案 0 :(得分:2)

您可以使用反射遍历模型中的所有公共属性:

var properties = typeof(MyViewModel).GetProperties();
foreach(var property in properties) 
{
    var propertyName = property.Name;
    var propertyValue = property.GetValue(model);
    //Now process the property
}

但请注意,反射会导致性能下降,如果有更好的替代方案,则不应使用反射。在您的情况下,看起来您可以很好地声明几个数组或字典来存储您的数据。例如:

public class MyViewModel
{
    public MyViewModel
    {
        TheStrings = new string[4];
        TheDates = new DateTimeOffset[2];
    }

    public string TheStrings { get; private set; }
    public DateTimeOffset TheDates { get; private set; }
}

现在您可以访问model.TheStrings[0]而不是model.AString,依此类推;使用带有键A,B,C,D的字典将进一步提高可读性,但想法是相同的。现在,您可以轻松地foreach字符串和日期。

答案 1 :(得分:0)

foreach适用于任何实现IEnumerable和数组的对象集合。在您的代码中,MyViewModel是一个POCO类,它没有实现Innumerable。

如果您发布的模型是MyViewModel的集合,您可以循环使用它们。例如,如果您要发布客户/产品列表,您将执行类似这样的操作

public ActionResult MyMethod (IEnumerable<MyViewModel> model)
{
  foreach(var product in model)
  {
    //You can access each property here
   //product.AString
  }
}

如果您只想阅读已发布模型的不同属性值,则不需要foreach。简单地说,阅读每个属性

public ActionResult MyMethod(MyViewModel model)
{
  var aStringVal =  model.AString;
  var bStringVal = model.BString;
  //Do something with the values.
}

如果你仍想获得MyViewModel的单个实例的所有属性,你应该使用反射来解决这个问题,就像Konamiman在他的回答中写的那样。

答案 2 :(得分:0)

C#与JavaScript完全不同:

  • 在C#中,foreach循环遍历一系列对象中的每个对象(IEnumerable)

  • 在JavaScript中,foreach循环遍历单个对象中每个属性的值。

在C#中,你不能轻易地遍历一个类中的每个属性,也不应该尝试这样做。
相反,如果您想要多个相同类型的属性,请使用wikipedia

foldr

答案 3 :(得分:0)

  

基于添加到问题的新信息

如果参数可以在每次调用时更改,那么使用具有固定属性的viewmodel将不适合您的情况。

请记住,C#是强类型的,您不能只发送您想要的任何值,只能发送已定义的值。

如果每个调用的参数都可以更改,那么您不能使用固定的viewmodel,因此将方法更改为name + value的字典:

 public ActionResult MyMethod(IDictionary<string, string> model)
 {
     var parameters = new List<Parameter>();
     foreach (var kvp in model)
     {
         parameters.Add(new parameter { name = kvp.Key, value = new List<string> { key.Value }});
     }
如果你有很多价值,这也可能是合适的。

您可以使用继承或具有字典属性的ViewModel,但这是必不可少的部分

如果参数始终相同,则明确使用值:

 public ActionResult MyMethod(IDictionary<string, string> model)
 {
     var parameters = new List<Parameter>();
     parameters.Add(new parameter { name = "AString", value = new List<string> { model.AString }});
     parameters.Add(new parameter { name = "BString", value = new List<string> { model.BString }});

但最有可能的情况是客户端正在定义参数。