我已经实现了这个 https://github.com/maartenba/MvcSiteMapProvider/wiki/Defining-sitemap-nodes-using-IDynamicNodeProvider
编辑:这是我的课
public class MyDynamicNodeProvider
: DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
webdata storeDB = new webdata();
var returnValue = new List<DynamicNode>();
foreach (var article in storeDB.SiteContents)
{
DynamicNode enode = new DynamicNode();
enode.Title = article.ArticleTitle;
enode.ParentKey = "ArticleID";
enode.Url = "ArticleDetails/" + article.ArticleID + "/" + article.ArticleAlias;
//Specify Controller and Action name
enode.Controller = "SiteContents";
enode.Action = "ArticleDetails";
enode.RouteValues.Add("id", article.ArticleID);
returnValue.Add(enode);
yield return enode;
}
}
}
编辑:这是我的站点地图文件
<mvcSiteMapNode title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="About Us" controller="Menu" action="AboutUs">
<mvcSiteMapNode title="Profile" controller="Menu" action="Profile"/>
<mvcSiteMapNode title="History" controller="Menu" action="History"/>
</mvcSiteMapNode>
<mvcSiteMapNode title="Article" controller="SiteContents" action="ArticleDetails" key="ArticleID">
<mvcSiteMapNode title="Details" dynamicNodeProvider="Myproject.Models.MyDynamicNodeProvider, Myproject" />
</mvcSiteMapNode>
编辑:我拥有的第二个控制器(SiteContent控制器)
public ActionResult ArticleDetails(int? id, string slug)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
SiteContents siteContents = db.SiteContents.Find(id);
if (siteContents == null)
{
return HttpNotFound();
}
if (string.IsNullOrWhiteSpace(slug))
{
var alias = db.SiteContents.First(p => p.ArticleID == id).ArticleAlias;
return RedirectToAction("ArticleDetails", new { id = id, slug = alias });
}
return View(siteContents);
}
我想要的网址(有效,但它没有带来站点地图是http://localhost:xxxx/ArticleDetails/1/Quality_Policy
我在我的布局页面上调用站点地图
@Html.MvcSiteMap().SiteMapPath()
编辑:我的路线.config
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(name: "Articles", url: "ArticleDetails/{id}/{slug}", defaults: new { controller = "SiteContents", action = "ArticleDetails", id = UrlParameter.Optional, slug = UrlParameter.Optional });
routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new {controller = "Home", action = "Index", id = UrlParameter.Optional});
}
我还有一些工作正常的静态节点。问题是在动态页面中什么也没返回,我没有收到任何错误消息谢谢
它不起作用的原因是您没有考虑所有路由值,即您有一个名为 slug
的路由值,您需要配置节点以匹配。
如果希望节点匹配而不考虑slug
的值(即使它是空白的),则应使用 PreservedRouteParameters
来匹配它。否则,应将其添加到RouteValues
节点将仅匹配您为其配置的一个值(如果需要,可以添加其他节点以匹配其他值)。我在这里展示PreservedRouteParameters
方法。
此外,通过在动态节点上配置 Url
属性,您有效地禁用了 MVC 支持。如果需要使用非 MVC 页或外部 URL,此属性很有用,但不建议用于 MVC。
MvcSiteMapProvider
直接取决于 MVC 路由配置。您可以在此处配置 URL 以使其外观。要使预期的 URL ( http://localhost:xxxx/ArticleDetails/1/Quality_Policy
) 正常工作,您需要相应的路由来匹配此模式,如下所示。
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
// Route to match the URL /ArticleDetails/1/Quality_Policy
routes.MapRoute(
name: "ArticleDetails",
url: "ArticleDetails/{id}/{slug}",
defaults: new { controller = "SiteContents", action = "ArticleDetails", slug = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
您遇到的另一个问题是将动态节点附加到的节点。您配置节点的方式当前将转到ArticleDetails
操作。我不知道你想在这里做什么。通常,您会显示所有文章页面的列表(索引),然后当用户单击文章时,将显示它。下面是一个示例。
// NOTE: Normally, you would put all of your Article stuff
// into an ArticleController
public class SiteContentsController
{
// NOTE: Normally, this would be named ArticleController.Index()
public ActionResult ArticleIndex()
{
// NOTE: You may want to use a view model here
// rather than using the SiteContents directly.
var siteContents = db.SiteContents.ToList();
return View(siteContents);
}
// NOTE: Normally, this would be named ArticleController.Details()
public ActionResult ArticleDetails(int? id, string slug)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
SiteContents siteContents = db.SiteContents.Find(id);
if (siteContents == null)
{
return HttpNotFound();
}
if (string.IsNullOrWhiteSpace(slug))
{
var alias = db.SiteContents.First(p => p.ArticleID == id).ArticleAlias;
return RedirectToAction("ArticleDetails", new { id = id, slug = alias });
}
return View(siteContents);
}
}
您的Mvc.sitemap
文件看起来更像这样(文章位于主页下方)。我相信这是您的主要问题 - 您的 XML 文件中必须只有一个根节点(通常是站点的主页)。
<mvcSiteMapNode title="Home" controller="Home" action="Index">
<mvcSiteMapNode title="About Us" controller="Menu" action="AboutUs">
<mvcSiteMapNode title="Profile" controller="Menu" action="Profile">
<mvcSiteMapNode title="Quality Policy" controller="Menu" action="Policy"/>
</mvcSiteMapNode>
<mvcSiteMapNode title="History" controller="Menu" action="History"/>
<mvcSiteMapNode title="Articles" controller="SiteContents" action="ArticleIndex" key="Articles">
<mvcSiteMapNode title="Details" dynamicNodeProvider="Myproject.Models.MyDynamicNodeProvider, Myproject" />
</mvcSiteMapNode>
</mvcSiteMapNode>
最后,我们有更正DynamicNodeProvider
.
public class MyDynamicNodeProvider
: DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
webdata storeDB = new webdata();
foreach (var article in storeDB.SiteContents)
{
DynamicNode enode = new DynamicNode();
enode.Title = article.ArticleTitle;
enode.ParentKey = "Articles";
// Don't use the Url property unless you have a
// non-MVC page/external URL
//enode.Url = "ArticleDetails/" + article.ArticleID + "/" + article.ArticleAlias;
// Specify Controller, Action name, and id.
// These values all must match the request in order
// for the node to be considered the "current" node
enode.Controller = "SiteContents";
enode.Action = "ArticleDetails";
enode.RouteValues.Add("id", article.ArticleID);
// Match the slug (we don't really care what its value is here)
enode.PreservedRouteParameters.Add("slug");
yield return enode;
}
}
}