应用程序框架实战三十三:表现层及ASP.NET MVC介绍(二)

  最近的更新速度愈来愈慢,主要是项目上比较忙,封装EasyUi也要花不少时间。不过你们请放心,本系列不会半途夭折,而且代码干货也会持续更新。本文继续介绍表现层和Asp.net Mvc,我将在本篇讨论一些重要的设计问题和封装技巧。css

是否须要将控制器分离为独立项目

  常常有人问我,是否有必要将控制器从Web项目中分离出来,下面谈一下个人认识,仅供你参考,不必定正确,请根据你本身的实际状况决定。html

  控制器的做用是调用业务逻辑,将得到的结果传给视图显示。从根本上说,控制器只是起协调做用,它不该该自身完成复杂的业务逻辑。jquery

  不过哪怕你将业务逻辑尽可能放到了领域层,控制器上仍是会有很多代码,好比查询条件的设置,事务控制等。在这种状况下,将控制器分离到一个独立的程序集,彷佛说得过去。web

  可是分离控制器代码有不少方法,好比引入应用层服务,应用层服务能够当作是控制器的延伸,控制器上大部分代码被转移到应用层服务中,控制器变成很薄的一层,这种状况下,分离控制器到独立项目,没有任何价值。缓存

  将控制器分离到一个独立程序集后,你会发现查找控制器对应视图变得更加困难,哪怕Resharper能够帮你定位跳转。从目录结构上看,也再也不遵循你们熟悉的约定,实际上下降了可维护性,增长了学习成本。服务器

  最后的结论就是,若是你采用了应用层服务,就不要分离控制器。架构

是否须要将MVC项目拆分为多个

  对于表现层的模块化,MVC提供了Areas(区域)技术来支持较大项目的开发。每一个区域包含独立的控制器和相关视图,为每一个业务模块建立一个区域,对于通常项目的管理,应该都够用了。框架

  我在学习一些流行的应用开发框架时发现,有些应用开发框架将同一个Asp.Net Mvc项目,拆分为多个Mvc项目,以实现网站级别的模块化。其中一个是主Web项目,包含大部分WEB资源,好比图片、CSS、JS等。其它一些附属Web项目,包含其它业务模块,若是包含js文件,该文件的生成操做须要设置成“嵌入的资源”,包含的cshtml文件还须要用RazorGenerator插件手工生成类。最后主Web项目引用其它附属Web项目,从而整合为一个网站。模块化

  这种架构的好处是容许复用业务UI模块,包括视图,同时方便团队协做,不一样成员开发不一样模块时干扰更小。工具

  可是这种架构也有不少问题,将JS设置成“嵌入的资源”,cshtml文件使用RazorGenerator生成类,会致使JS和页面调试部署都很不方便,调试时常常会碰上缓存问题。

  解决UI复用和协同工做的另外一个办法是,多个网站独立开发部署,采用单点登陆链接成一个系统。

  对表现层的模块化建议以下:普通项目采用单Mvc项目架构,经过Areas进行模块化, 更大项目采用多Mvc项目架构,单独开发部署,以单点登陆方式集成,尽可能不要将js、cshtml等页面元素嵌入程序集,会致使更难维护,仅在具备特殊需求时采用,好比插件式开发。

