EPiServer 7 custom routing problem

 

Hi I created a custom episerver route in Global.asax

 

            RouteTable.Routes.MapContentRoute("UserProfileRoute", "user/{uid}/{languageBranch}/{node}/{partial}/{action}", new
                {
                    uid = "",
                    languageBranch = "en",
                    node = "2424",
                    partial = UrlParameter.Optional,
                    action = UrlParameter.Optional
                 });

 

the idea of this route is when i open the following link "www.mywebsite.com/user/123123" it should open the Userprofile episerver page with id "2424"

but with the above mention url it takes me to startpage instead which has a id 3.

what am i doing wrong in this scenrio??

the second problem i am having is when i change the language in the url it never change the langiage of the page e.g "www.mywebsite.com/user/123123/fr" it still stay english

#65422 Jan 29, 2013 16:31
  • Corbin Camp
    Member since: 2012
     

    Same issue here.

    #65426 Jan 29, 2013 17:46
  • Johan Björnfot
    Member since: 2004
     

    When you use MapContentRoute it will treat the parts of the url that are inside {} as segment (something that is implementing EPiServer.Web.Routing.Segments.ISegment). There are some predefined keys that are handled by default, e.g. {node} that is a content instance, {language} that handles language segment. {uid} however will not be recognized and thereby it will be handled as a ParameterSegment. 

    So in your case you should use {language} instead of {languageBranch).

    A parameter segment works in the way that during incoming routing the value of the segment will be placed in RequestContext.RouteData.Values with the parameter name as key, in your case "uid". During creation of outgoing links the parameter will output value if the key (e.g "uid") is part of RouteValues dictionary.

    You can also have your own custom ISegment implementation (instead of ParameterSegment) that handles your segment, Then you need to use the overload of MapContentRoute that takes a ContentParameters as parameter and in property SegmentMappings add your custom segment with your url pattern as key as e.g. contentParameters.SegmentMappings.Add("uid", customSegmentInstance)

    #65430 Jan 29, 2013 19:15
  •  

    So what would be the best way to direct the url to a specific EPiServer page? Writing a custom iSegment implementation for the {node} segment?

    #65468 Jan 30, 2013 14:24
  • Johan Björnfot
    Member since: 2004
     

    I do not think any of the built in segements will do what you want so you need to create your own segment like UserIdSegment (it should be fairly simple, there is a baseclass SegmentBase that you can use). You could e.g. pass in the contentreference of the page in the constructor to your segment. And in RouteDataMatch check if the incoming segment match the a user id and if so set RoutedContentLink. Something like:

    public class UserIdSegment : SegmentBase
    {
    private ContentReference _linkToProfilePage;
    public UserIdSegment(string name, ContentReference contentLink) : base(name)
    {
    _linkToProfilePage = contentLink;
    }

    public override string GetVirtualPathSegment(System.Web.Routing.RequestContext requestContext, System.Web.Routing.RouteValueDictionary values)
    {
    return null;
    }

    public override bool RouteDataMatch(SegmentContext context)
    {
    var segmentPair = context.GetNextValue(context.RemainingPath);
    if (IsValidUserId(segmentPair.Next))
    {
    context.RemainingPath = segmentPair.Remaining;
    context.RoutedContentLink = _linkToProfilePage;
    return true;
    }

    return false;
    }

    private bool IsValidUserId(string p)
    {
    //Here should logic for user id go
    }
    }

    The you can register your route something like:

    var segment = new UserIdSegment("uid", new ContentReference(2424));
    var routingParameters = new MapContentRouteParameters()
    {
    SegmentMappings = new Dictionary<string, ISegment>()
    };
    routingParameters.SegmentMappings.Add("uid", segment);

    routes.MapContentRoute(
    name: "userprofiles",
    url: "user/{uid}/{language}/{action}",
    defaults: new { action = "index" },
    parameters: routingParameters);

     

    #65487 Jan 30, 2013 16:47
  •  

    Works like a charm! Thank you!

    #65494 Jan 30, 2013 18:19
  •  

    In case someone reads this in the future I wrote an article on the topic of custom routing featuring, amongst other things a custom segment inspired by Johan's above.

    #69887 Apr 09, 2013 10:18
  • Chris Sharp
    Member since: 2011
     

    Maybe I'm missing something here, but I've set up a custom route using a custom segment, and the route parameter I'm really concerned about always is null in my controller. For example, if I use the example above, the 'uid' parameter will be null in the page controller for the profile page. I can see it fine if I pass it as a querystring, but that defeats the purpose. What am I missing?

    #72000 Jun 05, 2013 0:45
  • Viktor Gars
    Member since: 2005
     

    Chris, I got the same problem but changed the code for RouteDataMatch to this,

    ----------

    public override bool RouteDataMatch(SegmentContext context)
    {
    var segmentPair = context.GetNextValue(context.RemainingPath);
    var userId = segmentPair.Next;
    if (IsValidUserId(userId))
    {
    context.RemainingPath = segmentPair.Remaining;
    context.RoutedContentLink = _linkToProfilePage;
    context.RouteData.Values.Add("uid", userId);
    return true;
    }
    return false;
    }

    ----------

    e.g. adding the value to the RouteData object. Don't know if this is the correct way to do it but it works :)

     

    /Viktor

    #73538 Jul 26, 2013 11:14