将复杂的条件语句移动到代码隐藏
本文关键字:代码 隐藏 移动 语句 复杂 条件 | 更新日期: 2023-09-27 17:47:21
我只是想知道,通过将复杂的 if else 语句和生成的 html 标记移动到后面的代码是否违反了某些"MVC"定律?
当面对内联 if else 语句时,这似乎是一个很好的选择,这些语句可能会变得非常不可读。
在您看来,有条件并不可怕。 我会将它们保留在 ASPX 中,而不是后面的代码中。 但是,条件通常表示控制行为。 请考虑以下 ASPX 代码:
<%if (ViewData["something"] == "foo") {%>
<%=Html.ActionLink("Save", "Save") %>
<%}%>
<%if (ViewData["somethingElse"] == "bar") {%>
<%=Html.ActionLink("Delete", "Delete") %>
<%}%>
这组条件表示视图正在处理的控制行为 - 即在错误的位置。 此行为不可进行单元测试。 相反,请考虑:
<%foreach (var command in (IList<ICommand>)ViewData["commands"]) {%>
<%=Html.ActionLink(command) %>
<%}%>
在此示例中,ActionLink 是 HtmlHelper 的自定义扩展,它采用我们自己的 ICommand 规范对象。 呈现此视图的控制器操作根据各种条件填充 ViewData["命令"]。 换句话说,控制器进行控制。 在此操作的单元测试中,我们可以测试在各种条件下是否会显示正确的命令集。
起初,与快速将几个 IF 扔进视图中相比,这似乎很麻烦。 你必须问自己的问题是,"这个IF是否代表控制行为,我是否想确保在某个时候不会中断?
我不想在我的视图中使用类背后的代码。这不是因为它默认违反了 MVC,而是因为我发现"自然"方式(至少对我来说)是不同的。
当我遇到与纯粹视图问题相关的复杂 HTML 标记时,我通常会为类编写一个扩展方法HtmlHelper
以隐藏复杂性。因此,我有像 Html.MoneyTextBox()
、 Html.OptionGroup()
和 Html.Pager<T>
这样的扩展。
在其他情况下,当出现复杂条件时,通常我错过了控制器的某些内容。例如,与元素的可见性、只读或启用相关的所有问题通常都源于控制器可以提供的内容。在这种情况下,我不是将模型传递给视图,而是创建一个视图模型,该模型封装了模型和控制器可以提供的其他信息,以简化 HTML 标记。视图模型的典型示例如下:
public class CustomerInfo
{
public Customer Customer { get; set; }
public bool IsEditable { get; set; } // e.g. based on current user/role
public bool NeedFullAddress { get; set; } // e.g. based on requested action
public bool IsEligibleForSomething { get; set; } // e.g. based on business rule
}
也就是说,背后的代码是视图的一部分,因此您可以自由使用它,如果它更适合您的需求。
它是一个渲染代码并且它在"视图"而不是在控制器中,那么将其放在后面或内联的代码上就无关紧要了。只要确保不要在控制器操作中编写这段渲染代码(这样你就会真正违反 MVC 模式)。
代码隐藏是视图的一部分 - 如果要直接在 ASPX 中或代码隐藏中放置内容,则由您决定。MVC并不意味着你必须在ASPX:)中编写所有丑陋的东西。