MVC3中的UserControl相当于什么?

18
在Web表单中,我们有UserControls。这些控件具有代码后台,并可在不依赖其他内容的情况下用于不同的项目/解决方案中。
我想创建一个控件来呈现一些控件,并带有一些链接,“触发事件”。我希望它们不会附加在我的网站上,我想能够在另一个网站上使用相同的“控件”。MVC中的等同物是什么?是否可以编译带有控制器的视图并在其他地方使用DLL?

与这些问题相关(但不是重复的):73902810187 - Daniel Schilling
2个回答

17

在MVC中,与WebForms风格的可重用用户控件最接近的功能等效物是html辅助器。一个html辅助器是返回一些标记的方法。推荐的方法是将它们实现为HtmlHelper的扩展方法或MVC页面的其他属性:

public static IHtmlString MyControl(this HtmlHelper helper, string value) {
    return new HtmlString("<p>" + value + "</p>");
}

你可以直接将此方法添加到你的MVC项目中,或者将它添加到一个单独的类库中。类库仅需要引用System.Web.Mvc.dll来引用HtmlHelper(如果使用更多类型,可能还需要System.Web.dll)。

通常情况下,你可以像这样从你的视图中调用它(这个示例使用了MVC 3中的Razor语法)。

@Html.MyControl("my value")

虽然表面上 HTML Helper 与用户控件一样会生成标记,但二者存在显著差异。最重要的是,MVC 视图没有 WebForms 页面生命周期的概念。这意味着与用户控件不同,HTML Helper 只在单次渲染中呈现,而不存在类似于 WebForms 中的 Init、Load、Render 等多个阶段,而在这些阶段中,您可以连接服务器端事件以与页面上的其他控件进行交互。

根据您所讨论的特定事件类型,可能会有适合 MVC 的技术来解决您的任务。您能否提供更多关于您想做什么的详细信息?HTML Helper 可以非常强大。例如,内置的 MVC 输入控件,如 TextBoxFor,可以连接客户端验证等功能。


他也可以使用常规的“View”,将其呈现为“partial”,并将ViewModel用作它的“Code Behind”吗?由于UserControl是一个ASCX,我认为,最接近的等效物是带有ViewModel的部分视图。 - Chase Florell
1
@rockinthesixstring 局部视图不符合 OP 的要求,即可重用组件可以在一个独立的程序集中定义,被几个不同的应用程序包含(至少不是没有编写自定义视图引擎或虚拟路径提供程序来从程序集加载视图等)。 - marcind
是的,很好的建议。虽然我认为"UserControl"这个术语不太准确。也许"自定义控件"更合适? - Chase Florell
RenderAction()更接近于用户控件,不是吗? - John Farrell
2
@jfar RenderAction()不适用于相同的原因。基本上,任何需要定义视图(以.aspx或.cshtml文件形式)的东西不能轻松地从多个项目中重用。我想这进一步强调了WebForms和MVC范例在根本上是不同的 :) - marcind

3

因为 MVC 中不存在与 WebForms 中相同的“事件”,所以满足所有要求将非常棘手。

对于 UserControl 相当的 UI 层,您应该使用 PartialView,并可能位于 Views/Shared/Templates 文件夹中,具体取决于是否希望它与某个模型类型关联。

对于后端(“事件”),您应该实现一个控制器,您可以从链接发送请求,并支持您需要的所有行为。

要在各种项目中使用这些功能,您需要复制控制器和模板/部分视图。诚然,它可能不像 WebForms 的全能用户控件那样简单易用,但这是一个关注点明确分离的限制,在良好设计的基于层的 WebForms 应用程序中也会显而易见。

更新,针对我提到的关注点分离的“限制”评论:
当然,控制器可以分发在独立的程序集中,有自己的测试程序集等。但是,将控制器程序集(或程序集)部分视图/模板与前端代码一起包含,可能是另一件事情要做(即可能失败),而不仅仅是复制一个它的代码后台的用户控件(它们存储在相邻位置)。


我本来想点赞这篇文章,但是看到“明确的关注点分离”这句话后就有所犹豫了。为什么关注点分离会阻止控制器被构建在另一个程序集中,并从许多MVC应用程序中引用呢?视图基本上是HTML,需要以此方式共享,但为什么所有的.NET代码不应该放在一个或多个单独的可测试程序集中呢? - John Saunders
1
当然可以将控制器放在单独的(可测试的)程序集中,并独立于项目的其余部分共享。我不是说这不可行(我甚至会认为这样值得努力!),但这绝对比仅仅从一个项目中提取用户控件及其代码后台文件(如果您有的话),并让它自行处理所有魔法要复杂得多。这受到关注点明确分离的限制,这是我非常愿意承担的成本。 - Tomas Aschan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接