mvcSiteMap 在 mvc 5 中创建 bredcrumb
mvcSiteMap create bredcrumb in mvc 5
我写信给你有一个问题。我有方法:
namespace NESTshop.Infrastructure
{
public class ProductListDynamicNodeProvider : DynamicNodeProviderBase
{
private ApplicationDbContext db = new ApplicationDbContext();
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
var returnValue = new List<DynamicNode>();
foreach (Category c in db.Category)
{
DynamicNode n = new DynamicNode();
n.Title = c.CategoryTitle;
n.Key = "Kategoria_" + c.CategoryID;
returnValue.Add(n);
}
return returnValue;
}
}
它应该给我面包屑(类别列表)。
我从类别中做了部分视图,因为我的主页上有类别列表。
模特类别:
namespace NESTshop.Models
{
public class Category
{
[Key]
public int CategoryID { get; set; }
[Display(Name ="Nazwa kategorii")]
public string CategoryTitle { get; set; }
[Display(Name ="Opis kategorii")]
public string CategoryDescription { get; set; }
[Display(Name = "Ikona Kategorii")]
public byte[] CategoryFile { get; set; }
[HiddenInput(DisplayValue = false)]
public string ImageMimeType { get; set; }
public virtual ICollection<Product> Product { get; set; }
}
}
部分查看产品类别
@using NESTshop.Models
@model List<Category>
<div class="jumbotron">
<h1>ASP.NET</h1>
<p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
<p><a href="http://asp.net" class="btn btn-primary btn-lg">Learn more »</a></p>
</div>
<div class="row">
<div class="col-md-12">
<h2>Kategorie</h2>
<ul class="categories">
@foreach (var cat in Model)
{
<li>
<img width="30" height="30"
src="@Url.Action("GetImage", "Categories", new { cat.CategoryID })" />
@*<img src="@Url.Content("~/Content/Images/Categories/" + cat.CategoryFile)" alt="" width="30" heigth="30"/>*@
@Html.ActionLink(cat.CategoryTitle, "ProductCategory", "Products", new { CategoryID = cat.CategoryID }, null)
</li>
}
</ul>
</div>
</div>
HomeController 操作类别列表:
public ActionResult CategoriesList()
{
List<Category> categories = categoryRepo.GetCategory().ToList();
return PartialView(categories);
}
我在 ProductCategory 视图中显示:
@using NESTshop.Models
@using NESTshop.Infrastructure
@model List<Product>
@{
ViewBag.Title = "ProductCategory";
}
@Html.MvcSiteMap().SiteMapPath() <--------
@if (User.IsInRole("Administrator"))
{
<p>
@Html.ActionLink("Create New", "Create")
</p>
}
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().ProductTitle)
</th>
@if (User.IsInRole("Administrator"))
{
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().ProductDescription)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().DateAdded)
</th>
}
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().ProductFile)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().Price)
</th>
@if (User.IsInRole("Administrator"))
{
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().IsBestseller)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().IsHidden)
</th>
}
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.ActionLink(Model.FirstOrDefault().ProductTitle, "Details", new { id = item.ProductID })
</td>
@if (User.IsInRole("Administrator"))
{
<td>
@Html.DisplayFor(modelItem => item.ProductDescription)
</td>
<td>
@Html.DisplayFor(modelItem => item.DateAdded)
</td>
}
<td>
@Html.DisplayFor(modelItem => item.ProductFile)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
@if (User.IsInRole("Administrator"))
{
<td>
@Html.DisplayFor(modelItem => item.IsBestseller)
</td>
<td>
@Html.DisplayFor(modelItem => item.IsHidden)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.ProductID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ProductID })
</td>
}
</tr>
}
</table>
问题之一,当我点击主页上的类别(测试类别 1)时,我得到了很好的面包屑(开始 > 测试类别 1),但是当我点击 2,3,4....类别 i具有相同的面包屑(开始 > 测试类别 1)。
你能帮我解决这个问题吗?非常感谢!
MVC 路由
面包屑基于当前节点。当前节点由当前请求的路由值决定。
因此您首先需要确保路由设置正确,以便将值作为路由值读入请求(与查询字符串值不同)。
路线选项 1
对所有主键使用 "id"。这是最简单的选项,因为默认路由是您唯一需要的。但是您需要确保构建您的 URL 和操作方法以使用 "id" 而不是 "CategoryID" 或 "ProductID".
@Html.ActionLink(cat.CategoryTitle, "ProductCategory", "Products", new { id = cat.CategoryID }, null)
路线选项 2
更改路由以考虑使用其他 "id" 值。这确保您的 URL 构建为路径的一部分 (/Products/ProductCategory/1234
) 而不是查询字符串的一部分 (/Products/ProductCategory?CategoryID=1234
)。
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Category",
url: "Products/ProductCategory/{CategoryID}",
defaults: new { controller = "Products", action = "ProductCategory" }
routes.MapRoute(
name: "Product",
url: "Products/{action}/{ProductID}",
defaults: new { controller = "Products", action = "Index" }
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
动态节点提供者
您在动态节点提供程序中负责两件事:
- 您必须为节点提供所有路由值才能创建与当前请求的匹配项
- 如果您有嵌套数据,则必须显式提供键-父键映射
ProductListDynamicNodeProvider.cs:
namespace NESTshop.Infrastructure
{
public class ProductListDynamicNodeProvider : DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
using (var db = new ApplicationDbContext())
{
foreach (Category c in db.Category)
{
DynamicNode n = new DynamicNode();
n.Title = c.CategoryTitle;
n.Key = "Kategoria_" + c.CategoryID;
// Optional: Add the parent key
// (and put a key="Home" on the node that you want these nodes children of)
//n.ParentKey = "Home";
// Add your route values
// Route Option 1
n.RouteValues("id", c.CategoryID);
// Route Option 2
// n.RouteValues("CategoryID", c.CategoryID);
// Optional: Add any route values to match regardless of value
// n.PreservedRouteParameters.Add("myKey");
yield return n;
}
}
}
}
}
ProductDetailsDynamicNodeProvider.cs
namespace NESTshop.Infrastructure
{
public class ProductDetailsDynamicNodeProvider : DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
using (var db = new ApplicationDbContext())
{
foreach (Product p in db.Product)
{
DynamicNode n = new DynamicNode();
n.Title = p.ProductTitle;
n.Key = "Product_" + p.ProductID;
// IMPORTANT: Setup the relationship with the
// parent node (category) by using the foreign key in
// your database. ParentKey must exactly match the Key
// of the node this node is to be a child of.
// If this is a many-to-many relationship, you will need
// to join to the table that resolves the relationship above
// and use the right key here.
n.ParentKey = "Kategoria_" + p.CategoryID;
// Add your route values
// Route Option 1
n.RouteValues("id", p.ProductID);
// Route Option 2
// n.RouteValues("ProductID", p.ProductID);
// Optional: Add any route values to match regardless of value
// n.PreservedRouteParameters.Add("myKey");
yield return n;
}
}
}
}
}
Mvc.sitemap
如果你上面的选项设置了key为"Home",你需要在你的SiteMap
"Home"中做一个节点的key,这样就有一个节点可以嵌套了它在.
<mvcSiteMapNode title="Start" controller="Home" action="Index" key="Home">
我将向您展示我的 routConfig 和站点地图文件代码:
<mvcSiteMapNode title="Start" controller="Home" action="Index">
<mvcSiteMapNode title="Kategoria" controller="Products" action="ProductCategory" dynamicNodeProvider="NESTshop.Infrastructure.ProductListDynamicNodeProvider, NESTshop">
<mvcSiteMapNode title="Produkt" controller="Products" action="Index" dynamicNodeProvider="NESTshop.Infrastructure.ProductDetailsDynamicNodeProvider, NESTshop"/>
</mvcSiteMapNode>
这里是 routConfig:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
我写信给你有一个问题。我有方法:
namespace NESTshop.Infrastructure
{
public class ProductListDynamicNodeProvider : DynamicNodeProviderBase
{
private ApplicationDbContext db = new ApplicationDbContext();
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
var returnValue = new List<DynamicNode>();
foreach (Category c in db.Category)
{
DynamicNode n = new DynamicNode();
n.Title = c.CategoryTitle;
n.Key = "Kategoria_" + c.CategoryID;
returnValue.Add(n);
}
return returnValue;
}
}
它应该给我面包屑(类别列表)。
我从类别中做了部分视图,因为我的主页上有类别列表。
模特类别:
namespace NESTshop.Models
{
public class Category
{
[Key]
public int CategoryID { get; set; }
[Display(Name ="Nazwa kategorii")]
public string CategoryTitle { get; set; }
[Display(Name ="Opis kategorii")]
public string CategoryDescription { get; set; }
[Display(Name = "Ikona Kategorii")]
public byte[] CategoryFile { get; set; }
[HiddenInput(DisplayValue = false)]
public string ImageMimeType { get; set; }
public virtual ICollection<Product> Product { get; set; }
}
}
部分查看产品类别
@using NESTshop.Models
@model List<Category>
<div class="jumbotron">
<h1>ASP.NET</h1>
<p class="lead">ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.</p>
<p><a href="http://asp.net" class="btn btn-primary btn-lg">Learn more »</a></p>
</div>
<div class="row">
<div class="col-md-12">
<h2>Kategorie</h2>
<ul class="categories">
@foreach (var cat in Model)
{
<li>
<img width="30" height="30"
src="@Url.Action("GetImage", "Categories", new { cat.CategoryID })" />
@*<img src="@Url.Content("~/Content/Images/Categories/" + cat.CategoryFile)" alt="" width="30" heigth="30"/>*@
@Html.ActionLink(cat.CategoryTitle, "ProductCategory", "Products", new { CategoryID = cat.CategoryID }, null)
</li>
}
</ul>
</div>
</div>
HomeController 操作类别列表:
public ActionResult CategoriesList()
{
List<Category> categories = categoryRepo.GetCategory().ToList();
return PartialView(categories);
}
我在 ProductCategory 视图中显示:
@using NESTshop.Models
@using NESTshop.Infrastructure
@model List<Product>
@{
ViewBag.Title = "ProductCategory";
}
@Html.MvcSiteMap().SiteMapPath() <--------
@if (User.IsInRole("Administrator"))
{
<p>
@Html.ActionLink("Create New", "Create")
</p>
}
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().ProductTitle)
</th>
@if (User.IsInRole("Administrator"))
{
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().ProductDescription)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().DateAdded)
</th>
}
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().ProductFile)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().Price)
</th>
@if (User.IsInRole("Administrator"))
{
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().IsBestseller)
</th>
<th>
@Html.DisplayNameFor(model => model.FirstOrDefault().IsHidden)
</th>
}
<th></th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.ActionLink(Model.FirstOrDefault().ProductTitle, "Details", new { id = item.ProductID })
</td>
@if (User.IsInRole("Administrator"))
{
<td>
@Html.DisplayFor(modelItem => item.ProductDescription)
</td>
<td>
@Html.DisplayFor(modelItem => item.DateAdded)
</td>
}
<td>
@Html.DisplayFor(modelItem => item.ProductFile)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
@if (User.IsInRole("Administrator"))
{
<td>
@Html.DisplayFor(modelItem => item.IsBestseller)
</td>
<td>
@Html.DisplayFor(modelItem => item.IsHidden)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id = item.ProductID }) |
@Html.ActionLink("Delete", "Delete", new { id = item.ProductID })
</td>
}
</tr>
}
</table>
问题之一,当我点击主页上的类别(测试类别 1)时,我得到了很好的面包屑(开始 > 测试类别 1),但是当我点击 2,3,4....类别 i具有相同的面包屑(开始 > 测试类别 1)。
你能帮我解决这个问题吗?非常感谢!
MVC 路由
面包屑基于当前节点。当前节点由当前请求的路由值决定。
因此您首先需要确保路由设置正确,以便将值作为路由值读入请求(与查询字符串值不同)。
路线选项 1
对所有主键使用 "id"。这是最简单的选项,因为默认路由是您唯一需要的。但是您需要确保构建您的 URL 和操作方法以使用 "id" 而不是 "CategoryID" 或 "ProductID".
@Html.ActionLink(cat.CategoryTitle, "ProductCategory", "Products", new { id = cat.CategoryID }, null)
路线选项 2
更改路由以考虑使用其他 "id" 值。这确保您的 URL 构建为路径的一部分 (/Products/ProductCategory/1234
) 而不是查询字符串的一部分 (/Products/ProductCategory?CategoryID=1234
)。
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Category",
url: "Products/ProductCategory/{CategoryID}",
defaults: new { controller = "Products", action = "ProductCategory" }
routes.MapRoute(
name: "Product",
url: "Products/{action}/{ProductID}",
defaults: new { controller = "Products", action = "Index" }
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
动态节点提供者
您在动态节点提供程序中负责两件事:
- 您必须为节点提供所有路由值才能创建与当前请求的匹配项
- 如果您有嵌套数据,则必须显式提供键-父键映射
ProductListDynamicNodeProvider.cs:
namespace NESTshop.Infrastructure
{
public class ProductListDynamicNodeProvider : DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
using (var db = new ApplicationDbContext())
{
foreach (Category c in db.Category)
{
DynamicNode n = new DynamicNode();
n.Title = c.CategoryTitle;
n.Key = "Kategoria_" + c.CategoryID;
// Optional: Add the parent key
// (and put a key="Home" on the node that you want these nodes children of)
//n.ParentKey = "Home";
// Add your route values
// Route Option 1
n.RouteValues("id", c.CategoryID);
// Route Option 2
// n.RouteValues("CategoryID", c.CategoryID);
// Optional: Add any route values to match regardless of value
// n.PreservedRouteParameters.Add("myKey");
yield return n;
}
}
}
}
}
ProductDetailsDynamicNodeProvider.cs
namespace NESTshop.Infrastructure
{
public class ProductDetailsDynamicNodeProvider : DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
using (var db = new ApplicationDbContext())
{
foreach (Product p in db.Product)
{
DynamicNode n = new DynamicNode();
n.Title = p.ProductTitle;
n.Key = "Product_" + p.ProductID;
// IMPORTANT: Setup the relationship with the
// parent node (category) by using the foreign key in
// your database. ParentKey must exactly match the Key
// of the node this node is to be a child of.
// If this is a many-to-many relationship, you will need
// to join to the table that resolves the relationship above
// and use the right key here.
n.ParentKey = "Kategoria_" + p.CategoryID;
// Add your route values
// Route Option 1
n.RouteValues("id", p.ProductID);
// Route Option 2
// n.RouteValues("ProductID", p.ProductID);
// Optional: Add any route values to match regardless of value
// n.PreservedRouteParameters.Add("myKey");
yield return n;
}
}
}
}
}
Mvc.sitemap
如果你上面的选项设置了key为"Home",你需要在你的SiteMap
"Home"中做一个节点的key,这样就有一个节点可以嵌套了它在.
<mvcSiteMapNode title="Start" controller="Home" action="Index" key="Home">
我将向您展示我的 routConfig 和站点地图文件代码:
<mvcSiteMapNode title="Start" controller="Home" action="Index">
<mvcSiteMapNode title="Kategoria" controller="Products" action="ProductCategory" dynamicNodeProvider="NESTshop.Infrastructure.ProductListDynamicNodeProvider, NESTshop">
<mvcSiteMapNode title="Produkt" controller="Products" action="Index" dynamicNodeProvider="NESTshop.Infrastructure.ProductDetailsDynamicNodeProvider, NESTshop"/>
</mvcSiteMapNode>
这里是 routConfig:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}