在Asp.net MVC模式下实现网站地图导航

来源:互联网 发布:化工流程图软件 编辑:程序博客网 时间:2024/05/16 14:16

   今格式各样的导航栏、导航菜单已经成了网站不可缺少的一部分,WebForms中,一般使用SiteMapPath来实现网站地图导航功能。SiteMapPath服务器控件在MVC模式下中仍然可以工作,但是显然无法很好满足C-V结构的分离,还有就是SiteMapPath默认的XML文件的格式已无法满足MVChttp请求的规则。所以有必要做一个MVC下使用的,并且符合MVC设计规范的导航栏类,以在MVC中取代之前SiteMapPath的应用。



先看项目结构如图:



1:添加路由规则

Global.asax中:
public static void RegisterRoutes(RouteCollection routes)        {            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");            string[] nameSpaces = { "TestMvc3.Controllers" };            routes.MapRoute("default2", "Youku/Moive", new { Controller = "Moive", Action = "Index" }, nameSpaces);            routes.MapRoute("default", "{Controller}/{Action}", new { Controller = "Home", Action = "Index" },nameSpaces);        }
2:添加一个区域UserCenter并添加路由规则

using System.Web.Mvc;namespace TestMvc3.Areas.UserCenter{    public class UserCenterAreaRegistration : AreaRegistration    {        public override string AreaName        {            get            {                return "UserCenter";            }        }        public override void RegisterArea(AreaRegistrationContext context)        {            context.MapRoute(                "UserCenter_default",                "UserCenter/{controller}/{action}",                new { action = "Index" }            );        }    }}

3:构建用于导航的XML文件

我们在站点根目录下建立SiteMap.xml文件来写导航规则。里面的area属性是来应对存在区域的情况的。

<?xml version="1.0" encoding="utf-8"?><node title="首页" area="" action="Index" controller="Home">    <node title="电影" area="" action="Index" controller="Moive">        <node title="详细页" area="" action="Detail" controller="Moive" />    </node>    <node title="用户中心" area="UserCenter" action="Index" controller="Home" /></node>

4:编写用于导航的类MvcSiteMap类,它将遍历SiteMap.xml文件并生成导航链接。

它的核心就是利用UrlHelper类的Action方法和RouteLink方法来比较当前XML节点的属性所生成的链接和当前请求所生成的链接是否相同。这里不能用拼接controller和action字符串来比较的方式,因为可能存在改写过的路由规则。类的代码如下:

using System;using System.Collections.Generic;using System.Text;using System.Web;using System.Web.Mvc;using System.Xml.Linq;using System.Web.Routing;namespace TestMvc3{    public class MvcSiteMap    {        private static XDocument doc = XDocument.Load(HttpContext.Current.Server.MapPath(@"~/SiteMap.xml"));        private UrlHelper url = null;        private string currentURL = "";        public MvcSiteMap()        {            url = new UrlHelper(HttpContext.Current.Request.RequestContext);            currentURL = url.RouteUrl(HttpContext.Current.Request.RequestContext.RouteData.Values).ToLower();        }        public MvcHtmlString Navigator()        {            XElement c = FindNode(doc.Root);            Stack<XElement> temp = GetPath(c);            return MvcHtmlString.Create(BuildPathString(temp));        }        private string GetNodeUrl(XElement c)        {            return url.Action(c.Attribute("action").Value, c.Attribute("controller").Value, new { area = c.Attribute("area").Value });        }        private string BuildPathString(Stack<XElement> m)        {            StringBuilder sb = new StringBuilder();            TagBuilder tb;            TagBuilder tc = new TagBuilder("span");            tc.SetInnerText(">>");            string sp = tc.ToString();            int count = m.Count;            for (int x = 1; x <= count; x++)            {                XElement c = m.Pop();                if (x == count)                {                    tb = new TagBuilder("span");                }                else                {                    tb = new TagBuilder("a");                    tb.MergeAttribute("href", GetNodeUrl(c));                }                tb.SetInnerText(c.Attribute("title").Value);                sb.Append(tb.ToString());                sb.Append(sp);            }            return sb.ToString();        }        private Stack<XElement> GetPath(XElement c)        {            Stack<XElement> temp = new Stack<XElement>();            while (c != null)            {                temp.Push(c);                c = c.Parent;            }            return temp;        }        private bool IsUrlEqual(XElement c)        {            string a = GetNodeUrl(c).ToLower();            return a == currentURL;        }        private XElement RecursiveNode(XElement node)        {            foreach (XElement c in node.Elements())            {                if (IsUrlEqual(c) == true)                {                    return c;                }                else                {                    XElement x = RecursiveNode(c);                    if (x != null)                    { return x; }                }            }            return null;        }        private XElement FindNode(XElement node)        {            if (IsUrlEqual(node) == true)            {                return node;            }            else            {                return RecursiveNode(node);            }        }    }}

在使用的时候一般是在模板页面来使用此类。



效果图:








原创粉丝点击