获取多个选择列表并在MVC中显示它们的推荐方法是什么?

本文关键字:是什么 方法 显示 选择 列表 MVC 获取 | 更新日期: 2023-09-27 18:11:44

我搜索了SO和Google,但没有找到相关/可接受的答案。
背景:
*使用MVC 4.5
*我有一些通用Repo<T>,我在EF5的顶部使用,这反过来又被通用Service<T>访问
*我有域模型和视图模型,我使用Automapper在它们之间进行映射,这种映射发生在Service
*最重要的是,我有我的Controllers,再次尽可能通用。

所以,对于这个问题;我有几个场景,我需要向用户提供一个选项列表,他们必须选择一个或多个。这些选项是用户特定的,所以我的域User有一个List<Location>,这是他们保存的位置,当添加/修改Item时,他们需要选择至少一个Location
我抵制在我的控制器中获取List<Location>的诱惑,因为我想保持它们的通用和苗条,但同时,我宁愿在我的ItemView模型中没有两个属性,一个用于AvailableLocations,一个用于SelectedLocations,因为这个模型不仅用于添加/修改,还用于搜索结果等。
选择:
*我是否应该引入一个不同的模型来添加/修改Item,例如ItemInput ?
*我应该使用一些自定义映射并让Automapper获得可用位置的列表吗?
*我应该在哪个图层中获取这些可用位置?

大家有什么好的建议吗?
很多谢谢!

获取多个选择列表并在MVC中显示它们的推荐方法是什么?

我会这样做:

    public IEnumerable<Location> GetLocations() {
        return db.GetAll();
    }

然后在你的控制器(我从MVC脚手架遵循这一点):

 ViewBag.Locations = new SelectList(service.GetLocations, "name", "id");

(或您自己的复选框列表)并在HTML/View页面上放置一个列表控件。

我认为这是最好的方法的原因是因为逻辑都驻留在服务中。如果你把它放在你的DTO/数据模型中,你可能会遇到这个问题:

如果需要额外的逻辑来拉回位置会发生什么?即位置的子位置。

您更改服务(或重写)以反映新的更改,并且该逻辑将进入服务内部:

    public IEnumerable<Location> GetLocations(string parent) {
        return db.GetAll().Where(loc => loc.parentname = parent);
    }

注。我从不使用通用服务,我使用服务的原因是它提供的一些数据访问包含了不适合通用DAL的逻辑。

我可以做一个接口或抽象的服务来让我的生活更容易一些服务之间的共同操作,但是一旦你定义了一个具体的,一个UserManagementSerive,你肯定是说你想管理一个对象,它有用户,位置和项目,每个都有自己的特定功能?

我不认为这个问题只有一个可能的答案。

我建议使用一种简单但不那么通用的方法。我会写所谓的ViewModels,即与你的特定视图相关的模型类。然后我会从控制器中获得可用的位置,并使用获取的位置在控制器中填充ViewModel的实例。

基本上我会公开一些服务,比如:

IEnumerable<Location> GetAvailableLocationsForUser(string userName);

请注意,我使用了IEnumerable<T>,而不是IQueryable<T>。因为实现实际上会请求数据库,因为如果控制器的角色这样做(记住IQueryable<T>的延迟执行),那么它太容易出错(至少在IMO)。它返回一个域实例,即一个实体,而不是一个映射模型。我个人只会处理服务层中的域类。例如,域类可能是而不是实体,而是实体的组合。这有助于发出有效的请求,避免在控制器中使用延迟加载和延迟执行。当控制器需要一个完整的对象图而不仅仅是一个实体时,这是很有用的。

然后我将在web应用程序程序集中像下面这样编写模型和视图模型:

public LocationModel
{
    ...
}
public CreateItemViewModel : ItemModel
{
    public List<LocationModel> AssociatedLocations { get; set; }
    public List<LocationModel> AvailableLocations { get; set; }
    ...
}
  • 基本上有模型 (ItemModelLocationModel),它们是与web应用程序相关的对象。这意味着在这些模型中可能会有一些与网络相关的东西,例如计算的只读属性或属性上的属性(DisplayAttribute…等)。我会多次编写那些模型,因为我不认为这是可以一般化的东西:例如,一个视图可能需要使用导航属性而另一个视图不需要。这改变了映射过程的深度取决于使用模型的视图。我根本不会使用AutoMapper(只使用手写的映射器)。
  • 还有ViewModels (CreateItemViewModel),它们是与单个视图相关的对象(例如,在本例中允许创建Item的视图)。Model和ViewModel之间的区别在于ViewModel与单个视图相关(并根据该视图命名)。另一方面,模型与多个视图相关(它的名称空间将有助于了解哪些视图)。例如,xxx.Item.Models表示与xxx.Item目录中所有视图相关的模型)。ViewModels是在基于域类的控制器(或单独的映射器)中从头开始构建的。

在上面的例子中,你可以构建一个域类,返回AssociatedLocationsAvailableLocations,但这需要你的服务层知道web部分(我的意思是,你的服务接口和域类会知道特定视图需要哪些属性)。我不确定这些属性实际上与您的应用程序中的单个视图有关,但如果不是这种情况,您还可以构建一个域类作为实体的组合,将返回AssociatedLocationsAvailableLocations:

public ItemExtended : Item
{
    public List<Location> AssociatedLocations { get; set; }
    public List<Location> AvailableLocations { get; set; }
}
ItemExtended GetItemExtendedById(long idItem);