Asp.Net Mvc抽象封装技巧

  对于技术和业务逻辑,咱们进行了复杂的分层和封装,那么对于页面自己,还要不要抽象?

  Html由标签组成,大量的Html标签,让你没法清晰的看出页面结构。当须要修改页面上某个区域时,若是页面很长很复杂,你须要在杂乱的Html标签中来回扫描,以定位目标,这与几百行的长方法相似。有经验的开发人员,老是以单一职责原则SRP为指导,经过提取方法和组合方法重构,保持方法的简短,同时得到清晰的代码结构。

  除了定位困难之外,未进行抽象的页面,将包含大量重复的Html,而冗余代码是可维护性的天敌。

  对于Asp.Net WebForm,抽象封装主要依赖母版页、服务器控件、用户控件等元素。

  母版页用于管理通用页面结构,帮助划分区域,它相似于抽象类,能够提供一部分具体实现,它将多个页面共享的部分抽取上来,并提供了内容占位符,占位符相似于虚方法或抽象方法,以方便具体页面填充内容。

  服务器控件用于封装可以高度复用的UI元素,提供加强功能,好比自定义文本框,通常的文本框只能输入文本,自定义文本框能够进行验证,甚至能进行权限控制等。

  用户控件是比服务器控件更轻量的封装方式,用户控件通常用于封装页面上的元素或区域。母版页的工做方式相似于继承,有经验的同窗知道,继承的灵活性是比较低的,因此设计上流传一句话“多用委托,少用继承”,WebForm的“委托”就是用户控件,它一样能够切割页面,而且提供了更好的灵活性。

  若是不少页面都须要分红上中下三个区域,每一个区域有一些固定的元素,这时候采用母版页就是合适的。但若是只有一个或几个页面须要这个结构,采用母版页将是大炮打蚊子,用户控件则是更好的选择。

  用户控件除了可以封装Html之外,还包含后置代码,能够处理逻辑。

  了解了WebForm的基础封装元素后,再来看Asp.Net Mvc提供了哪些元素,与Web Form的元素是如何对应的。

  首先看母版页,母版页的功能是提供布局结构,Mvc提供了布局页来支持相似功能。打开Mvc项目Views\Shared目录,会发现一个名为_Layout.cshtml的文件,这是系统定义的布局页,_Layout这个名称不是必须的,它可以起做用的缘由是Views目录下的_ViewStart.cshtml设置指向它。不过没事不要乱改系统定义的文件名,这样会破坏约定,增长维护成本。

  _ViewStart.cshtml包含了Layout的设置,它的做用是为视图提供默认布局设置,值得一提的是,根目录Views下的_ViewStart.cshtml设置不能继承,Areas各模块必须添加本身的_ViewStart.cshtml。

  对于较复杂的系统,仅依靠一个_Layout.cshtml来抽象页面冗余是不够的,通常须要多层继承结构,_Layout.cshtml仅放置通用性很强的内容,好比js,css引用等,更具体的抽象可定义本身的布局页,继承_Layout.cshtml。

  Asp.Net Mvc再也不提供服务器控件这种可视化元素,但相关的封装思想却从未间断。Mvc提供了HtmlHelper、UrlHelper、AjaxHelper等几个帮助类来封装相关操做,其中HtmlHelper包含表单元素的封装,是与WebForm服务器控件相对应的东西,咱们封装控件主要从它下手。

  Mvc容许在视图中经过Html属性访问HtmlHelper,能够看到,全部控件都是经过扩展方法的方式添加上去的,这也给咱们提供了一种思路。我在前文已经屡次提到,使用扩展方法要很当心,特别是扩展系统的类,由于可能形成大面积污染。

  对于HtmlHelper,我通常仅扩展少许方法,首先是通用UI技术的封装,我会把须要在视图上用到的通用技术封装到@Html.X()方法中,好比导入一个Js文件,能够这样调用@Html.X().ImportJs(“xx”),固然如今导入Js通常用Bundle,本篇后续再介绍。

  其次是对特定UI技术的封装,好比Dwz,EasyUi,Ext等,也多是其它组件,好比图表FusionCharts,ECharts等。对于每个要用到的组件,都仅为其在HtmlHelper扩展一个方法,以EasyUi为例,你不能这样扩展,@Html.EasyUiTextBox(),@Html.EasyUiCombox(),这样会在HtmlHelper中扩展大量方法,致使查找其它方法变得困难,更好的方法是@Html.EasyUi().TextBox() ,@Html.EasyUi().Combox()。这里设计的核心是EasyUi方法返回一个接口,将EasyUi全部操做所有放到这个接口中。关于Mvc的控件封装,我会在后续EasyUi系列详细讲述。

  最后,须要在HtmlHelper中扩展的是业务UI组件,好比字典、省市区三级联动、人员选择等,我会把全部业务UI组件扩展到@Html.Ui()方法中,以方便开发某些业务模块时复用,好比字典@Html.Ui().Dic()。

  下面来看WebForm用户控件在Mvc中有哪些对应元素。

  若是页面中的某个区域很复杂,根据逻辑结构,将区域分解为更小的部分,每一个部分放到一个用户控件中,从而获得清晰的结构。

  Mvc提供的@Html.Partial()方法容许将Html分离到部分视图中,并能够给这个部分视图传递一个实体,以进行数据绑定。

  不过部分视图的能力是有限的,你的主视图必须可以提供部分视图相关数据,这就要求主视图的实体携带更多的数据,这在不少时候都不太方便。打个比方,你的页面上须要显示一个下拉人员列表,列表的内容是用另外一个表的数据填充的,若是采用部分视图来封装这个列表,你的主视图对应的实体就必须提供人员集合。

  Mvc提供了更为强大的@Html.Action()方法,Action也用于操做部分视图,但它可以独立的为视图提供数据。仍是刚才的下拉人员列表,如今主视图的实体再也不须要携带人员数据了,调用Action后,人员列表已加载完成。

  虽然Action更强大,但它须要设置Url信息,以肯定这个功能由哪一个控制器的方法提供,当某个Action操做用得很是频繁时,考虑将该操做扩展到HtmlHelper中,这样能够封装掉Url和参数信息,以简化调用。

  以上简单介绍了Mvc的一些封装元素,以供你编写出更清晰的UI代码。同时比较了Asp.net WebForm与Mvc的元素对应状况,你若是具备WebForm的基础,相信Mvc的封装也会很快上手。

  补充一点,虽然我用方法与Html长度类比,但不能认为Html的封装粒度越细越好,我曾经尝试过很细粒度的UI拆分,最终效果并不理想,合适的拆分粒度更好维护,这方面根据本身的习惯进行摸索。

