3

I am unable to figure out the correct route configuration for this scenario.

The tree structure is as:

Home
|_Articles
  |_Topic1
    |_Blogs
      |_blog1
      |_blog2
  |_Topic2

Each topic page will show the list of all its blogs, with pagination.
So, example.com/en/Articles/Topic1 is the topic page which shows list of all its related blogs.

Now, I want to have a custom URL like this - example.com/en/Articles/Topic1/1 to indicate that it is page1 and so on.

Route setting:

routes.MapRoute(
  name: "TopicsListing",
  url: "{scItemPath}/{pg}",
  defaults: new { scItemPath = "/{*pathInfo}", controller = "Topics", action = "TopicsListing", pg = UrlParameter.Optional },                
  constraints: new { pg = @"^[0-9]+$" }    
);

There was a similar route setting configured, but it used a class in the constraints. I just followed it to create mine.

This is a multi-site instance and I'm aware url defined could match with any other pattern, but not sure what else to configure here.

We aren't using any wild card modules. Also, it is not an option for us to have any new items/folders with "*".

When I browse example.com/en/Articles/Topic1/1, it doesn't hit the controller method and redirects to the default page not found.

UPDATE:

I would like to implement the solution mentioned here by zzzzBov, but have a few questions.

My new structure will be like this. Is it correct?

Home  
|_Articles  
  |_Topic1  
    |_*  
    |_Blogs  
      |_blog1  
      |_blog2  
  |_Topic2  
  1. Of what template will be the * item.
  2. Should it have a layout. I would like to assign just a controller rendering, but how to read the * value
  3. Any changes reqd in the Routeconfig in this case

All I want to do is pass a query string parameter in the URL as

example.com/en/articles/topic1/1

instead of

example.com/en/articles/topic1?pg=1

The existing controller method I have is

public ActionResult TopicsListing(string pg)
{

}
5
  • What's the reasoning behind dismissing the wildcard solution? – Mark Cassidy Jul 22 '17 at 9:05
  • @MarkCassidy Does it require creating new folders. If that's it, we are not to do so. Also, I see another similar routing done here in my code with no such wild card...so wanted to to keep it simple and do it the same way. – Qwerty Jul 22 '17 at 9:39
  • Yet you are keeping it complicated, with a non-sensical constraint :P Look; your pages need to be served by SitecoreController - you know... so Sitecore can do its thing. Even if you did succeed to make the above routing work, I assume your TopicsController is just one component of many on the target page. – Mark Cassidy Jul 22 '17 at 11:30
  • @MarkCassidy I have updated my question. Please have a look. – Qwerty Jul 22 '17 at 11:58
  • 1
    Yes. You want to do wildcards, but you don't want to do wildcards :P I think you need to take this to Slack, have a discussion about your options. – Mark Cassidy Jul 22 '17 at 11:59
2

I have implemented something similar to this using the wildcard solution. I had a begin request pipeline that fired when an item of a specific type was being hit (the type that my wildcard was). The item had a droplink field and template type field. The droplink pointed to a folder of pages that was in a global location so many sites could reference the same pages and the content for those sites could be edited by one content editing team. In your case you can probably skip these two fields knowing that it will redirect to the parent item.

I patched the pipeline processor right after the item resolver. What it did was save the current item (wildcard item) in Sitecore.Context.Items and then set Sitecore.Context.Item to the new item which in your case would be the parent item. Here's some sample code. Please note that it was written from memory and untested:

public class PointerResolver : HttpRequestProcessor
{
   public override void Process(HttpRequestArgs args)
   {
      //Inherits is a custom extension method to check 
      //if an item inherits from a template. If using code generation
      //you should leverage that for this check
      if(Sitecore.Context.Item == null 
         || !Sitecore.Context.Item.Inherits(Constants.MyWildcardTemplateId))
         return;

      //You may want to do some validation against the value
      //the user is using here (ex: validate it is a number)

      //The string for MyConstants.OriginalItemKey was stored in a 
      //class holding our constants
      Sitecore.Context.Items[MyConstants.OriginalItemKey] = Sitecore.Context.Item;

      //You might not want to blindly redirect to the parent
      Sitecore.Context.Item = Sitecore.Context.Item.Parent;
   }
}

Patch:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <httpRequestBegin>
        <processor 
patch:after="processor[@type='Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel']" type="My.Namespace.PointerResolver, MyDll">
        </processor>
      </httpRequestBegin>
    </pipelines>
  </sitecore>
</configuration>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.