URL without Index

Marija Jemuovic
Member since: 2010
 

Hi, guys,

If I have a pager on the page, is there a possibility to ditch the Index in the URL by defining a custom route, ie have localhost:12345/Events/2 instead of localhost:12345/Events/Index/2

Thank you in advance,

Marija

 

#65637
Feb 04, 2013 14:52
Johan Björnfot
Member since: 2004
 

What you need to do is to replace the segment that handles {action}. By default {action} is handled by ParameterSegment which always will consume the current segment form the url. In your case you would like the segment handling action that it does not consume the segment but instead passes it on to next segment like {page} that handles paging.

So you need a different segment implementation that could look something like:

public class OptionalActionSegment : ParameterSegment
{
private 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 (IsRequestForEventPage(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;
}
else if (context.Defaults.ContainsKey(Name))
{
context.RouteData.Values[Name] = context.Defaults[Name];
return true;
}

return false;
}

private bool IsRequestForEventPage(SegmentContext context)
{
IContent content = _contentLoader.Get<IContent>(context.RoutedContentLink);
return content is EPiServer.Templates.AlloyTech.PageTypes.EventItemPage;
}
}

 

Then you can register a route with your segment as:

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

var segment = new OptionalActionSegment("action", ServiceLocator.Current.GetInstance<IContentLoader>());
var routingParameters = new MapContentRouteParameters()
{
SegmentMappings = new Dictionary<string, ISegment>(),
UrlSegmentRouter = new DefaultUrlSegmentRouter(ServiceLocator.Current.GetInstance<IContentLoader>(),
new LanguageSelectorFactory(), ContentReference.StartPage, ServiceLocator.Current.GetInstance<IRoutingSegmentLoader>())
};
routingParameters.SegmentMappings.Add("action", segment);

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

 

in your controller you can then get the paging value from RouteValues on Request context where it will be stored with key "page" (if that is the name of your pagining segment).

#65671
Feb 05, 2013 12:46
Marija Jemuovic
Member since: 2010
 

Thanks a lot for such a detailed answer! I will try this out, hopefully it will go smoooothly :)

 

// Edit: tried it, went smoothly :)

#65675
Edited, Feb 05, 2013 13:41
Marija Jemuovic
Member since: 2010
 

Hi, Johan, 

Is there any other place I could register routes?

ServiceLocator.Current.GetInstance<IContentLoader>() gives me StructureMap exception when I call it in Global.asax. (I am using StructureMap in the solution, too)

#73036
Jul 04, 2013 14:43
Marija Jemuovic
Member since: 2010
 

I have fixed it finally, simply by adding an if statement before using IContentLoader and IRoutingSegmentLoader.

The code is now:

protected override void RegisterRoutes(RouteCollection routes)
        {
            base.RegisterRoutes(routes);
                        
            IContentLoader contentLoader;
            ServiceLocator.Current.TryGetExistingInstance(out contentLoader);

            IRoutingSegmentLoader routingSegmentLoader;
            ServiceLocator.Current.TryGetExistingInstance(out routingSegmentLoader);

            if (contentLoader != null && routingSegmentLoader != null)
            {
                var segment = new OptionalActionSegment("action", contentLoader);
                var routingParameters = new MapContentRouteParameters()
                {
                    SegmentMappings = new Dictionary<string, ISegment>(),
                    UrlSegmentRouter = new DefaultUrlSegmentRouter(
                        contentLoader,
                        new LanguageSelectorFactory(),
                        ContentReference.StartPage,
                        routingSegmentLoader)
                };
                routingParameters.SegmentMappings.Add("action", segment);

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

    

#73467
Jul 23, 2013 14:31
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.