Bundle介绍

  如今的系统Js和Css文件都不少,若是一个网站引用太多Js或css文件,对性能是有必定影响的,由于每一个文件会发送一个请求。

  我之前的办法是使用AjaxMinifier工具手工压缩Js,再手工合并,Css也采用相似办法,后面使用了一个第三方的工具,也比较麻烦。

  Asp.Net为此提供了一个叫Bundle的打包压缩技术,它可以在运行时将js或css文件打包压缩,这正是我须要的。

  不过在使用过程当中,发现它并非想像中那么易用,问了一些人,也用起来有问题。还有一些人没碰到啥问题,但观察他的代码,实际上没有起做用,由于他没有设置启用优化的选项。

  使用Bundle有几点须要注意:

  1. 若是文件中的代码对路径很敏感,好比css中用了相对路径,你在配置Bundle时,虚拟路径就不能很随意,由于会破坏路径关系,致使失败。
  2. 若是没有在代码中设置BundleTable.EnableOptimizations = true,也没有在web.config进行相应配置,则打包压缩不会起做用,只是让你在引用文件时省点力。
  3. 已经压缩过的文件,好比jquery.min.js,不要用Bundle配置,使用常规方式引入,否则运行时可能出错。

Util最新代码示例更新

  除了以前的大量代码已重构外,主要更新了EasyUi的行内编辑方式。

结束语

本文简单介绍了Mvc相关的一些问题和技巧,有不一样意见,欢迎交流。

下载地址:下载时请顺手推荐,以支持本人写做.

http://files.cnblogs.com/files/xiadao521/Applications.2015.3.16.1.rar

http://files.cnblogs.com/files/xiadao521/Framework.2015.3.16.1.rar

http://files.cnblogs.com/files/xiadao521/Data.2015.3.5.1.rar

 

注意:本人每次发布新版本时,会删除老版本

 

.Net应用程序框架交流QQ群: 386092459,欢迎有兴趣的朋友加入讨论。

.Net Easyui开发交流QQ群(本群仅限Easyui开发者,非Easyui开发者勿进):157809322

谢谢你们的持续关注,个人博客地址:http://www.cnblogs.com/xiadao521/

相关文章
相关标签/搜索