0

Current Route


// Create the front-end route.
Route defaultRoute = routes.MapRoute(
    "CMS_Default",
    "CMS/RenderMvc/{action}/{id}",
    new { controller = "RenderMvc", action = "Index", id = UrlParameter.Optional }
);
defaultRoute.RouteHandler = new RenderRouteHandler(cmsContext, ControllerBuilder.Current.GetControllerFactory());

Desired Functionality


I would like any URL to be picked up e.g. /home, /about-us, /contact-us and go to the current route above: /cms/rendermvc/home, /cms/rendermvc/about-us, /cms/rendermvc/contact-us as this is were it will take the URL segment or in the routes case the {action} and do the logic for getting the content from the database. I would like to do this without the use of a default {*url} route.

Current Ideas


  • I'm not very familiar with it but could ActionFilters be used in this instance?
  • I believe this could be achieved by a default module?

Desired Functionality Examples


Umbraco has the identical routing structure I am after, just with a lot more complexity.

Halden Collier
  • 845
  • 7
  • 18
  • I really don't understand what you are saying here? – DavidG Dec 08 '20 at 17:28
  • @DavidG when I go to the `/home` url I want this default route action to fire. It does not do this unless I go to `/cms/rendermvc/index`. – Halden Collier Dec 08 '20 at 17:29
  • I want my routing to be very similar if not the same (with less complexity) to Umbraco. I have been crawling through their source code but cannot figure out how they are able to redirect `/home` to `/umbraco/rendermvc/index` and then back to `/home` unless I'm going about it all wrong? – Halden Collier Dec 08 '20 at 17:32
  • You have two options. First, you can write other routes eg. Home, and set the controller and action to your default action. I mean you have to write every possible routing you want to address to the default route. 2nd option is using rewrite url – Mahdi Farhani Dec 08 '20 at 23:20
  • @Mahdi the default route: `/cms/rendermvc/{url}` will handle every front-end page e.g. `Home`, `About`, `Contact`. The content and logic for these pages are handled in the `RenderMvcController`. I'm not entirely sure how I would rewrite `/home` to go to the controller action and then back to the provided url. As I do not want a route like this: `{url}` – Halden Collier Dec 09 '20 at 09:38
  • What I would like is for any url to be picked up and then go to the `RenderMvcController` route without the use of a `{url}` route. – Halden Collier Dec 09 '20 at 09:39
  • I believe the question is a bit more complex that it seems. – Halden Collier Dec 09 '20 at 09:46
  • vice versa I think is easier than you think. – Mahdi Farhani Dec 09 '20 at 09:49

2 Answers2

1

I figured it out, as my question suggests I needed a IHttpModule. With help from this answer, I have now been able to get my desired routing!

For those of you that are curious, here is my code.

CMSModule


using System;
using System.IO;
using System.Web;

public class CMSModule : IHttpModule
{
    public void Init(HttpApplication app)
    {
        app.BeginRequest += (sender, e) =>
        {
            var httpContext = ((HttpApplication) sender).Context;
            BeginRequest(new HttpContextWrapper(httpContext));
        };
    }

    private void BeginRequest(HttpContextBase httpContext)
    {
        Uri url = httpContext.Request.Url;
        string requestExtension = Path.GetExtension(url.LocalPath);
        if (!string.IsNullOrWhiteSpace(requestExtension)) return;

        httpContext.RewritePath("/cms/rendermvc" + httpContext.Request.Path);
    }

    public void Dispose()
    { }
}

Web.config


<configuration>
  <system.webServer>
    <modules>
      <add name="CMSModule" type="CMS.Web.CMSModule,CMS.Web"/>
    </modules>
  </system.webServer>
</configuration>

WARNING


This is very basic code and I would not suggest copying it as I'm sure there are lots of edge cases that I'm not taking into account but for the moment, it works.

Halden Collier
  • 845
  • 7
  • 18
0

Try to add another route to your routeTable. for example :

Route HomeRoute = routes.MapRoute(
    "CMS_Home",
    "CMS/Home",
    new { controller = "RenderMvc", action = "HomeAction"}
);

Route AboutRoute = routes.MapRoute(
    "CMS_About",
    "CMS/About",
    new { controller = "RenderMvc", action = "About"}
);

So all these routes will address to RenderMvcController and different action.

Mahdi Farhani
  • 964
  • 1
  • 9
  • 22
  • Hi Mahdi, thank you for the suggestion. However I'm not sure you understand the question. I would like to do this **WITHOUT** the use of more routes. As the URL should be sent over to the default one. Please view my updated answer, which hopefully explains the question a bit better. – Halden Collier Dec 09 '20 at 09:54
  • This routing is not used for the CMS, that will be routed through AngularJS. This route is purely for getting the provided URL passing it to the custom `RouteHandler` which will then get content e.g. `Name`, `Id`, `Alias`, `Template` from the database using the URL that was provided and rendering the default view with this information. – Halden Collier Dec 09 '20 at 09:58
  • I don't get it so. what's wrong with this routing : "CMS/RenderMvc/{url}", new { controller = "RenderMvc", action = "Index", url = UrlParameter.Optional } and you can get url parameter in index action. – Mahdi Farhani Dec 09 '20 at 10:04
  • For one, this route would only be fired when you go to this url: `cms/rendermvc/home`. I would like it to happen from any given url. I have updated my question with an example of software with an almost identical routing system. – Halden Collier Dec 09 '20 at 10:06
  • It will work for all routes, because {url} is an optional parameter – Mahdi Farhani Dec 09 '20 at 10:09
  • check this question maybe it's helpful for your https://stackoverflow.com/questions/16026441/dynamic-routes-from-database-for-asp-net-mvc-cms – Mahdi Farhani Dec 09 '20 at 10:12
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/225702/discussion-between-halden-collier-and-mahdi-farhani). – Halden Collier Dec 09 '20 at 10:14
  • 1
    I was able to find my own answer, check it out if you're curious. – Halden Collier Dec 09 '20 at 11:33
  • Mark your post as answer – Mahdi Farhani Dec 09 '20 at 11:41
  • I can't until tomorrow – Halden Collier Dec 09 '20 at 11:46