对于 ViewBag,我听说它是禁止使用的。我会假设应该将 ViewBag 中的内容合并到视图模型中?
问题:
我的假设是否高于最佳实践。(不要使用 ViewBag,其次要在视图模型中使用它)
是否存在绝对需要 ViewBag 的情况?
对于 ViewBag,我听说它是禁止使用的。我会假设应该将 ViewBag 中的内容合并到视图模型中?
问题:
我的假设是否高于最佳实践。(不要使用 ViewBag,其次要在视图模型中使用它)
是否存在绝对需要 ViewBag 的情况?
ViewBag 是一个动态字典。因此,当使用 ViewBag 在操作方法和视图之间传输数据时,如果您在尝试访问视图中的 ViewBag 项时在代码中出现拼写错误,您的编译器将无法捕捉到。您的视图将在运行时崩溃:(
通常,使用视图模型在您的操作方法和视图之间传输数据是一个好主意。视图模型是一个简单的 POCO 类,它具有特定于视图的属性。因此,如果您想向视图传递一些额外的数据,请向您的视图模型添加一个新属性并使用它。强类型视图使代码更清晰,更易于维护。使用这种方法,您不需要来回将您的 viewbag 字典项显式转换为某些类型,而这与 view bag 相关。
public class ProductsForCategoryVm
{
public string CategoryName { set;get; }
public List<ProductVm> Products { set;get;}
}
public class ProductVm
{
public int Id {set;get;}
public string Name { set;get;}
}
在您的操作方法中,创建此视图模型的对象,加载属性并将其发送到视图。
public ActionResult Category(int id)
{
var vm= new ProductsForCategoryVm();
vm.CategoryName = "Books";
vm.Products= new List<ProductVm> {
new ProductVm { Id=1, Name="The Pragmatic Programmer" },
new ProductVm { Id=2, Name="Clean Code" }
}
return View(vm);
}
而你的视图,它是视图模型的强类型,
@model ProductsForCategoryVm
<h2>@Model.CategoryName</h2>
@foreach(var item in Model.Products)
{
<p>@item.Name</p>
}
许多教程/书籍都有代码示例,它们使用 ViewBag 来获取下拉数据。我个人还是觉得 ViewBag 的不应该用于这个。它应该是List<SelectListItem
视图模型中类型 > 的属性来传递下拉数据。这是一篇包含如何做到这一点的示例代码的帖子。
是否存在绝对需要 ViewBag 的情况?
在一些有效的用例中,您可以(不必要)使用 ViewBag 发送数据。例如,您想在 Layout 页面上显示某些内容,您可以使用 ViewBag 来实现。另一个例子是ViewBag.Title
(对于页面标题)出现在默认 MVC 模板中。
public ActionResult Create()
{
ViewBag.AnnouncementForEditors="Be careful";
return View();
}
在布局中,您可以阅读ViewBag.AnnouncementForEditors
<body>
<h1>@ViewBag.AnnouncementForEditors</h1>
<div class="container body-content">
@RenderBody()
</div>
</body>
1)我的假设是否高于最佳实践。(不要使用 ViewBag,其次要在视图模型中使用它)
您应该尽可能使用视图模型而不是通过 ViewBag 传递数据。
2) 是否存在绝对需要 ViewBag 的情况?
没有绝对需要 ViewBag 的情况。但是,有一些数据我个人更喜欢使用 ViewBag 而不是 View Model。例如,当我需要为预定义值(即城市)填充下拉框时,我使用 ViewBag 来携带 SelectListItem 数组进行查看。我不想用这些数据污染我的 ViewModel。
1)我的假设是否高于最佳实践。(不要使用 ViewBag,其次要在视图模型中使用它)
是的。
2) 是否存在绝对需要 ViewBag 的情况?
不。您存储在 ViewBag 中的所有内容都可以进入传递给视图的视图模型。
ViewBags 的问题和推荐的最佳实践归结为编译时检查。ViewBags 只是字典,你会得到“神奇”的字符串,所以如果你最终改变了一个 viewbag 项目的对象类型或键名,你直到运行时才会知道,即使你使用<MvcBuildViews>true</MvcBuildViews>
.
坚持使用视图模型是最好的,即使您必须不时更改它们以适应特定视图。
我发现 ViewBag 有一些用途,其中所有页面都有通用功能,并且功能不依赖于显示的页面。例如,假设您正在构建 StackOverflow。工作板出现在每个页面上,但显示的工作与页面无关(我的用法在概念上相似)。为每个 ViewModel 添加一个属性会很困难而且很耗时,而且会给您的测试带来很多麻烦。在这种情况下,我认为不值得。
我已经使用了带有横切数据的基本 ViewModel 类,但是如果您有多个(例如,工作和堆栈交换站点列表),您要么必须开始填充额外的数据,要么对 ViewModel 进行其他一些滥用,另外您需要一个 ViewModel 构建器来填充基础数据。
至于魔弦问题,有很多解决方案。常量、扩展方法等
综上所述,如果您的页面上显示的内容取决于页面的上下文,那么 ViewModel 就是您的朋友。
埃里克
如果您无法重新设计现有的 ViewModel,请使用 ViewBag。
我想我会对此发表意见,因为我已经广泛使用了 ViewBag。
使用它的唯一真正好处是用于小型项目,或者在您有一个新项目并且只想让球滚动而不必担心创建大量模型类的情况下。
当您的项目更加成熟时,您可能会发现由于在整个应用程序中使用弱类型而导致的意外行为问题。当出现问题时,逻辑可能会令人困惑、难以测试并且难以排除故障。
实际上,我走的是从我的应用程序中完全删除 ViewBag的路线,并通过在尝试使用时抛出编译错误来阻止其他开发人员在同一代码库中使用它,即使在 Razor 视图中也是如此。
这是 GitHub 上的一个示例 ASP.NET 5 项目,我已将其删除:https ://github.com/davidomid/Mvc5NoViewBag
这是一篇博客文章,我解释了删除它的动机以及解决方案如何工作的解释: https ://www.davidomid.com/hate-the-aspnet-mvc-viewbag-as-much-as-i-做这里如何删除它
2.是否存在绝对需要ViewBag的情况?
在某些情况下,您需要在布局、视图和部分视图之间共享来自控制器的数据。在这种情况下,ViewBag 非常有帮助,我怀疑有没有更好的方法。
如果没有它的用例,它一开始就不会实施。是的,您可以使用 ViewModel 完成所有工作,但如果您真的不需要它怎么办?一种这样的场景是编辑实体。您可以直接将 DTO 作为模型传递。
@model CategoryDto
<div class="md-form form-sm">
<input asp-for="Name" class="form-control">
<label asp-for="Name">("Category Name")</label>
</div>
但是如果你想选择 Category parent 怎么办?实体 DTO 理想情况下只包含它自己的值,因此要填充选择列表,您可以使用 ViewBag
<select asp-for="ParentId" asp-items="ViewBag.ParentList">
<option value="">None</option>
</select>
为什么要这样做?好吧,如果您有 50 种类型的实体,每种类型都可以从不同的值中进行某种选择,那么您只需避免创建 50 个额外的 ViewModel。
冒着在这里打开一罐旧蠕虫的风险,让我提供一点见解。不管什么可能是“最佳实践”,让我提供真实世界的经验,即 ViewBag 的广泛使用可能是琐碎的噩梦来源,很难找到错误和问题,这些问题完全令人讨厌,难以追踪和解决。即使可以为使用 ViewBag 建立一个令人满意的概念或规则,它们也很容易成为初级开发人员的拐杖,以分散注意力并阻止开发适当的强类型 ViewModel。
不幸的是,太多的“教程”YouTube 视频展示了 ViewBags 用于演示目的,并且几乎没有提供关于这种做法何时不适合生产代码的见解。是的,有时使用 ViewBag 可能是解决给定问题的合适解决方案,但可能会导致漫长而曲折的挫折之路和可维护性差。冒着在谨慎的方向上过度纠正的风险,我会鼓励年轻的开发人员不要依赖 ViewBag,直到他们获得更多的 MVC 经验,自然地了解 ViewModel 何时以及如何有用,然后再开发一个更老练的感觉何时使用 ViewBag 是合适的。