【问题标题】:ASP.net MVC: Creating SelectList in the view or action?ASP.net MVC:在视图或操作中创建 SelectList?
【发布时间】:2010-02-08 01:36:40
【问题描述】:

我只是想知道人们在哪里创建他们的 SelectList - 在操作或视图中。

我已经看到了这两种情况的例子,对我来说最有意义的例子是在动作中执行它并且让视图模型具有 SelectList 类型的属性。

另一方面,我看到一些示例,其中人们让视图模型具有 SelectList 的属性,并且 SelectList 填充在视图模型中(在构造函数中或通过延迟加载)。我喜欢这个想法,因为这意味着我的操作中的代码更少......

简而言之,我只是想知道人们在做什么。

干杯安东尼

【问题讨论】:

    标签: asp.net-mvc mvvm viewmodel automapper selectlist


    【解决方案1】:

    在控制器中创建您的 SelectList(通过从模型存储库中查找项目列表),并将其作为 ViewData 对象或作为强类型 ViewModel 的一部分传递给视图。

    【讨论】:

    • 为什么?如果您提供更多详细信息说明为什么您认为这种方法更可取,我将很乐意投票。是不是更容易测试?促进代码重用?更好地分离关注点?
    • @Seth:强类型 ViewModel 对象的目的是打包视图所需的所有数据,以便正确呈现它。在这种情况下,因为下拉列表需要项目列表,所以将其包含在 ViewModel 对象中是合适的。跟在我后面的程序员将在 ViewModel 中看到 SelectList,并得出结论认为它正在用于填充视图中的下拉列表。而且他不必看其他地方。
    • @Robert:我完全同意你的看法。我的观点是您的答案被选为“正确”答案,我认为一些额外的信息可能对将来遇到此问题的人有所帮助。我宁愿新的 MVC 程序员知道为什么这是可取的,而不是盲目地遵循 SO 答案:)
    • @Seth:非常正确。当时,我只有时间回答这个问题,没有话语。谢谢你提醒我。
    • 您不能将 SelectList 属性作为强类型 ViewModel 的一部分,因为它会引发“无参数构造函数”错误。
    【解决方案2】:

    这是一个特定于演示的方面,所以我更喜欢在视图中使用 Html 帮助器来完成。所以我将一个集合传递给 View 并使用一个 html 帮助器方法将项目映射到 SelectListItems。该方法可能看起来很像这样:

    public static IList<SelectListItem> MapToSelectItems<T>(this IEnumerable<T> itemsToMap, Func<T, string> textProperty, Func<T, string> valueProperty, Predicate<T> isSelected)
    {
        var result = new List<SelectListItem>();
    
        foreach (var item in itemsToMap)
        {
            result.Add(new SelectListItem
            {
                Value = valueProperty(item),
                Text = textProperty(item),
                Selected = isSelected(item)
            });
        }
        return result;
    }
    

    问候。

    【讨论】:

    • 你仍然需要在你的 ViewModel 中创建一个项目列表,那么为什么不把它变成一个 SelectList 呢?
    • 你说得对,我认为模型只是一个实体或从实体翻译的 dto(而不是特定于视图的模型或 ViewModel),无论如何,你可以使用上面的方法进行翻译。
    • 我认为特定于视图的模型可能应该直接公开一个 SelectList,因为它减少了您必须在视图中编写的代码量,即使只是一点点。但在某些情况下,我将 DTO 或业务对象传递给视图,在这些情况下,我会从视图中调用如上所示的帮助器 [我的称为 .ToSelectList()]。我认为这两种方法都适用于不同的场景。
    • 我不喜欢在 Controller(或在将 BO 转换为 ViewModel 的类中)创建 SelectList 的地方是,有时您需要将虚拟选项添加为“选择一个”或“无”等。如果您的应用程序要进行本地化,那么您应该从一个令人不安的资源文件中选择此文本,因为它会影响该特定操作的测试。
    【解决方案3】:

    我通常在操作或服务层中创建我的 SelectList,并通过 ViewData 将其传递给我的视图。我还让它成为视图模型和强类型视图的一部分。两种方式都在操作或服务层中创建它。

    【讨论】:

    • 通过 ViewData 传递 SelectLists 是可以的,但如果您的页面被强类型化为 ViewModel 对象,那么将您的 SelectLists 作为 ViewModel 的一部分包含在内会更简洁。
    • 同意,如果需要向视图发送更多数据而不仅仅是选择列表,这就是我所做的。如果我只需要一个选择列表,那么我倾向于使用 ViewData。
    【解决方案4】:

    我将 SelectList 作为属性公开在视图模型中,并使用必要的存储库将其填充到操作中。我认为直接与存储库交互的代码应该也是负责填充的代码,无论是控制器操作还是服务层或其他任何东西。

    我不认为直接从视图模型填充列表是一个好主意,因为它需要视图模型具有存储库依赖并进行数据库交互,而视图模型不应该负责这种东西。

    如果您有多个 SelectList 字段并希望保持操作代码更简洁,您还可以创建一个单独的特殊对象,称为 Initializer 或类似的东西,它会执行所有填充和初始化。

    【讨论】:

    • “我认为直接从视图模型填充列表不是一个好主意,因为它需要视图模型具有存储库依赖关系” - 不一定。 View Model 填充在控制器中(包括 SelectList 所需的项目列表),因此 View Model 本身不需要存储库依赖项。
    • 这正是我的观点。应该从控制器调用存储库填充代码,而不是从视图模型代码(构造函数或其他方法)内部调用。
    【解决方案5】:

    也不行,在单独的类中创建,看这里How to map View Model back to Domain Model in a POST action?

    我在控制器中使用 IBuilder 接口,并在此 Builder 的实现中完成所有实体/视图模型的构建

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多