Ron*_*rby 47 asp.net-mvc breadcrumbs
如何使用ASP.net MVC实现动态面包屑?
如果你对面包屑是什么感到好奇:
什么是面包屑?好吧,如果您曾浏览过在线商店或在论坛中阅读帖子,您可能会遇到面包屑.它们提供了一种查看网站位置的简便方法.像Craigslist这样的网站使用面包屑来描述用户的位置.每页上面的列表上方都是这样的:
sf bayarea craigslist>旧金山市>自行车
我意识到SiteMapProvider可以实现的功能.我也知道网上的提供商可以让你将sitenodes映射到控制器和动作.
但是,当你想要一个breadcrumb的文本匹配一些动态值时,如下所示:
首页>产品>汽车>丰田
首页>产品>汽车>雪佛兰
首页>产品>执行器材>电动椅
主页>产品>执行设备>绞架
...产品类别和产品是数据库中的记录.应该静态定义一些链接(Home肯定).
我想弄清楚如何做到这一点,但我确信有人已经用ASP.net MVC完成了这个.
Sea*_*ddy 55
站点地图绝对是一种方式......或者,你可以自己写一个!(当然只要遵循标准的MVC规则)......我只写了一个,我想我会在这里分享.
@Html.ActionLink("Home", "Index", "Home")
@if(ViewContext.RouteData.Values["controller"].ToString() != "Home") {
@:> @Html.ActionLink(ViewContext.RouteData.Values["controller"].ToString(), "Index", ViewContext.RouteData.Values["controller"].ToString())
}
@if(ViewContext.RouteData.Values["action"].ToString() != "Index"){
@:> @Html.ActionLink(ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["action"].ToString(), ViewContext.RouteData.Values["controller"].ToString())
}
Run Code Online (Sandbox Code Playgroud)
希望有人会觉得这很有帮助,这正是我在寻找MVC面包屑时所寻找的.
vul*_*ven 26
在ASP.NET Core中,事情进一步优化,因为我们不需要在扩展方法中对标记进行字符串化.
在~/Extesions/HtmlExtensions.cs:
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace YourProjectNamespace.Extensions
{
public static class HtmlExtensions
{
private static readonly HtmlContentBuilder _emptyBuilder = new HtmlContentBuilder();
public static IHtmlContent BuildBreadcrumbNavigation(this IHtmlHelper helper)
{
if (helper.ViewContext.RouteData.Values["controller"].ToString() == "Home" ||
helper.ViewContext.RouteData.Values["controller"].ToString() == "Account")
{
return _emptyBuilder;
}
string controllerName = helper.ViewContext.RouteData.Values["controller"].ToString();
string actionName = helper.ViewContext.RouteData.Values["action"].ToString();
var breadcrumb = new HtmlContentBuilder()
.AppendHtml("<ol class='breadcrumb'><li>")
.AppendHtml(helper.ActionLink("Home", "Index", "Home"))
.AppendHtml("</li><li>")
.AppendHtml(helper.ActionLink(controllerName.Titleize(),
"Index", controllerName))
.AppendHtml("</li>");
if (helper.ViewContext.RouteData.Values["action"].ToString() != "Index")
{
breadcrumb.AppendHtml("<li>")
.AppendHtml(helper.ActionLink(actionName.Titleize(), actionName, controllerName))
.AppendHtml("</li>");
}
return breadcrumb.AppendHtml("</ol>");
}
}
}
Run Code Online (Sandbox Code Playgroud)
~/Extensions/StringExtensions.cs 保持不变如下(向下滚动以查看MVC5版本).
在剃刀视图中,我们不需要Html.Raw,因为Razor在处理时会处理转义IHtmlContent:
....
....
<div class="container body-content">
<!-- #region Breadcrumb -->
@Html.BuildBreadcrumbNavigation()
<!-- #endregion -->
@RenderBody()
<hr />
...
...
Run Code Online (Sandbox Code Playgroud)
===下面的原始/旧答案===
(扩展Sean Haddy的答案)
如果你想让它扩展驱动(保持视图干净),你可以做类似的事情:
在~/Extesions/HtmlExtensions.cs:
(与MVC5/bootstrap兼容)
using System.Text;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace YourProjectNamespace.Extensions
{
public static class HtmlExtensions
{
public static string BuildBreadcrumbNavigation(this HtmlHelper helper)
{
// optional condition: I didn't wanted it to show on home and account controller
if (helper.ViewContext.RouteData.Values["controller"].ToString() == "Home" ||
helper.ViewContext.RouteData.Values["controller"].ToString() == "Account")
{
return string.Empty;
}
StringBuilder breadcrumb = new StringBuilder("<ol class='breadcrumb'><li>").Append(helper.ActionLink("Home", "Index", "Home").ToHtmlString()).Append("</li>");
breadcrumb.Append("<li>");
breadcrumb.Append(helper.ActionLink(helper.ViewContext.RouteData.Values["controller"].ToString().Titleize(),
"Index",
helper.ViewContext.RouteData.Values["controller"].ToString()));
breadcrumb.Append("</li>");
if (helper.ViewContext.RouteData.Values["action"].ToString() != "Index")
{
breadcrumb.Append("<li>");
breadcrumb.Append(helper.ActionLink(helper.ViewContext.RouteData.Values["action"].ToString().Titleize(),
helper.ViewContext.RouteData.Values["action"].ToString(),
helper.ViewContext.RouteData.Values["controller"].ToString()));
breadcrumb.Append("</li>");
}
return breadcrumb.Append("</ol>").ToString();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在~/Extensions/StringExtensions.cs:
using System.Globalization;
using System.Text.RegularExpressions;
namespace YourProjectNamespace.Extensions
{
public static class StringExtensions
{
public static string Titleize(this string text)
{
return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(text).ToSentenceCase();
}
public static string ToSentenceCase(this string str)
{
return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]));
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用它(例如在_Layout.cshtml中):
....
....
<div class="container body-content">
<!-- #region Breadcrumb -->
@Html.Raw(Html.BuildBreadcrumbNavigation())
<!-- #endregion -->
@RenderBody()
<hr />
...
...
Run Code Online (Sandbox Code Playgroud)
ICo*_*fee 22
有一个工具可以在codeplex上执行此操作:http://mvcsitemap.codeplex.com/ [project moved to github]
编辑:
有一种方法可以从数据库派生SiteMapProvider:http: //www.asp.net/Learn/data-access/tutorial-62-cs.aspx
您可以修改mvcsitemap工具以使用它来获得所需内容.
我构建了这个 nuget 包来为自己解决这个问题:
https://www.nuget.org/packages/MvcBreadCrumbs/
如果您对此有想法,可以在这里做出贡献:
https://github.com/thelarz/MvcBreadCrumbs
对于那些使用 ASP.NET Core 2.0 并寻找比 vulcan 的 HtmlHelper 更解耦的方法的人,我建议看看使用带有依赖注入的部分视图。
下面是一个简单的实现,可以很容易地根据您的需要进行塑造。
面包屑服务 ( ./Services/BreadcrumbService.cs):
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System;
using System.Collections.Generic;
namespace YourNamespace.YourProject
{
public class BreadcrumbService : IViewContextAware
{
IList<Breadcrumb> breadcrumbs;
public void Contextualize(ViewContext viewContext)
{
breadcrumbs = new List<Breadcrumb>();
string area = $"{viewContext.RouteData.Values["area"]}";
string controller = $"{viewContext.RouteData.Values["controller"]}";
string action = $"{viewContext.RouteData.Values["action"]}";
object id = viewContext.RouteData.Values["id"];
string title = $"{viewContext.ViewData["Title"]}";
breadcrumbs.Add(new Breadcrumb(area, controller, action, title, id));
if(!string.Equals(action, "index", StringComparison.OrdinalIgnoreCase))
{
breadcrumbs.Insert(0, new Breadcrumb(area, controller, "index", title));
}
}
public IList<Breadcrumb> GetBreadcrumbs()
{
return breadcrumbs;
}
}
public class Breadcrumb
{
public Breadcrumb(string area, string controller, string action, string title, object id) : this(area, controller, action, title)
{
Id = id;
}
public Breadcrumb(string area, string controller, string action, string title)
{
Area = area;
Controller = controller;
Action = action;
if (string.IsNullOrWhiteSpace(title))
{
Title = Regex.Replace(CultureInfo.CurrentCulture.TextInfo.ToTitleCase(string.Equals(action, "Index", StringComparison.OrdinalIgnoreCase) ? controller : action), "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]));
}
else
{
Title = title;
}
}
public string Area { get; set; }
public string Controller { get; set; }
public string Action { get; set; }
public object Id { get; set; }
public string Title { get; set; }
}
}
Run Code Online (Sandbox Code Playgroud)
在startup.cs之后注册服务AddMvc():
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddTransient<BreadcrumbService>();
Run Code Online (Sandbox Code Playgroud)
创建一个局部来渲染面包屑 ( ~/Views/Shared/Breadcrumbs.cshtml):
@using YourNamespace.YourProject.Services
@inject BreadcrumbService BreadcrumbService
@foreach(var breadcrumb in BreadcrumbService.GetBreadcrumbs())
{
<a asp-area="@breadcrumb.Area" asp-controller="@breadcrumb.Controller" asp-action="@breadcrumb.Action" asp-route-id="@breadcrumb.Id">@breadcrumb.Title</a>
}
Run Code Online (Sandbox Code Playgroud)
此时,要呈现面包屑只需调用Html.Partial("Breadcrumbs")或Html.PartialAsync("Breadcrumbs")。
| 归档时间: |
|
| 查看次数: |
75212 次 |
| 最近记录: |