0

I have an Asp.Net MVC site with a MS SQL database. This site has an administration panel where, apart from other things, the administrator can change the menu of the site.

What we want to do is allow the owner of the site to change dynamically not only the menu names but also the page routes, so they can decide the url of any page in the site.

Imagine that we have different pages(views) like videos, news, photos...the default routes (url) for those view can be:

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

The admin has to be able to change dynamically those routes son when a user hit the news page it shows the URL they want, for example:

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

The idea is loading the site menu from DB, getting the name of the menu, the controller, the action and the route of the page. And from there we have to call a controller and action to load a view but we need to show in the URL the route the admin has set for that view.

Also it is possible that we have multiple actions(views) in the same controller. For example news and videos are in the same controller.

If we pass a parameter "customRoute" to the Route.Config it gives us an error because the name of that parameter is the same for those actions in the same controller.

How can we do this with the ASP.NET routing?

Thanks in advance.

John Mathison
  • 904
  • 1
  • 11
  • 36

1 Answers1

0

The code below shows how to add routes from a database to your route config (this only gets executed when the application pool starts)

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
}

Or you could override the BeginProcessRequest with something like this

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;
    }
}
Gelootn
  • 601
  • 6
  • 16