【问题标题】:Dynamically adding to RouteTable isnt working动态添加到路由表不起作用
【发布时间】:2012-01-31 15:55:34
【问题描述】:

我目前正在为应用程序编写新闻文章方面,并将新路由(用于新文章)添加到我的 RouteTable,这看起来很好,但路由无法访问?

我使用的代码如下:

var routes = RouteTable.Routes;
using (routes.GetWriteLock())
{
    var url = contentHelper.GetPageUrl(page);
    routes.MapRoute(page.Id.ToString(), url, new { controller = "Cms", action = "Index", id = url }, new[] { "Web.Controllers.CmsController" });
}

正如我之前所说,新的 Url 已添加到 RouteTable.Routes 但我无法访问该页面。重新启动后,它会被 Global.asax 中的 RegisterRoutes 拾取并正常工作。

您能对此有所了解的任何想法都会很棒,因为我想在不强制重启应用的情况下实现这一目标

编辑

这是我 global.asax 中的 RegisterRoutes

public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute("LogOff", "LogOff", new { controller = "Account", action = "LogOff" });

        routes.MapRoute(
                "News", // Route name
                "News/",// URL with parameters
                new { controller = "NewsPage", action = "Index" }, // Parameter defaults
                new[] { "Web.Controllers.NewsController" }
            );

        //register all content pages
        var urls = new ContentPageHelper().GetAllUrls();
        foreach (var url in urls)
        {
            routes.MapRoute(url.Key.ToString(), url.Value, new { controller = "Cms", action = "Index", id = url.Key }, new[] { "Web.Controllers.CmsController" });
        }

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}",// URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
        );
    }

【问题讨论】:

    标签: c# model-view-controller asp.net-mvc-routing


    【解决方案1】:

    问题是调用RouteTable.MapRoute 会将路由添加到表的末尾。您的默认路由通常是要添加到表中的最后一个路由,但由于您在构建路由表之后动态调用RouteTable.MapRoute,因此默认路由在到达您新添加的路由之前就被命中了。

    我对这个问题的解决方法如下。

        public static void AddContentRoute(this RouteCollection routes, Data.UrlMap map, bool needsLock = false)
        {
            var route = new Route(map.Url, new MvcRouteHandler());
            route.Defaults = new RouteValueDictionary(new
            {
                controller = "Content",
                action = "Display",
                id = map.Id,
                type = map.Type
            });
    
            if (needsLock)
            {
                using (routes.GetWriteLock())
                {
                    routes.Insert(0, route);
                }
            }
            else
            {
                routes.Insert(0, route);
            }
        }
    

    这基本上做了RouteTable.MapRoute 所做的事情,但是将路由插入到表的顶部而不是末尾。

    如果您有其他路线需要坐在桌子的顶部,您可能需要修改此解决方案。

    【讨论】:

    • 如何确定添加路由是否需要锁(当您将其作为参数传递时)?
    • 我写的函数基本上是 RouteTable.MapRoute 的一个副本(检查源代码并自己查看)。在线程情况下使用锁,在大多数情况下没有必要。
    【解决方案2】:

    为什么要即时创建路线?当应用程序自己重新启动应用程序时,这不会破坏目的吗?所有这些路由都需要重新创建才能工作

    为什么不创建一个只处理对您的 cms 的所有请求的路由?

    routes.MapRoute("CmsPage", "{page}", new { controller = "Cms", action = "Index"}, new [] { "Web.Controllers.CmsController" });
    

    如果您这样做是为了不与应用程序中的其他路由/控制器发生冲突,您总是可以在所有 cms 生成的页面前加上 pages。我正在为我现在正在创建的一个 CMS 网站执行此操作。

    routes.MapRoute("CmsPage", "pages/{page}", new { controller = "Cms", action = "Index"}, new [] { "Web.Controllers.CmsController" });
    

    您在控制器中的操作与此类似

    public ActionResult Index(string page) 
    {
        // logic to load page
        return View();
    }
    

    【讨论】:

    • 我已经在 global.asax 中执行此操作,但我需要新页面一制作完成,而无需重新启动应用程序
    • 如果路由是在 global.asax 中创建的,它们应该在创建后就已经可用。调用 Action 时如何检索页面?您是否将页面存储在数据库中?
    • 另外,将“Pages/”添加到 url 是一种丑陋和 hacky 的做法,从 SEO 的角度来看,它不会做任何积极的事情。查看 global.asax 的编辑
    猜你喜欢
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 2023-04-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多