生成小 HTML 片段的辅助方法

Helper methods to generate small HTML snippets

我正在使用 ASP.NET MVC 将我的 HTML 视图与我的模型分开。但是有一个特定的情况让我有点困惑。

我有几个常用的小信息面板,它们本身是由许多小的信息面板组成的。这些从包含在各种模型中的子class 获取数据,有时是单个实例,有时是对象列表。

目前这是使用部分视图完成的,通过模型参数传递适当的数据,如下所示:

@Html.Partial("UserInfo", this.Model.CurrentUser);
@Html.Partial("UserInfo", reply.PostedBy);

等等。这一切都很好。

我最近遇到了一个要求,感觉它延伸了这个模型的合理限制,但是 - 它会涉及非常多的局部视图,每个视图中只有极小的 HTML,嵌套了很多次.页面解析时间似乎开始有点失控,我怀疑搜索和反映部分视图的数量可能与它有关。

请注意: 我假设仍然要避免重复 HTML 应该是相同的。我可以通过在一些更高级别的控件中使用 HTML 的副本来简化嵌套,但我觉得这会损害可维护性。

对于最内部的那些,我似乎更有意义创建静态助手 classes 生成和 return 所需的 HTML - 然而,尽管事实上MVC 本身是用 Html 助手 class 来做的,感觉这与 MVC 模式背道而驰。

显然,这种方法仍然将辅助方法与模型分开,但由于它需要一个模型来处理,我真的看不出它到底有多分离。

静态帮助程序与扩展方法只有一步之遥,以 userInstance.InfoHtml() 类型的方式使用,这似乎使整个方法非常类似于仅将帮助程序方法添加到模型中。这当然是 MVC 最初试图摆脱的东西!

请注意:我不是想规避规则或抱怨!我只是想尽可能地接近这个 "on pattern" 。如果有很多很多的局部视图,我会尽我所能坚持这一点和性能调整。

很难根据您在此处提供的内容确定最佳路径。这在很大程度上取决于您的工作内容和您想要实现的目标。

例如,您当前通过部分视图包含的用户信息内容听起来更适合由子操作提供:

[Authorize]
public class AccountController : Controller
{
    ...

    [ChildActionOnly]
    [AllowAnonymous]
    public ActionResult UserInfo()
    {
        // get your user info here
        return PartialView("UserInfo", userInfo);
    }
}

然后在你的 view/layout:

@Html.Action("UserInfo", "Account")

然后,您无需确保在您使用的任何视图模型上都填充了用户对象。

接下来,Html.Partial 等 Razor 辅助方法本身只是对 Url.* 辅助方法的 HtmlHelperUrlHelper 的扩展。添加您自己的扩展方法没有错。例如,在开箱即用地融入 MVC 5 之前,使用自定义 EnumDropDownListFor 扩展 HtmlHelper 是很常见的。但是,扩展确实最适合 HTML 的小部分,这似乎是您想要在此处使用的内容。对于 HTML 的大块,使用局部变量更有意义。不过,两者都有效。很大程度上取决于您决定什么对您的应用程序最有意义。

我相信有四种常见的解决方案可以根据您的需要在问题中重用html。

  1. 部分浏览量 (@Html.Partial);
  2. 子操作(@Html.Action);
  3. 自定义静态助手(@Html.Whatever@Url.Whatever、模型的扩展方法等);
  4. 剃须刀帮手。 (@helper)

Is it OK to use static helper classes to generate small HTML snippets?

使用静态助手 类 生成小的 HTML 片段是否绝对可以。我不喜欢将它们作为方法添加到模型中的想法,扩展方法没问题。

我想说这些方法之间的区别主要在于编码风格和个人喜好。我会使用部分视图只是为了将大视图分解成可消耗的部分,应用程序真正常见和独立部分的子操作(如小部件或登录框),所以我不必用填充我所有的视图模型常见事物的数据。我会为非常小的 html 片段(表单中的一个字段)使用静态助手或 razor 助手,为更多代码使用静态助手,为更多 html 使用 razor 助手。

Where should the static UserInfo class go? Views? Controllers? Elsewhere?

这些东西从pattern的角度来说属于View。如果您询问应该在解决方案中填充哪些文件夹,我会为它们推荐一个特殊的文件夹(可能 HtmlHelpers)。共享剃须刀助手可能存在驻留在 App_Code 文件夹中的限制。

我认为以下问题会让您更多地了解如何在它们之间进行选择:

  1. Creating reusable HTML view components using Razor in ASP.NET MVC;
  2. How to create reusable control in ASP.NET MVC;
  3. How to create a reusable piece of HTML with dynamic contents;
  4. ASP.NET MVC: Razor @helper vs extension methods to HtmlHelper - which is preferred?.

更新

新的 ASP.NET MVC 中可能有第五种解决方案:View Components。据我所知,您可以使用它们代替子动作。