Try our conversational search powered by Generative AI!

Custom Routing eliminating simple address for frontpage

Vote:
 

Hey EPiServer CMS.

I have for a while tried to setup a custom route in EPiServer that will include a customer Id, obtained through the login claims, in the start of the URL. I could not get the MapContentRoute to work in any shapre or form, so I ended up using MapPageRootRoute instead.

The Route:

routes.MapPageRootRoute(
                "selfservice",
                "SE{company}/{node}/{partial}/{action}",
                new { action = "index" },
                new { company = @"\d{8}", node = new ContentTypeConstraint() });

base.RegisterRoutes(routes);

The Problem:
This route worked just fine, when the SelfServiceBasePages were positioned as children of the Root Page, but after I moved them to under the StartPage instead, then the simple address of the StartPage no longer seems to be valid.

E.g. with this structure:
CMS Structure

The following URL will not work and results in 404-Not Found: http://localhost:52275/SE14814833/selvbetjening/ 
While the URL with the full path will: http://localhost:52275/SE14814833/dansk-forside/selvbetjening/ 

This is only the case for the pages affected by the custom route, since the other pages can be routed to using the simple address of the startpage or not.

E.g. both of the following URLs are valid for a non-SelfServiceBasePage while being positioned as a child of the startpage:
http://localhost:52275/sporgsmal-og-svar/
http://localhost:52275/dansk-forside/sporgsmal-og-svar/ 

My Question:

My question is why the simple address of the StartPage doesn't work for my route, and how I can go about fixing that. Normally I wouldn't position these pages as children of the StartPage, but that is a requirement for this specific project. Do I need to change the Route, or what needs to change? 

Let me know if any additional information is needed, or if the question is unclear in any way.

#193478
Edited, May 30, 2018 12:46
Vote:
 

When you set up a content route it will be set up with a starting point of the route. By default it will start routing from RootPage. It is possible to define another start point as in example below where start page is set as start point for the route:

var urlSegmentRouter = ServiceLocator.Current.GetInstance<IUrlSegmentRouter>();
urlSegmentRouter.RootResolver = sd => sd.StartPage;
var parameters = new MapContentRouteParameters
{
    UrlSegmentRouter = urlSegmentRouter,
    Direction = SupportedDirection.Incoming,
    Constraints = new { company = @"\d{8}", node = new ContentTypeConstraint<SelfServiceBasePage>() }
};

routes.MapContentRoute(
    "selfservice",
    "SE{company}/{node}/{partial}/{action}",
    new { action = "index" },
    parameters);
#193488
May 30, 2018 13:49
Vote:
 

Hey Johan, thanks for the quick answer!

I experimented a bit with your solution, and it seems to work for now, but I still need to register both routes (MapPageRootRoute and MapContentRoute), otherwise EPiServer's UrlResolver doesn't translate {company} as part of the URL, but rather just as a standard parameter (/?company=...), which is incorrect. Is the expected solution to register the route for both the root and the startpage?

Current solution:

routes.MapPageRootRoute(
    "selfserviceRoot",
    "SE{company}/{node}/{partial}/{action}",
    new { action = "index" },
    new { company = @"\d{8}", node = new ContentTypeConstraint<SelfServiceBasePage>() });

var urlSegmentRouter = ServiceLocator.Current.GetInstance<IUrlSegmentRouter>();
urlSegmentRouter.RootResolver = sd => sd.StartPage;
var parameters = new MapContentRouteParameters
                 {
                     UrlSegmentRouter = urlSegmentRouter,
                     Direction = SupportedDirection.Incoming,
                     Constraints = new { company = @"\d{8}", node = new ContentTypeConstraint<SelfServiceBasePage>() }
                 };

routes.MapContentRoute(
    "selfservice",
    "SE{company}/{node}/{partial}/{action}",
    new { action = "index" },
    parameters);

base.RegisterRoutes(routes);



As a side note, I currently carry the RoutedValue for {company} around by extending the Urlhelper:

//public const string SE_NUMBER_KEY = "company";
public static string PageUrl(this UrlHelper urlHelper, PageReference pageLink, object routeValues)
{
    var routeValueDictionary = new RouteValueDictionary(routeValues);

    var se = m_httpContextService.GetFullSeNumber();

    if (string.IsNullOrWhiteSpace(se) || !(pageLink.GetPage() is SelfServiceBasePage))
        return urlHelper.ContentUrl(pageLink);

    routeValueDictionary.Add(Constants.Routing.SE_NUMBER_KEY, se);

    var language = routeValueDictionary[RoutingConstants.LanguageKey] as string
                   ?? ContentLanguage.PreferredCulture.Name;

    return PageUrl(urlHelper, pageLink, language, routeValueDictionary);
}

//m_urlResolver = ServiceLocator.Current.GetInstance<UrlResolver>();
public static string PageUrl(this UrlHelper urlHelper, PageReference page, string lang, RouteValueDictionary routeValues)
{
    var virtualPath = new VirtualPathArguments { RouteValues = routeValues };
    return m_urlResolver.GetUrl(page, lang, virtualPath);
}




 

#193503
May 30, 2018 15:10
Vote:
 

Ok, I did not understand that you also wanted to generate urls in that format, I though you just wanted to be able to handle incoming request. in that cas just change the SupportedDirection in the registration to Both, as:

var urlSegmentRouter = ServiceLocator.Current.GetInstance<IUrlSegmentRouter>();
urlSegmentRouter.RootResolver = sd => sd.StartPage;
var parameters = new MapContentRouteParameters
{
    UrlSegmentRouter = urlSegmentRouter,
    Direction = SupportedDirection.Both,
    Constraints = new { company = @"\d{8}", node = new ContentTypeConstraint<SelfServiceBasePage>() }
};

routes.MapContentRoute(
    "selfservice",
    "SE{company}/{node}/{partial}/{action}",
    new { action = "index" },
    parameters);
#193504
May 30, 2018 15:13
Vote:
 

Ok, thanks once again. Out of curiosity, If you have several sites, will this route be registered for all startpages?

#193516
May 30, 2018 17:02
Vote:
 

Yes it works for all sites. The root for the router is determined by a delegate that's get called for each request meaning StartPage is resolved from the host of the request. 

#193535
May 30, 2018 19:26
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.