MVC 5 + EF6 入门完整教程14 -- 动态生成面包屑导航
上篇文章我们完成了 动态生成多级菜单 这个实用组件。
本篇文章我们要开发另一个实用组件:面包屑导航。
面包屑导航(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 -- 动态生成面包屑导航的更多相关文章
- MVC5+EF6 入门完整教程13 -- 动态生成多级菜单
稍微有一定复杂性的系统,多级菜单都是一个必备组件. 本篇专题讲述如何生成动态多级菜单的通用做法. 我们不用任何第三方的组件,完全自己构建灵活通用的多级菜单. 需要达成的效果:容易复用,可以根据mode ...
- MVC5 + EF6 入门完整教程1
https://www.cnblogs.com/miro/p/4030622.html 第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定& ...
- MVC5 + EF6 入门完整教程二
从前端的UI开始 MVC分离的比较好,开发顺序没有特别要求,先开发哪一部分都可以,这次我们主要讲解前端UI的部分. ASP.NET MVC抛弃了WebForm的一些特有的习惯,例如服务器端控件,Vie ...
- MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用
摘要: 第一阶段1~10篇已经覆盖了MVC开发必要的基本知识. 第二阶段11-20篇将会侧重于专题的讲解,一篇文章解决一个实际问题. 根据园友的反馈, 本篇文章将会先对呼声最高的仓储模式进行讲解. 文 ...
- MVC5+EF6 入门完整教程12--灵活控制Action权限
大家久等了. 本篇专题主要讲述MVC中的权限方案. 权限控制是每个系统都必须解决的问题,也是园子里讨论最多的专题之一. 前面的系列文章中我们用到了 SysUser, SysRole, SysUserR ...
- MVC5+EF6 入门完整教程
MVC5+EF6 入门完整教程11--细说MVC中仓储模式的应用 MVC5+EF6 入门完整教程10:多对多关联表更新&使用原生SQL@20150521 MVC5+EF6 入门完整教程9:多表 ...
- MVC5+EF6 入门完整教程九
前一阵子临时有事,这篇文章发布间隔比较长,我们先回顾下之前的内容,每篇文章用一句话总结重点. 文章一 MVC核心概念简介,一个基本MVC项目结构 文章二 通过开发一个最基本的登录界面,介绍了如何从Co ...
- MVC5 + EF6 入门完整教程(转载)--01
MVC5 + EF6 入门完整教程 第0课 从0开始 ASP.NET MVC开发模式和传统的WebForm开发模式相比,增加了很多"约定". 直接讲这些 "约定&qu ...
- MVC5+EF6 入门完整教程 总目录
本系列文章会从一个主干开始,逐渐深入,初步规划30篇.初级10篇,中级10篇,综合项目实战10篇 初级10篇 MVC5+EF6 入门完整教程10:多对多关联表更新&使用原生SQL@201505 ...
随机推荐
- CentOS6下Haproxy的安装配置
Haproxy 是一个开源的负载均衡和反向代理软件,其提供了高可用的网络服务.其一般是应用于web服务,但同时也能为SMTP和终端服务等提供可靠的支持. 1.下载安装haproxy wget ftp: ...
- CAS认证原理图
- SQLServer 获得所有表结构(包括表名及字段)
then d.name else null end) 表名, a.colorder 字段序号,a.name 字段名, ( then '√'else '' end) 标识, (case when (SE ...
- 用 Python 通过马尔可夫随机场(MRF)与 Ising Model 进行二值图降噪
前言 这个降噪的模型来自 Christopher M. Bishop 的 Pattern Recognition And Machine Learning (就是神书 PRML……),问题是如何对一个 ...
- [原]如何用Android NDK编译FFmpeg
我们知道在Ubuntu下直接编译FFmpeg是很简单的,主要是先执行./configure,接着执行make命令来编译,完了紧接着执行make install执行安装.那么如何使用Android的ND ...
- HTML5[3]:中文换行
保证中文每行第一个字,不会出现标点符号 p { white-space: pre-wrap; }
- `fw服务端非完整` 工程开发初期的工作
前面写到了一些关于cocos2dx在开发中的一些模块以及一些解决方法,那些都属于本人的个人简介和个人倾向的解决方案.最近这几天我完善了一下ui解析的部分,当然也只是抽出一点点时间去做的这件事情.我添加 ...
- linux rdate
检查服务器时间,发现服务器时间与当前时间错了很多.于是调整. 使用ntpdate ,不管如何设置,包括关闭防火期,设置ntp.conf,结果都不成功. 随即使用网上提供的另外一种方法,临时先解决一下燃 ...
- 二叉查找树(一)之 图文解析 和 C语言的实现
概要 本章先对二叉树的相关理论知识进行介绍,然后给出C语言的详细实现.关于二叉树的学习,需要说明的是:它并不难,不仅不难,而且它非常简单.初次接触树的时候,我也觉得它似乎很难:而之所产生这种感觉主要是 ...
- ReflectionToStringBuilder
1. 使用背景 后台接口需要在接口调用的初期,记录下面查询(修改)对象的参数. 2. 使用方法 通过Apache 工具类 输出entity对象所有属性值 <dependency> < ...