我对MVC相当陌生,并尝试对ViewModels进行更多探索。我有一个产品类别页面,我想显示产品类别以及产品及其相关图像。我将简化其中一些表,仅关注将这些数据返回到视图的逻辑。我有使用填充下拉列表的视图,但是我不确定如何在CategoryViewModel中填充ProductViewModel。
类别表
CategoryId
CategoryName
CategoryDescription
产品表
ProductId
ProductName
ProductDescription
ProductPrice
CategoryId
ProductImage表
ProductId
ProductImage1
ProductImage2
ProductImage3
ProductImage4
ProductImage5
ProductImage6
ProductImage7
ProductImage8
ProductImage9
ProductImage10
public class ProductViewModel
{
public Product ProductVM { get; set; }
public ProductImage ProductImageVM { get; set; }
}
public class CategoryViewModel
{
public List<Category> Category { get; set; }
public List<ProductViewModel> Products { set;get;}
}
public ActionResult Index()
{
var model = new CategoryViewModel();
model.Category = db.Categories.OrderBy(d => d.CategoryName).ToList();
model.Products = from p in db.Products
join pi in db.ProductImages on p.ProductId equals pi.ProductId
orderby p.ProductPrice descending
return View(model);
}
@model CategoryViewModel
@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Category, "CategoryId", "CategoryName"), "View all Categories")
<table>
@foreach (var product in Model.Products)
{
<tr>
<td>@item.ProductImage.ProductImage1</td>
<td>@item.Product.ProductName</td>
<td>@item.Product.ProductPrice</td>
<td>@item.Product.ProductDescription</td>
</tr>
}
</table
答案 0 :(得分:2)
每当我使用ViewModels时,我也会开发一个Service类来填充它。这有助于保持控制器清洁并隔离逻辑。
首先,创建一个名为“服务”的文件夹以包含这些类。如果使用Areas,则在项目层次结构中与使用Controller的控制器在同一级别创建文件夹。
然后,在该文件夹中创建一个“服务”类。例如,由于ViewModel被命名为CategoryService
,因此我将创建一个名为CategoryViewModel
的类。
在此类中,我将代码初始化ViewModel:
public class CategoryServices
{
private MyDbContext db = new MyDbContext();
internal CategoryViewModel GetCategoryViewModel(){
return new CategoryViewModel(){
Category = GetCategories(),
Products = GetProductViewModel()
};
}
internal List<Category> GetCategories(){
return db.Categories.OrderBy(d => d.CategoryName).ToList();
}
internal List<ProductViewModel> GetProductViewModel(){
return db.Products.Select(x => new ProductViewModel()
{
ProductVM = x,
ProductImageVM = x.ProductImage
});
}
}
现在,您可以轻松地从控制器中检索ViewModel:
public ActionResult Index()
{
CategoryService service = new CategoryService();
return View(service.GetCategoryViewModel());
}
在视图上,您必须更新模型引用以处理ViewModel中的内容。
@model CategoryViewModel
@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Category, "CategoryId", "CategoryName"), "View all Categories")
<table>
@foreach (var item in Model.ProductViewModels)
{
<tr>
<td>@item.ProductImage.ProductImage1</td>
<td>@item.Product.ProductName</td>
<td>@item.Product.ProductPrice</td>
<td>@item.Product.ProductDescription</td>
</tr>
}
</table
这应该将您设置在需要走的大致方向上。如果您对以上任何问题有任何评论,请随时离开。我将尽力澄清。
编辑: 另外,我建议您进一步细分服务类中的功能。我在这里避免了这种情况,因为我不想为您提供10个以上的函数类。
EDIT2:
更新了GetProductViewModel()
函数。由于Product和ProductImage模型之间存在1对1的关系,并且ProductImage在ProductId上具有引用产品的ProductId的外键,因此ProductImage应该可以作为Product模型上的子实体使用。
因此,您可以使用方便的lambda表达式在一个数据库行程中生成ProductViewModels的列表。我已经使用此lambda表达式生成了很多列表,但是您可能需要对其进行修改才能正常工作。
答案 1 :(得分:1)
我与杰克采取了类似的方法,只是我将其进一步分离了。
似乎有些矫kill过正(在某些情况下可能如此),但它为您提供了更大的灵活性。
我将创建两个类:
ProductViewModelFactory
(创建ProductViewModel
)CategoryViewModelFactory
(创建CategoryVieWModel
) ProductViewModelFactory
可以在内部使用任何数量的存储库,服务或其他必要的视图模型工厂来构建其数据。
在这种情况下,ProductViewModelFactory
将在内部调用CategoryViewModelFactory
以创建CategoryViewModel
。 ProductViewModelFactory
也可能会调用ProductRepository
或ProductService
并将从某种持久性存储中检索到的返回的Product
映射到视图模型。
它可能还会调用其他一些内容-如果现在还不行,那么以后添加更多功能的机会就很大。
CategoryViewModelFactory
可能会调用CategoryService
或CategoryRepository
,然后将数据映射到CategoryViewModel
。
那么,这些额外的层给我们带来了什么优势?毕竟,这需要更多的工作。
当然,有YAGNI,但是根据我的经验,这种方法以最少的工作量提供了最大的灵活性来处理意外的要求。
您认为YAGNI的时代,但是您刚刚发现您确实需要 ,这可能会导致一些灾难性的情况-因此恕我直言,值得付出额外20%的精力来创建一个简单一致的结构,在大多数情况下,可以确保您不会陷入困境。
这意味着当需要一个完全不同的视图时,您不必最终弄乱您的服务或存储库-这些应该返回可能的最原始数据。
他们还可以调用其他ViewModelFactories,这很方便,因为随着应用程序的增长,很多时候您需要在ViewModel内的ViewModel中包括其他ViewModels。
这种情况比您在以下情况下想的要多 -在某些情况下需要测试的错误, -另一个相关组件未完成, -您需要返回一组特定的数据才能进行前端开发的视图, -您要创建一系列测试, -您需要为客户端演示等返回特定数据
您不必关心视图模型工厂,服务或存储库如何获取或返回数据。您不必担心当前正在上课的人在消费什么。
如果需要大量数据,只需根据需要注入其视图模型工厂,服务或存储库,并传递一些参数,然后一切在整个应用程序中以可预测的一致模式工作。
因此,总结,以下是大概的生命周期:
这还可以为您提供一些有趣的选项,以基于带有动作过滤器的命名约定自动处理事物,从而导致非常空的控制器动作。