上篇文章我们完成了 动态生成多级菜单 这个实用组件。

本篇文章我们要开发另一个实用组件:面包屑导航。

面包屑导航(BreadcrumbNavigation)这个概念来自童话故事"汉赛尔和格莱特",当汉赛尔和格莱特穿过森林时,不小心迷路了,但是他们发现在沿途走过的地方都撒下了面包屑,让这些面包屑来帮助他们找到回家的路。所以,面包屑导航的作用是告诉访问者他们目前在网站中的位置以及如何返回。(摘自百度百科)

要实现面包屑导航,也可以直接从nuget搜一些sitemap组件直接使用。

当然,和上篇一样,我们同样不用任何第三方组件,完全自己构建灵活通用的sitemap.

下面给出我的最佳实践。

文章提纲

  • 概述要点
  • 详细步骤

    一、分析多级目录的html结构

    二、根据html结构构建xml的站点地图源及相应的data model

   三、构建html helper, 完成breadcrumb生成功能

   四、前端调用

  • 总结

概述要点

实现面包屑导航分成两个步骤:

1. 获取当前的url地址,根据url地址去相关配置文件中查询到当前位置,递归查询父节点

2. 根据查询到的结果动态拼接出 breadcrumb 的html

如果大家看了上篇文章应该会对这篇文章用到的技术很熟悉(比上篇文章更简单 : ))

我们直接根据站点的配置拼接出 html,前端通过自定义html helper的方法调用获取拼接出的内容。

关于如何自定义html helper,上篇文章有介绍,不再重复。

下面直接讲解详细步骤。

详细步骤

分成四个步骤

一、分析多级目录的html结构

首先打开一个样例,如下图

对应的html为

大家可以看到,由两层组成, 外面是一个<ol>, 里面是一组<li>。

每个<li>包含一个<a>标签,指向相应的位置地址。

最后的<li>不包含<a>标签,仅显示名字。

二、根据html结构构建xml的站点地图源及相应的data model

1. 根据上面的html结构,我们准备站点地图的数据源。

一般来说,站点地图不涉及到权限,也不会经常改变,如网站的某个位置没有配置,直接不显示即可,也不会有其他影响。

因此我们简单起见,直接准备个xml文档即可。

<?xml version="1.0" encoding="utf-8" ?>

<!--填绝对路径,类似 /XEngine/home/about-->

<MvcSiteMaps>

<MvcSiteMap ParnetID = "0" Name = "主页" Url = "/XEngine/" ID = "1" ></MvcSiteMap>

<MvcSiteMap ParnetID = "1" Name = "组织" Url = "/XEngine/Organization" ID = "2"></MvcSiteMap>

<MvcSiteMap ParnetID = "2" Name = "关于" Url = "/XEngine/home/about" ID = "3"></MvcSiteMap>

</MvcSiteMaps>

最终我们只需要将xml中相应的值填充到breadcrumb的html

2. 准备对应的data model

[XmlRoot("MvcSiteMaps")]

public class MvcSiteMaps

{

[XmlElement("MvcSiteMap")]

public MvcSiteMap[] Items { get; set; }

}

public class MvcSiteMap

{

[XmlAttribute(AttributeName = "ID")]

public int ID { get; set; }

[XmlAttribute(AttributeName = "Name")]

public string Name { get; set; }

[XmlAttribute(AttributeName = "Url")]

public string Url { get; set; }

[XmlAttribute(AttributeName = "ParnetID")]

public int ParnetID { get; set; }

public MvcSiteMap Parent { get; set; }

}

注意 [XmlAttribute(AttributeName = "xxx")],AttributeName需要和xml里面的名字对应,我们的xml和data model的命名完全对应,所以也可以省略。

三、构建html helper, 完成breadcrumb生成功能

需要完成以下几个功能

1. 获取xml中所有的节点信息

private static string SiteMapString = System.Configuration.ConfigurationManager.AppSettings["SiteMapString"] ?? string.Empty;

//获取sitemap的配置信息

