【问题标题】:How to convert List<IEnumerable<ProductViewModel>> into <IEnumerable<ProductViewModel>>?如何将 List<IEnumerable<ProductViewModel>> 转换为 <IEnumerable<ProductViewModel>>?
【发布时间】:2017-01-10 18:21:37
【问题描述】:

我正在从类别的ICollection&lt;Product&gt; Products 属性访问数据。如果您查看下面的控制器代码,使用第二个选择,我将每个产品的 Form 从 Product 实体更改为返回 IQueryable&lt;IEnumerable&lt;ProductViewModel&gt;&gt; 的 ProductViewModel。

最后,使用ToListAsync() 方法,模型返回一个List&lt;IEnumerable&lt;ProductViewModel&gt;&gt;,我的View 不接受它。

我的控制器型号是这样的:

var model = (await db.Categories.Where(c => c.Id == id).Select(p => p.Products.Select(x => new 
                    ProductViewModel { Id = x.Id, Name = x.Name,  ByteImage = x.Image, Price = x.Price})).ToListAsync());

            return View(model);

这个模型的返回类型是List&lt;IEnumerable&lt;ProductViewModel&gt;&gt;,我不能在我的视图中遍历这个模型来显示数据。

View的视图模型是:

@model IEnumerable&lt;ProductViewModel&gt;.

这是我收到的错误消息:

编译器错误消息:CS0411:无法从用法推断方法“DisplayNameExtensions.DisplayNameFor(HtmlHelper, Expression>)”的类型参数。尝试明确指定类型参数。

Source Error:

Line 14:     <tr>
Line 15:         <th>
Line 16:             @Html.DisplayNameFor(model => model.Name)
Line 17:             
Line 18:         </th>

产品视图模型:

public class ProductViewModel
    {
        public int Id { get; set; }
        [Required, Display(Name="Product Name")]
        public string Name { get; set; }
        [Required, DataType(DataType.Upload)]
        public HttpPostedFileBase Image { get; set; }
        public string OutputImage { get; set; }
        public Byte[] ByteImage { get; set; }
        [Required]
        public Decimal Price { get; set; }

        public static byte[] ConvertToByte(ProductViewModel model)
        {
            if (model.Image != null)
            {
                byte[] imageByte = null;
                BinaryReader rdr = new BinaryReader(model.Image.InputStream);
                imageByte = rdr.ReadBytes((int)model.Image.ContentLength);

                return imageByte;
            }

            return null;
        }

        // ViewModel => Model | Implicit type Operator
        public static implicit operator Product(ProductViewModel viewModel)
        {
            var model = new Product
            {
                Id = viewModel.Id,
                Name = viewModel.Name,
                Image = ConvertToByte(viewModel),
                Price = viewModel.Price
            };

            return model;
        }

        // Model => ViewModel | Implicit type Operator
        public static implicit operator ProductViewModel(Product model)
        {
            var viewModel = new ProductViewModel
            {
                Id = model.Id,
                Name = model.Name,
                OutputImage = string.Format("data:image/jpg;base64,{0}", Convert.ToBase64String(model.Image)),
                Price = model.Price
            };

            return viewModel;
        }

    }

这是查看索引:

@model List<ValueVille.Models.ProductViewModel>
@using MvcApplication8.Models

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Name)

        </th>
        <th>
            @Html.DisplayNameFor(model => model.Image)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Price)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Name)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Image)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.Id }) |
            @Html.ActionLink("Details", "Details", new { id=item.Id }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.Id })
        </td>
    </tr>
}

</table>

【问题讨论】:

  • 看起来您只想使用model.SelectMany(x =&gt; x) 来拉平结果。
  • 我真的没有吸收你的问题的实质。但一个快速的解决方法是将您的 LINQ 中的第一个 .Select() 更改为 .SelectMany()
  • 谢谢。
  • 当您输入model.Name 时是否获得 IneliiSense 支持?
  • 你在迭代Model吗?

标签: c# asp.net-mvc linq


【解决方案1】:

您需要改用SelectMany

(await db.Categories
         .Where(c => c.Id == id)
         .SelectMany(p => p.Products.Select(x => new ProductViewModel { Id = x.Id, Name = x.Name, ByteImage = x.Image, Price = x.Price }))
         .ToListAsync());

SelectMany 在您想从多个序列投影到单个(平面)序列时很有用。


根据您的更新:

由于您的模型实际上是List&lt;ProductViewModel&gt;,当您想要显示某个属性的名称时,您需要指向一个实际的ProductViewModel 实例该列表中。

例如:

@Html.DisplayNameFor(model => model[0].Name)

MSDN

【讨论】:

  • 谢谢你。我现在得到一个 List 从控制器返回,并且 View 似乎在 @Html.DisplayNameFor()Html.DisplayFor() 标签助手中有红色下划线错误。是否列出了我需要使用的特定标签助手?
  • @Naz786,显示你的ProductViewModel
  • 我刚刚将它包含在上面。
【解决方案2】:

目前,您的序列看起来像这样

[ [model1, model2, model3], [model4, model] ]

你可以把它弄平

model.SelectMany(m => m)

[ model1, model2, model3, model4, model5 ]

(如果这真的是你想要的)

【讨论】:

  • 我正在使用请求 product/index/[Category ID] 访问数据,并且所有特定于该类别的产品对象都应与查询一起显示。
猜你喜欢
  • 2012-02-24
  • 1970-01-01
  • 2018-08-04
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多