来自数据库

时间:2016-02-17 08:52:11

标签: asp.net-mvc routing custom-routes

我有一个带有MS SQL数据库的Asp.Net MVC站点。该站点有一个管理面板,管理员可以在其中更改网站的菜单。

我们想要做的是让网站所有者不仅动态更改菜单名称而且还动态更改页面路由,以便他们可以决定网站中任何页面的网址。

想象一下,我们有不同的页面(视图),如视频,新闻,照片......这些视图的默认路径(网址)可以是:

www.site.com/videos 
www.site.com/news
www.site.com/photos

管理员必须能够在用户点击新闻页面时动态更改这些路线,并显示他们想要的URL,例如:

www.site.com/my-videos 
www.site.com/latest-news
www.site.com/photo-gallery

这个想法是从DB加载站点菜单,获取菜单名称,控制器,操作和页面路径。从那里我们必须调用控制器和动作来加载视图,但我们需要在URL中显示管理员为该视图设置的路由。

我们也可能在同一个控制器中有多个动作(视图)。例如,新闻和视频在同一个控制器中。

如果我们将参数“customRoute”传递给Route.Config,它会给我们一个错误,因为该参数的名称对于同一控制器中的那些操作是相同的。

我们如何使用ASP.NET路由执行此操作?

提前致谢。

1 个答案:

答案 0 :(得分:0)

下面的代码显示了如何将数据库中的路由添加到路由配置中(这仅在应用程序池启动时执行)

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

        var redirects = LegacyRedirectRepo.GetRedirects();
        foreach (var legacyRedirect in redirects)
        {
            if (!legacyRedirect.Source.Contains("?"))
            {
                routes.Add(new LegacyRoute(legacyRedirect.Source, legacyRedirect.Destination));
            }
        }

        routes.IgnoreRoute("{folder}/{*pathInfo}", new { folder = "upload" });
        routes.IgnoreRoute("{folder}/{*pathInfo}", new { folder = "content" });

        routes.IgnoreRoute(
            "{*staticfile}",
            new { staticfile = @".*\.(jpg|gif|jpeg|png|js|css|htm|html)$" }
        );
 //static routing rules
}

或者你可以用这样的东西覆盖BeginProcessRequest

public class LegacyHandler : MvcHandler
{
    /// <summary>
    /// Initializes a new instance of the <see cref="LegacyHandler"/> class.
    /// </summary>
    /// <param name="requestContext">The request context.</param>
    public LegacyHandler(RequestContext requestContext)
        : base(requestContext)
    {
    }

    /// <summary>
    /// Called by ASP.NET to begin asynchronous request processing.
    /// </summary>
    /// <param name="httpContext">The HTTP context.</param>
    /// <param name="callback">The asynchronous callback method.</param>
    /// <param name="state">The state of the asynchronous object.</param>
    /// <returns>The status of the asynchronous call.</returns>
    protected override System.IAsyncResult BeginProcessRequest(HttpContext httpContext, System.AsyncCallback callback, object state)
    {
        var legacyRoute = RequestContext.RouteData.Route as LegacyRoute;

        httpContext.Response.Status = "301 Moved Permanently";
        var urlBase = RequestContext.HttpContext.Request.Url.GetLeftPart(System.UriPartial.Authority);

        var url = string.Format("{0}/{1}", urlBase, legacyRoute.Target);
        if (!string.IsNullOrWhiteSpace(RequestContext.HttpContext.Request.Url.Query))
        {
            var pathAndQuery = RequestContext.HttpContext.Request.Url.PathAndQuery;
            pathAndQuery = pathAndQuery.Substring(1, pathAndQuery.Length - 1);
            var redirect = LegacyRedirectRepo.GetRedirect(pathAndQuery);

            url = string.Format(@"{0}/{1}", urlBase, redirect.Destination);

        }

        httpContext.Response.RedirectPermanent(url);
        httpContext.Response.End();

        return null;
    }
}