在WebForms中,大家应该都体会过SiteMapPath给开发带来的便利,而今格式各样的导航栏、导航菜单已经成了网站不可缺少的一部分,接下去大家会看到一个在MVC下使用的,并且符合MVC设计规范的导航栏“插件”,以在MVC中取代之前SiteMapPath的应用。
首先我们还是明确一下这个插件的意义和需要完成的基本功能:
问:既然有SiteMapPath,为什么还要重复开发一个同样功能的导航栏?
答:没错,SiteMapPath服务器控件在MVC(以下无特别说明都专指ASP.NET MVC)中仍然可以很好地“显示”,但是显然无法很好满足C-V结构的分离,SiteMapPath控件依赖于aspx页面,而在MVC中,早在aspx页面执行之前,几乎所有数据都应该在Controller处理完成,“打包”给ViewData。这就要求这个控件能够同时在Controller和View中被很好地控制,并且View主要只起到显示的作用。还有一点就是SiteMapPath默认的sitemap格式已经无法满足MVC中http请求的规则,使得无法很好地进行控制。
问:新开发的导航栏有哪些功能?
答:
1、完全兼容原有WebForms项目下的Web.sitemap文件格式,即当网站中同时存在MVC和WebForms项目时, 可以共享sitemap文件。但须按照MVC的执行方式对原有文件稍加补充。
2、自动从Web.sitemap获得当前页面(Controller,Action)对应的网站地图位置,自动生成导航条, 使用时不需要编写任何代码。
3、根据MVC的Controller-Action规则自动创建对应链接,也可自由设置,包括只显示文字,不使用连接等。
4、可以完全或部分手动设置、增减节点。
5、可以限制节点显示层数。
以上的大部分功能都是在SiteMapPath可实现的,但是我们已经不再需要PostBack功能的设置。
遵照这些前提,我给大家展示一下我的实现方法:
一、建立全局共享的Model层的NavigationInfo,包含在Models/ExtentionEntity.cs中
其中,Title、ActionName、ControllerName、Values分别对应View页面ActionLink需要的链接文字、action、controller和values。里面也提供了对NavigationInfo的4种重写的方法,以便和ActionLink的参数重写尽量配套,在适应使用习惯的同时也提供了更大的灵活性。
二、创建BaseViewData,所有继承了这个类的ViewData都将获得NavigationInfo属性。Models/BaseViewData.cs
三、创建Views/Shared/Navigation.ascx,供页面调用。
注:这里我使用了用户控件的形式是因为考虑到开发时实际调用导航栏的页面不会太多(一般都只在母板页),如果你觉引用的比较多,这样不太方便,也可以加到HtmlHelper中,其中要执行的代码是一样的:
在aspx中,我们只需要这样引用就行了:
四、准备工作基本做好了,下面来看一下在Controller中如何对导航栏灵活控制。
在此之前,我需要在Common中建了一个专门负责处理NavigationInfo的类Common/Navigation.cs:
上面可以看到,相比使用XMLDocument的传统方式,Linq to XML大大简化了对XML的操作。其中关键的地方都作了比较详细的注释,欢迎大家提出建议或批评!
下面是上述方法在Controller中的使用。
注:这里还有一个注意点:虽然NavigationInfo中的Title提供直接在ActionLink中显示的text内容,但是建议不要在Controller中定义的过死,否则可能导致C-V数据的脱节,我在Controller演示设置NavigationInfo的功能,并不在于要在Controller中就把导航栏HTML代码输出,只是输出一个包含节点信息的List给ViewDate,让其在View中具体生成。
我举NavController为例,里面有一个Action叫void More(string type):
通过上面case的4种情况我向大家演示了文章开头我们需要完成的5项基本功能,其中如果你不需要对导航栏信息修改,让其自动获取的话,只要传递一个BaseViewData给页面,什么都不用做:
而接下去在aspx页面(Views)中,你可以什么都不要做,如果需要获取信息或者修改的话只需要查看ViewData.NavInfo或者ViewData[“NavInfo”]就行了。
这里要小说一下上面提到的BaseViewData的Title参数,是用于网页标题Title的显示,由于Title基本属于View层面的东西,在这里设Title主要是方便Controller和View的沟通,具体设置也可以在View中完成(我还是觉得在程序员和美工有很好沟通的情况下,在Controller先设置好基础部分更方便一些,而且不用劳烦每个aspx文件都对title设置,那样有时实在很辛苦)。这个Title你只需要设置最“个性化”的信息,全局的包括每个母板的特定信息会自动加上。有了这个功能,你还可以自己进行一些扩展,比如:把导航栏的最后一个节点的信息作为标题等等。由于和导航栏没有非常直接的关系,这里我暂不多加论述,具体应用你可以在我的Demo中的母板页文件看到(注意.Master.cs文件)
这里是上面代码的Demo下载:/Files/szw/MVCTools_mvc.rar
补充一下,对于sitemap的变化,只是为每个节点多加了两个controller和action属性,以控制节点显示的链接,具体大家可以看Demo中的Web.sitemap
这个导航栏的实现很简单,希望能够发上来抛砖引玉,也省去一些朋友重复劳动之苦。如果有任何不周之处,还望大家见谅和赐教!