Registering a route with an optional action segment in EPiServer 7.5 and on

PLACE FOR BLOG

Registering a route with an optional action segment in EPiServer 7.5 and on

Registering a route with an optional action segment in EPiServer 7.5 and on

marija

The article explains how to register a route in EPiServer 7.5 that enables you to have /news/2 instead of news?page=2 or news/Index/2.

The motivation and explanation of how OptionalActionSegment is created is already present in the previous article.

However, since API was slightly changed with EPi 7.5, I've got quite some questions about how the code should look like from this version on.

OptionalActionSegment stays the same, check it out here:

using Project.Web.Models.Definitions;
using EPiServer;
using EPiServer.Core;
using EPiServer.Web.Routing.Segments;

namespace Project.Web.Core
{
    public class OptionalActionSegment : ParameterSegment
    {
        private readonly IContentLoader _contentLoader;

        public OptionalActionSegment(string name, IContentLoader contentLoader) : base(name)
        {
            _contentLoader = contentLoader;
        }

        public override bool RouteDataMatch(SegmentContext context)
        {
            var segmentPair = context.GetNextValue(context.RemainingPath);
            if (!string.IsNullOrEmpty(segmentPair.Next))
            {
                if (ShouldAddDefaultAction(context))
                {
                    //do not consume segment just add default action
                    context.RouteData.Values[Name] = context.Defaults[Name];
                }
                else
                {
                    context.RouteData.Values[Name] = segmentPair.Next;
                    context.RemainingPath = segmentPair.Remaining;
                }

                return true;
            }
            
            if (context.Defaults.ContainsKey(Name))
            {
                context.RouteData.Values[Name] = context.Defaults[Name];
                return true;
            }

            return false;
        }

        private bool ShouldAddDefaultAction(SegmentContext context)
        {
            var content = _contentLoader.Get(context.RoutedContentLink);
            // perhaps add more page types in future, for search, etc
            return content is IListing;
        }
    }
}

The part that is custom to your implementation is ShouldAddDefaultAction - what it does is basically restricts for which page types you want to have an optional action segment. It might be that you want to have a URL with "Index" instead.

New Global.asax:

using System.Collections.Generic;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;
using EPiServer;
using EPiServer.ServiceLocation;
using EPiServer.Web.Routing;
using EPiServer.Web.Routing.Segments;
using PROJECT.Web.Business; // this is where OptionalActionSegment.cs is placed

namespace PROJECT.Web
{
    public class Global : EPiServer.Global
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();            
        }

        protected override void RegisterRoutes(RouteCollection routes)
        {
            base.RegisterRoutes(routes);

            IContentLoader contentLoader;
            ServiceLocator.Current.TryGetExistingInstance(out contentLoader);
            
            IUrlSegmentRouter segmentRouter;
            ServiceLocator.Current.TryGetExistingInstance(out segmentRouter);

            if (contentLoader != null && segmentRouter != null)
            {
                segmentRouter.RootResolver = sd => sd.StartPage;
                var parameters = new MapContentRouteParameters
                {
                    UrlSegmentRouter = segmentRouter,
                    BasePathResolver = EPiServer.Web.Routing.RouteCollectionExtensions.ResolveBasePath,
                    Direction = SupportedDirection.Both
                };
                var segment = new OptionalActionSegment("action", contentLoader);
                var segmentMappings = new Dictionary { { "action", segment } };
                parameters.SegmentMappings = segmentMappings;

                routes.MapContentRoute(
                    name: "optionalaction",
                    url: "{language}/{node}/{partial}/{action}/{page}",
                    defaults: new { action = "index" },
                    parameters: parameters);
            }
        }
    }
}

Happy updating!

Comments

no avatar

Raja Chandran (not verified) SAYS:

Nov 22, 2017 at 11.29 am

HI,

Is this work for multiple parameters? like {language}/{node}/{partial}/{action}/{cateogory}/{id}

Regards,
Raja

LEAVE A COMMENT