public static IList<MvcSiteMap> GetSiteMapList()

{

using (TextReader reader = new StreamReader(HttpContext.Current.Server.MapPath(SiteMapString)))

{

var serializer = new XmlSerializer(typeof(MvcSiteMaps));

var items = (MvcSiteMaps)serializer.Deserialize(reader);

if (items != null)

{

return items.Items;

}

return null;

}

}

2. 根据上一步获取的节点信息及当前url地址,拼接出面包屑html

/// <summary>

/// 填充面包屑

/// </summary>

/// <param name="url"></param>

/// <returns></returns>

public static MvcHtmlString PopulateBreadcrumb(string url)

{

StringBuilder str = new StringBuilder();

List<string> pathList = new List<string>();

MvcSiteMap current = GetSiteMapList().FirstOrDefault(m=>m.Url==url);

GetParent(current, pathList);

pathList.Reverse();

for (int i = 0; i < pathList.Count; i++)

{

if (i == pathList.Count - 1)

{

string s = pathList[i];

s = s.Substring(s.IndexOf(">") + 1, s.LastIndexOf("<") - s.IndexOf(">") - 1);

str.AppendFormat("<li class='active'>{0}</li>", s);

}

else

{

str.AppendFormat("<li>{0}</li>", pathList[i]);

}

}

string result = str.ToString();

return MvcHtmlString.Create(result);

}

说明:首先找到当前位置,递归找出父节点依次添加到列表中;反转列表,完善html代码。

/// <summary>

/// 递归找到上一级

/// </summary>

/// <param name="parent"></param>

/// <param name="pathList"></param>

static void GetParent(MvcSiteMap parent, List<string> pathList)

{

if (parent != null)

{

pathList.Add(string.Format("<a href={0}>{1}</a>", parent.Url, parent.Name));

parent.Parent = GetSiteMapList().FirstOrDefault(i => i.ID == parent.ParnetID);

GetParent(parent.Parent, pathList);

}

}

四、前端调用

类似于上一篇文章,我们新建个html helper供前端调用。

这次我们稍微做一点改进(规范一下命名)

先看下微软原生的html helper定义方法,以Html.ActionLink为例,如下图

如方框处,类似于 xxxExtensions的命名,我们定义一个静态类来调用之前的方法。

前端调用:

以访问http://localhost/XEngine/home/about 为例,最终返回的结果

相应的html为:

<div>

<br />

<ol class="breadcrumb">

<li><a href=/XEngine/>主页</a></li><li><a href=/XEngine/Organization>组织</a></li><li class='active'>关于</li>

</ol>

</div>

总结

本篇对上篇的用到的html helper知识点做了细微改进 :

规范了自定义 html helper命名(类名为xxxExtensions和,原生形式统一);

直接返回MvcHtmlString类型,这样html字符串不会被转义,可以直接在前端调用。

自定义的 html helper非常实用,大家可以多多挖掘使用场景。

欢迎大家多多评论,祝学习进步:)

P.S.

示例中前端直接在_Layout.cshtml中使用。

后端菜单相关的程序结构:

