来自数据库的动态站点地图不显示节点

Dynamic sitemap from database doesn't display the nodes

我已经实现了这个https://github.com/maartenba/MvcSiteMapProvider/wiki/Defining-sitemap-nodes-using-IDynamicNodeProvider

编辑:这是我的class

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>

编辑:我拥有的第二个控制器 (SiteContentsController)

  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);
      }

我想要的url(可以,但不带站点地图 是 http://localhost:xxxx/ArticleDetails/1/Quality_Policy

我在布局页面调用站点地图

@Html.MvcSiteMap().SiteMapPath()

编辑:我的route.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});


    }

我还有一些工作正常的静态节点。问题是在动态页面 returns 中什么都没有,我没有收到任何错误消息 谢谢

它不起作用的原因是您没有考虑所有路由值,即您有一个名为 slug 的路由值,您需要配置节点以匹配它。

如果你想让节点匹配而不考虑slug的值(即使它是空白),你应该使用PreservedRouteParameters来匹配它。否则,您应该将其添加到 RouteValues 并且该节点将仅匹配您为其配置的 one 值(如果需要,您可以添加其他节点以匹配其他值)。我在这里展示 PreservedRouteParameters 方法。

此外,您通过在动态节点上配置 Url 属性 有效地禁用了 MVC 支持。如果您需要使用非 MVC 页面或外部 URL,此 属性 很有用,但不推荐用于 MVC。

MvcSiteMapProvider直接依赖MVC路由配置。这是您配置 URLs 以查看您希望它们的外观的地方。为了使您预期的 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;
        }
    }
}