【问题标题】:asp mvc list product details in view using View Modelasp mvc 使用 View Model 在视图中列出产品详细信息
【发布时间】:2015-10-29 13:14:24
【问题描述】:

我正在尝试在视图中列出单个产品的详细信息。产品规格会动态变化,因为规格是在表格中逐行添加的,这意味着我们可以为每个产品添加大量规格(就像在电子商务网站中所做的那样)。现在我可以使用ViewBag 满足要求,但我决定使用ViewModel 作为更好的做法。

模型类:

// Product:
public partial class ProductTable
{
    public ProductTable()
    {
        this.SpecificationsTable = new HashSet<SpecificationsTable>();
    }

    public int ProductID { get; set; }
    public string Title { get; set; }
    public string SmallDescription { get; set; }
    public string FullDescription { get; set; }

    public virtual ICollection<SpecificationsTable> SpecificationsTable { get; set; }
    }

//Specifications:
public partial class SpecificationsTable
{
    public int SpecificationsID { get; set; }
    public string SpecificationName { get; set; }
    public string SpecificationValue { get; set; }
    public Nullable<int> ProductID { get; set; }
    public virtual ProductTable ProductTable { get; set; }
}

视图模型:

public class DetailsViewModel
{
    public int ProductID { get; set; }
    public string Title { get; set; }
    public string SmallDescription { get; set; }
    public string FullDescription { get; set; }
    public string SpecificationName { get; set; }
    public string SpecificationValue { get; set; }
}

动作方法

public ActionResult ProductDetails(int id)
{
    var details = (from c in dbo.ProductTable
                   join s in dbo.SpecificationsTable 
                   on c.ProductID equals s.ProductID
                   where c.ProductID == id
                   select new DetailViewModel
                   {
                       Title = c.Title,
                       SmallDescription = c.SmallDescription,
                       FullDescription = c.FullDescription
                   }).ToList();

     // To remove repeated product title , small and full description
     var distinctItems = details.GroupBy(x => x.ProductID).Select(y => y.First());

     // To show product title, small and full description for this product

     ViewBag.ProductDetails = distinctItems;

     var specifications = (from c in dbo.ProductTable
                             join s in dbo.SpecificationsTable 
                             on c.ProductID equals s.ProductID
                             where c.ProductID == id
                             select new DetailViewModel
                             {
                                 SpecificationName = s.SpecificationName,
                                 SpecificationValue = s.SpecificationValue
                             }).ToList();

    // To show list of specifications for this product
    ViewBag.Specifcations = specifications;
    return View();
}

预期输出:

详情:

Title: New Samsung offer

SmallDescription : Something small 

FullDescription : Something full

规格:

Mobile Name :Samsung

Model : 2015

Price : 70 $

Color:  White

我正在使用数据库优先方法,我正在尝试在这里学习如何使用视图模型。

【问题讨论】:

  • 有点不清楚你在问什么。您有一个不代表您想要显示的视图模型。它需要属性TitleSmallDescriptionFullDescriptionIEnumerable&lt;SpecificationViewModel&gt;,其中SpecificationViewModel 包含属性SpecificationNameSpecificationValue
  • @StephenMuecke,我使用this 设计了帖子和产品规格动态变化,我已经解释了here 希望对您有所帮助,谢谢。
  • 是的,我明白你想做什么。我要说的是您的视图模型是错误的(您对填充它的查询也是如此)。给我 30 分钟,我会添加一个答案,说明你需要做什么。
  • @StephenMuecke,是的,谢谢。

标签: asp.net-mvc asp.net-mvc-4 viewmodel asp.net-mvc-viewmodel


【解决方案1】:

您当前的视图模型没有反映您想要在视图中显示的内容,这是每个产品的多个规范,因此您需要一个集合属性。将您的视图模型更改为

public class SpecificationVM
{
  public string Name { get; set; }
  public string Value { get; set; }
}
public class ProductVM
{
  public string Title { get; set; }
  public string SmallDescription { get; set; }
  public string FullDescription { get; set; }
  IEnumerable<SpecificationVM> Specifications { get; set; }
}

然后在控制器中,使用

填充您的视图模型
public ActionResult ProductDetails(int id)
{
  var product = db.ProductTable.Where(p => p.ProductID == id).FirstOrDefault();
  // note you may need to add .Include("SpecificationsTable") in the above
  if (product == null)
  { 
    return new HttpNotFoundResult();
  }
  ProductVM model = new ProductVM()
  {
    Title = product.Title,
    SmallDescription = product.SmallDescription,
    FullDescription = product.FullDescription,
    Specifications = product.SpecificationsTable.Select(s => new SpecificationVM()
    {
      Name = s.SpecificationName,
      Value = s.SpecificationValue
    })
  };
  return View(model);
}

