2

We're currently making a small CMS module for our application where existing routes and controllers are highly prioritize, while dynamically created pages through the CMS will only be loaded if the provided URL does not exists in the default route.

I already looked at this one: Dynamic Routes from database for ASP.NET MVC CMS but it prioritizes the dynamically created page before the routes.

This is our default route:

routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Store", action = "Index", id = UrlParameter.Optional }
        );

And aside from the default route, we have other routes that are using prefixes like this one:

routes.MapRoute(
            name: "Media",
            url: "m/{*url}",
            defaults: new { controller = "Content", action = "GetContent", contentlibrary = "Media" },
            constraints: new { url = @"(.*?)\.(png|jpg|pdf|mpeg|mp3|mp4)" }
        );

UPDATE 1: I created an IRouteConstraint for validating if the Controller exists for the default route. Here is my code:

public class ControllerValidatorConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        var tempRequestContext = httpContext.Request.RequestContext;
        IController controller = null;

        try
        {
            controller = ControllerBuilder.Current.GetControllerFactory().CreateController(httpContext.Request.RequestContext, values["controller"].ToString());
        }
        catch (Exception ex)
        {

        }

        return controller != null;
    }
}

then on routing:

routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Store", action = "Index", id = UrlParameter.Optional },
            constraints: new { url = new ControllerValidatorConstraint() }
        );

        routes.MapRoute(
            name: "Page",
            url: "{*url}",
            defaults: new { controller = "Content", action = "GetPage" },
            constraints: new { url = @"(.*?)(|.cshtml)" },
            namespaces: new[] { "AppCore.Controllers" }
        );

This already works as what I intend. The only remaining issue is the Match() method. The Match() method is currently creating an instance of the controller, I wrapped it with a Try-Catch block because it throws an error related to the provided path that does not exists as temporary solution but this is still wrong.

I'm almost there, I just have to find a proper way to check if the controller exists. Is reflection a bad choice? Any lighter way to check them? Thanks!

eSPiYa
  • 882
  • 1
  • 12
  • 29
  • The example you linked to has some problems. First of all, it uses a route constraint + catchall route instead of just extending `RouteBase`. Secondly, there is no caching which is highly recommended since routing runs on every request. See [Multiple levels in MVC custom routing](https://stackoverflow.com/a/31958586/181087) for a better approach. – NightOwl888 Jun 07 '17 at 11:47
  • @NightOwl888 thanks for the link. At my initial inspection, it looks like it prioritizes the custom/dynamic pages than the existing routes like the link I attached but will try and tweak it. – eSPiYa Jun 08 '17 at 01:36
  • I am not sure what you expect. [Specific route *must* be prioritized before the default route](https://stackoverflow.com/a/35674633/181087) in order for them to work right. – NightOwl888 Jun 08 '17 at 05:13
  • @NightOwl888 I just need some kind of route that will catch the "not found" error from the default route. This route will try to check the provided URL path if it does exists in the hard drive or the database then serve it to the user, otherwise, return the final 404 error message. – eSPiYa Jun 08 '17 at 07:10

0 Answers0