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

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

面包屑导航(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. [JS Compose] 0. Understand 'Box' or 'Container', they are just like Array!

    We'll examine how to unnest function calls, capture assignment, and create a linear data flow with a ...

  2. PL-SQL 存储函数和存储过程

     PL-SQL 存储函数和存储过程 ORACLE 提供能够把PL/SQL 程序存储在数据库中,并能够在不论什么地方来执行它.这样就叫存储过程或函数. 过程和函数统称为PL/SQL子程序.他们是被命 ...

  3. js后退一直停留在当前页面或者禁止后退

    //禁用后退按钮 function stopHistoryGo() { //禁用回退 window.location.hash="no-back-button"; window.l ...

  4. gtest 安装

    1.下载,https://code.google.com/p/googletest/.解压,进入该目录,按REAME说明 安装:1.5之前 make install可以安装,1.6之后不可以...安装 ...

  5. iOS工程集成支付宝错误Undefined symbols for architecture armv7

    问题描述: 新工程中需要集成支付宝功能,于是咱就把支付宝的库给集成了进入然后就出现了下面这种错误了说,错误信息如下: Undefined symbols for architecture armv7: ...

  6. C 语言函数参数只能传指针,不能传数组

    今天被要求编写一个C/C++冒泡算法的程序,心想这还不是手到擒来的事儿,虽然最近都是用Javascript程序,很少写C/C++程序,但是好歹也用过那么多年的C语言: 首先想的是怎么让自己的代码看上去 ...

  7. ping: sendto: Network is unreachable

    在我的板子上ping路由上的IP的时候可以ping通,但是ping外网的IP的时候提示"ping: sendto: Network is unreachable" 后来使用rout ...

  8. webpack+vue-loader 在单独.vue组件中使用sass-loader编译sass报错问题not a valid Win32 applictation

        如果webpack配置没有问题,在vue文件中编译sass/scss报上面的错误,大概是由于node-sass安装失败,重新卸载安装,   在国内安装node-sass失败的话,可以使用淘宝镜 ...

  9. fzu 2107 Hua Rong Dao(状态压缩)

    Problem 2107 Hua Rong Dao Accept: 106    Submit: 197 Time Limit: 1000 mSec    Memory Limit : 32768 K ...

  10. 说说你所熟知的MSSQL中的substring函数

    说说你所熟知的MSSQL中的substring函数 *:first-child { margin-top: 0 !important; } body>*:last-child { margin- ...