Asp.net mvc asp mvc使用视图模型列出视图中的产品详细信息

Asp.net mvc asp mvc使用视图模型列出视图中的产品详细信息,asp.net-mvc,asp.net-mvc-4,viewmodel,asp.net-mvc-viewmodel,Asp.net Mvc,Asp.net Mvc 4,Viewmodel,Asp.net Mvc Viewmodel,我试图在视图中列出单个产品的详细信息。产品规格是动态变化的,因为规格是按行添加到表中的,这意味着我们可以为每个产品添加大量规格(就像在电子商务网站中所做的那样)。现在,我可以使用ViewBag满足要求,但我决定使用ViewModel作为更好的实践 型号类别: // Product: public partial class ProductTable { public ProductTable() { this.SpecificationsTable = new H

我试图在视图中列出单个产品的详细信息。产品规格是动态变化的,因为规格是按行添加到表中的,这意味着我们可以为每个产品添加大量规格(就像在电子商务网站中所做的那样)。现在,我可以使用
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();
}
视图中的预期输出:

// 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; }
}
详细信息:

说明:


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

视图模型确实是一种方法。我不会详细说明viewmodels是什么,因为您已经在代码中声明了一些viewmodels,所以我假设您已经知道它们的用途和功能。但是,为了完整性起见,viewmodels仅表示希望在视图中显示的数据;假设视图显示员工的名字和姓氏,当您只需要两个属性时,没有理由发回
employee
对象

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

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; }
}
实例化并填充viewmodel后,将其传递给视图:

var yourViewModel = new YourViewModel();
//populate it and pass it to the view
return View(yourViewModel);
@Model.MobileName
var parentViewModel = new ParentViewModel();
var yourViewModel = new YourViewModel();
//populate it and attach it to the parent viewmodel
parentViewModel.YourViewModel = yourViewModel;
return View(parentViewModel);
@Model.YourViewModel.MobileName
在视图的顶部,将
@model
变量声明为
YourViewModel
类型:

@model YourViewModel
…你可以走了。因此,如果要在视图中打印手机名称:

var yourViewModel = new YourViewModel();
//populate it and pass it to the view
return View(yourViewModel);
@Model.MobileName
var parentViewModel = new ParentViewModel();
var yourViewModel = new YourViewModel();
//populate it and attach it to the parent viewmodel
parentViewModel.YourViewModel = yourViewModel;
return View(parentViewModel);
@Model.YourViewModel.MobileName
请记住,虽然每个视图只能有一个
@model
,但仍然可以有多个viewmodels。这可以通过创建一个父视图模型来保存所有与视图相关的视图模型,并将其设置为
@model

public class ParentViewModel
{
    //all the viewmodels which are relevant to your view
    public DetailsViewModel DetailsViewModel { get; set; }
    public YourViewModel YourViewModel { get; set; }
    //...etc        
}
@model ParentViewModel
实例化并填充viewmodel后,将其传递给视图:

var yourViewModel = new YourViewModel();
//populate it and pass it to the view
return View(yourViewModel);
@Model.MobileName
var parentViewModel = new ParentViewModel();
var yourViewModel = new YourViewModel();
//populate it and attach it to the parent viewmodel
parentViewModel.YourViewModel = yourViewModel;
return View(parentViewModel);
@Model.YourViewModel.MobileName
这次,在视图的顶部,将
@model
变量声明为
ParentViewModel
类型:

public class ParentViewModel
{
    //all the viewmodels which are relevant to your view
    public DetailsViewModel DetailsViewModel { get; set; }
    public YourViewModel YourViewModel { get; set; }
    //...etc        
}
@model ParentViewModel
…你可以走了。使用相同的示例,如果要在视图中打印手机名称:

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

请记住,我并没有真正关注您如何构建viewmodels,而是解释了如何将一个(或多个)viewmodels传递回您的视图,并使用它们而不是
ViewBag
(根据您的问题)。查看模型的实际填充方式和外观是一个不错的选择。

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

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; }
}
然后在视图中

@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)
}
@model yoursassembly.ProductVM
细节
@DisplayNameFor(m=>m.Title)
@DisplayFor(m=>m.Title)
.... // SmallDescription和FullDescription同上
规格
@foreach(型号规格中的var项目)
{
@DisplayFor(m=>item.Name)
@DisplayFor(m=>item.Value)
}

不太清楚您的要求。您的视图模型不表示要显示的内容。它需要属性
Title
SmallDescription
FullDescription
IEnumerable
,其中
SpecificationViewModel
包含属性
SpecificationName
SpecificationValue
@StephenMuecke,我已经设计使用后和产品规格的变化动态我解释了希望有帮助,谢谢你。是的,我理解你的尝试做什么。我想说的是,您的视图模型是错误的(对于填充它的查询也是错误的)。给我30分钟,我会加上一个答案,说明你需要做什么。@StephenMuecke,是的,谢谢。我的规格为不同的产品而改变,不仅仅是手机,如果换成其他规格的名称和价值,我已经解释了希望这会有所帮助,谢谢。这就是为什么我还向您展示了如何将多个viewmodels传递回视图作为示例的原因。您需要重新组织和重组viewmodels。Stephen Muecke在你问题的评论中建议的是前进的道路。轻微的打字错误:关闭两个
。选择()
:)Oops。谢谢@trashr0x:)谢谢您的时间,我收到此错误
“myproject.Models.ProductTable”不包含“Select”的定义,并且找不到接受“myproject.Models.ProductTable”类型的第一个参数的扩展方法“Select”(是否缺少using指令或程序集引用?)
靠近
产品。选择
是否使用System.Linq包含
不确定“我必须格式化数据”是什么意思。此链接可能有助于理解视图模型-