然后在视图中

@model yourAssembly.ProductVM
<h2>Details</h2>
@Html.DisplayNameFor(m => m.Title)
@Html.DisplayFor(m => m.Title)
.... // ditto for SmallDescription and FullDescription 
<h2>Specifications</h2>
@foreach(var item in Model.Specifications)
{
  @Html.DisplayFor(m => item.Name)
  @Html.DisplayFor(m => item.Value)
}

【讨论】:

  • 小错别字:关闭两个.Select() :)
  • 糟糕。谢谢@trashr0x :)
  • 感谢您的宝贵时间,我在product.Select 附近收到此错误'myproject.Models.ProductTable' does not contain a definition for 'Select' and no extension method 'Select' accepting a first argument of type 'myproject.Models.ProductTable' could be found (are you missing a using directive or an assembly reference?)
  • 你有没有收录using System.Linq;
  • 不确定您所说的“我必须格式化数据” 是什么意思。此链接可能有助于理解视图模型 - What is ViewModel in MVC?
【解决方案2】:

Viewmodels 确实是通往这里的路。我不会详细说明什么是视图模型,因为您已经在代码中声明了一些视图模型,所以我假设您已经知道它们的用途和功能。然而——为了完整起见——视图模型只代表你想在视图中显示的数据。假设视图显示员工的名字和姓氏,那么当您只需要其中两个属性时,没有理由发回 Employee 对象。

根据上面提供的简短视图模型定义,要返回视图模型而不是将返回的对象附加到 ViewBag,您只需创建一个类只保存您希望在视图中显示的数据时间>。因此,根据您的“视图中的预期输出”,您的视图模型看起来类似于:

public class YourViewModel 
{
    public string Title { get; set; }
    public string SmallDescription { get; set; }
    public string FullDescription { get; set; }
    public string MobileName { get; set; }
    public int ModelYear { get; set; }
    public decimal Price { get; set; }
    public string Color { get; set; }
}

一旦你的视图模型被实例化和填充,就将它传递给视图:

var yourViewModel = new YourViewModel();
//populate it and pass it to the view
return View(yourViewModel);

在视图的顶部,将@model 变量声明为YourViewModel 类型:

@model YourViewModel

..你可以走了。因此,如果您想在视图中打印出手机名称:

@Model.MobileName

请记住,虽然每个视图只能有 一个 @model,但您仍然可以有多个视图模型。这可以通过创建一个父视图模型来保存所有与视图相关的视图模型并将其设置为 @model 来实现:

public class ParentViewModel
{
    //all the viewmodels which are relevant to your view
    public DetailsViewModel DetailsViewModel { get; set; }
    public YourViewModel YourViewModel { get; set; }
    //...etc        
}

一旦你的视图模型被实例化和填充,就将它传递给视图:

var parentViewModel = new ParentViewModel();
var yourViewModel = new YourViewModel();
//populate it and attach it to the parent viewmodel
parentViewModel.YourViewModel = yourViewModel;
return View(parentViewModel);

这一次,在视图的顶部,将 @model 变量声明为 ParentViewModel 类型:

@model ParentViewModel

..你可以走了。使用相同的示例,如果您想在视图中打印出手机名称:

@Model.YourViewModel.MobileName

请记住,我并没有真正关注您如何构建视图模型,而是解释了如何将一个(或多个)视图模型传递回您的视图并使用它们而不是 ViewBag(根据你的问题)。对于您的视图模型应该如何实际填充和外观,Stephen Muecke's answer 是要走的路。

【讨论】:

  • 我的规格因不同的产品而有所变化,不仅仅是手机,如果服装是其他规格名称和价值,我已经解释了here希望对您有所帮助,谢谢。
  • 这就是为什么我还向您展示了如何将多个视图模型传递回视图作​​为示例。您需要重新组织和重组您的视图模型。 Stephen Muecke 在您的问题的 cmets 中建议的是要走的路。
猜你喜欢
  • 2021-01-17
  • 1970-01-01
  • 2013-04-19
  • 2015-12-22
  • 1970-01-01
  • 1970-01-01
  • 2013-10-03
  • 2010-12-06
  • 2019-11-11
相关资源
最近更新 更多