MVC 5 + EF6 入门完整教程14 -- 动态生成面包屑导航的更多相关文章

  1. MVC5+EF6 入门完整教程13 -- 动态生成多级菜单

    稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据mode ...

  2. MVC5 + EF6 入门完整教程1

    https://www.cnblogs.com/miro/p/4030622.html 第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定& ...

  3. MVC5 + EF6 入门完整教程二

    从前端的UI开始 MVC分离的比较好,开发顺序没有特别要求,先开发哪一部分都可以,这次我们主要讲解前端UI的部分. ASP.NET MVC抛弃了WebForm的一些特有的习惯,例如服务器端控件,Vie ...

  4. MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用

    摘要: 第一阶段1~10篇已经覆盖了MVC开发必要的基本知识. 第二阶段11-20篇将会侧重于专题的讲解,一篇文章解决一个实际问题. 根据园友的反馈, 本篇文章将会先对呼声最高的仓储模式进行讲解. 文 ...

  5. MVC5+EF6 入门完整教程12--灵活控制Action权限

    大家久等了. 本篇专题主要讲述MVC中的权限方案. 权限控制是每个系统都必须解决的问题,也是园子里讨论最多的专题之一. 前面的系列文章中我们用到了 SysUser, SysRole, SysUserR ...

  6. MVC5+EF6 入门完整教程

    MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用 MVC5+EF6 入门完整教程10:多对多关联表更新&使用原生SQL@20150521 MVC5+EF6 入门完整教程9:多表 ...

  7. MVC5+EF6 入门完整教程九

    前一阵子临时有事,这篇文章发布间隔比较长,我们先回顾下之前的内容,每篇文章用一句话总结重点. 文章一 MVC核心概念简介,一个基本MVC项目结构 文章二 通过开发一个最基本的登录界面,介绍了如何从Co ...

  8. MVC5 + EF6 入门完整教程(转载)--01

    MVC5 + EF6 入门完整教程   第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定". 直接讲这些 "约定&qu ...

  9. MVC5+EF6 入门完整教程 总目录

    本系列文章会从一个主干开始,逐渐深入,初步规划30篇.初级10篇,中级10篇,综合项目实战10篇 初级10篇 MVC5+EF6 入门完整教程10:多对多关联表更新&使用原生SQL@201505 ...

随机推荐

  1. <[你在荒废时间的时候别人都在拼命!]>

    如果我在这里退缩了,那么再也不可能前进 当人有了目标的时候,就会有拼命努力的动力. 当一个人真的掌握了一些东西的时候,才会觉得踏实,这就是所谓的内涵. 人生其实就是这样一步步走过去的.付出总有回报,回 ...

  2. UML 六种关系

    .继承, 男人 和 人 的关系2.实现, 孕妇 和 生宝宝 的关系3.依赖, 人 和 大米.水4.关联, 男人 和 工作5.聚合, 弱整体和部分, 轮子和车6.组合, 强整体和部分, 眼睛和人 参考: ...

  3. Singleton<T>

    代码如下: public class Singleton<T> where T : class { private static T _instance; private static r ...

  4. Cubieboard2裸机开发之(五)看门狗操作

    前言 说到看门狗,应该不会陌生,看门狗说白了就是一个定时器,但是它有一个非常重要的功能就是复位系统.在A20里,看门狗的操作非常简单,只有两个寄存器,不需要操作时钟相关的东西,系统起来后可以直接使用, ...

  5. [转载]CSS教程:实例讲解定位Position

    http://www.missyuan.com/thread-395406-1-1.html 1. position:static 所有元素的默认定位都是:position:static,这意味着元素 ...

  6. MARIADB 在 OPENSUSE 的安装。

    1.MARIADB  在 OPENSUSE  的安装或者升级  (参考 Setting up MariaDB Repositories ) OPENSUSE 从 12.3 版本开始,默认带有 MARI ...

  7. OpenGL es3.0 初始化及渲染

    class FOpenglEs { public: /** * 初始化 OpenGLES3.0 */ bool initOpenGLES30(HWND hwnd) { EGLConfig config ...

  8. JQM[jquery mobile] 实战经验汇总

    动态装载的子页面(data-role=”page”),完全不用page div之外的tag,也不会起作用.子页面的javascript脚本必须写在page的</div>之前. 切换按钮(a ...

  9. 【Xamarin报错】libpng warning : iCCP: Not recognizing known sRGB profile that has been edited

    报错: Xamarin Android 编译时发生以下错误: libpng warning : iCCP: Not recognizing known sRGB profile that has be ...

  10. IT项目经理成长手记

    1.流程化,项目化,工业化: 2.启动,规划,实施,监控,收尾.五个过程 3.需求管理,项目策划,项目监控,集成项目管理,定量项目管理,供应商协议管理,风险管理. 4.项目经理是熬出来的,伟大都是熬出 ...