虽然MVC提供了方便的关注点分离,但这似乎打破了封装(即,您可以添加一个控件而不添加或使用其支持代码,导致运行时错误).每次在视图中添加控件时,都必须修改一个控件,好像我将整合关注点放在一起,而不是分开它们.我宁愿打破纯粹主义的MVC意识形态,而不是放弃可重复使用的封装控制的好处.
我需要能够在整个站点中包含与webforms用户控件相似的组件,但不包括整个站点,而不是属于主页面的级别.这些组件应该有自己的代码,而不仅仅是标记(与业务层进行交互),如果页面控制器不需要知道控件就会很好.由于MVC用户控件没有代码隐藏,我看不到一个很好的方法来做到这一点.
更新
最后,一个好的(并且回想起来,明显的)这样做的方式.
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace K.ObjectModel.Controls { public class TestControl : ViewUserControl { protected override void Render(System.Web.UI.HtmlTextWriter writer) { writer.Write("Hello World"); base.Render(writer); } } }
创建一个继承ViewUserControl的新类
覆盖.Render()方法,如上所示.
通过其相关的ASCX注册控件,就像在WebForm中一样:
<%@ Register TagName =“tn”TagPrefix =“k”Src =“〜/ Views / Navigation / LeftBar.ascx”%>
在您需要的任何视图或母版页中使用相应的标签:
< k:tn runat =“server”/>
确保您的.ascx继承您的新控件:
<%@ Control Language =“C#”Inherits =“K.ObjectModel.Controls.TestControl”%>
Voila,你开始运行了.这是使用ASP.NET MVC 2,VS 2010和.NET 4.0进行测试.
您的自定义标签引用从TestControl类继承的ascx部分视图.然后,该控件将覆盖用于呈现视图的Render()方法,从而可以完全控制从标记到输出的过程.
使用这种方法和调用Html.RenderPartial()或“Html.RenderAction()”之间的区别是添加一个视图的控件是一个webforms样标签,这不仅对设计人员更加舒适,而且使它们不被必须知道控制器名称和方法.控制类的名称与ASCX隔离,也可以将它们放在程序集中,并将它们复制到单独的项目中.
有些人可能会说这违反了SoC,但我相信这种方法在功能上等同于将局部视图和控制器绑在一起,同时保持清晰的标记.然而,应该清楚的是,开发人员只能将控制中的演示相关逻辑保持在业务和数据访问逻辑仍属于各自的层.
解决方法
一旦你得到了知道的ASP.NET MVC,你会发现有several techniques for creating rich controls and components和封装方面的MVC遵循along the same pathways 封装一个WebForms应用程序.
我认为你所做的只是看MVC的View方面,而不是所有底层的M和C可以被封装在一起.部分视图,渲染动作/部分只是MVC的底层组件功能的一小部分.封面下有更丰富的丰富.