Five New Optimizely Certifications are Here! Validate your expertise and advance your career with our latest certification exams. Click here to find out more

Redirect all URLs so they end with /

Ayo
Ayo
Vote:
 

Is there a way to configure episerver so that all my URLs end with slash.

So for example if a user navigates to www.mywebsite.com/en/home they are redirected to www.mywebsite.com/en/home/

Thanks in advance.

Ayo

#189373
Mar 16, 2018 14:58
Vote:
 

This can be done with URL Rewrite

<rule name="Add trailing slash" stopProcessing="true">
  <match url="(.*[^/])$" />
  <conditions>
    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
  </conditions>
  <action type="Redirect" redirectType="Permanent" url="{R:1}/" />
</rule>
#189376
Mar 16, 2018 15:33
Ayo
Vote:
 

I did it by adding this to my global asax.cs file:

protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.Request.Url.AbsolutePath != "/" && !HttpContext.Current.Request.Url.AbsolutePath.EndsWith("/"))
{
string redirect = HttpContext.Current.Request.Url.AbsolutePath;
redirect = redirect + "/";
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", redirect);
Response.End();
}


UPDATE: Doing it via the webconfig is better so we don't redirect .css URLs or .jpg URLs.

#189377
Edited, Mar 16, 2018 15:51
Ayo
Vote:
 

thanks for your reply Quan Mai

Used your method and it works great on the front end, but the issue is it breaks the episerver back end, how can I exclude all URLs assosiated with the back office? 

#189387
Mar 16, 2018 18:35
Vote:
 

You should be able to do that by adding this rule before the previous rule, assuming /episerver is your admin path

<rule name="block" stopProcessing="true">
    <match url="^/episerver$" ignoreCase="true" />
<action type="None" />
</rule>

#189388
Mar 16, 2018 19:04
Ayo
Vote:
 

I did try that but its still breaking the back office.... I posted a simlar question on stack overflow... I'll copy and paste it......


I want to create a URL rewite rule that adds a / on URLs that don't have one so for example:

www.domain.com/news/latest will get redirected to www.domain.com/news/latest/

The rule below does exactly that, but the problem I am having is two fold:

  1. This rewrite rule is getting applied to things like image files. So For example domain.com/globalassets/icons/image.svg gets changed to domain.com/globalassets/icons/image.svg/ causing a 404 its not happening with CSS files which is strange, maybe because I am adding them using the RegisterBundles method in MVC?

  2. This is a ASP.net MVC based website using a CMS (episerver) so I want to ignore any redirects in the Admin area so I added a second rule, but again its doing this to the CSS and images breaking the admin area.

This is what I have got so far, can anyone help me get this rule working correctly?


I just want this to work for the URL's to pages only and not effect the other supporting files like images and css, js files.

#189561
Mar 20, 2018 16:23
Vote:
 

What do your entire UrlRewrite rules look like? 

#189563
Mar 20, 2018 16:24
Ayo
Vote:
 

At the moment it looks like this....

<rewrite>
<rules>
<rule name="Exclude Slash Episerver " stopProcessing="true">
<match url="^episerver/" />
<action type="None" />
</rule>

<rule name="Add trailing slash" stopProcessing="true">
<match url="(.*[^/])$" />
<conditions>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="{R:1}/" />
</rule>
</rules>

</rewrite>



[Pasting files is not allowed][Pasting files is not allowed][Pasting files is not allowed]

#189565
Edited, Mar 20, 2018 16:46
Vote:
 

I dont' think this is correct, did you try with ^/episerver$ instead?

<match url="^episervers/" />
#189566
Mar 20, 2018 16:49
Ayo
Vote:
 

Yeah I did try that first (going to try it again now) but it didn't work... is $ a wild card? so it catches anything with  /episerver/matchesAnyThingAfterTheSlash  ?

#189567
Mar 20, 2018 16:52
Vote:
 

Hmm. $ is the end of the regex. This works for me on Quicksilver

<rule name="add trailing slash" stopProcessing="true">
<match url="(.*[^/])$" ignoreCase="true"/>
<conditions>
<add input="{URL}" pattern="^/(Login|episerver|util)" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="{R:1}/" />
</rule>

So it's a bit different way, but same purpose. Login is optional, while episerver|util is required

#189572
Mar 20, 2018 17:34
Vote:
 

I think the addition of the "util" part of the pattern is the key piece there Quan :)

#189573
Mar 20, 2018 18:10
Vote:
 

For future visitors, I wrote a blog post explaining the "magic" https://vimvq1987.com/adding-backslash-ending-to-your-urls-by-urlrewrite/ 

#189598
Mar 21, 2018 9:55
Ayo
Vote:
 

That works! - Thank you.

#189604
Mar 21, 2018 10:44
Ayo
Vote:
 

One more thing.... I just put this on to my staging server and we have a SSL certificate, now I am getting errors about mixed content, becuase some JS and CSS is now coming over http.... if I remove the rule it goes away....

Is there something I need to do to account for the fact I am using a SSL certificate. 

#189608
Mar 21, 2018 12:44
Vote:
 

There is a singelton instance of EPiServer.Web.Routing.RoutingOptions registered in IOC container. You can set the property UseTrailingSlash on the options class to control if you want the generated URL:s to have an trailing slash or not.

#189708
Mar 23, 2018 8:49
Ayo
Vote:
 

Hi Johan, 

This looks like exactly what I need, I had no idea episerver had something like this built in out of the box.

BUT.... I can't get it to work. This is what I have got...I have added this to my app start method, but I am not getting the / at the end of the URLs, do I need an IIS redirect as well?

I Put a break point in this method and I can see that routingOptions.UseTrailingSlash is already set to true, but my Urls are a not being redirected to have the / on the end... 

protected void Application_Start()
{
      AreaRegistration.RegisterAllAreas();
      BundleConfig.RegisterBundles(BundleTable.Bundles);
      AutoMapperConfig.InitializeMappings();

      var routingOptions = 
      ServiceLocator.Current.GetInstance<RoutingOptions>();
      routingOptions.UseTrailingSlash = true;
}

any ideas.... any one?

#189722
Mar 23, 2018 11:13
Vote:
 

I was probably a bit unclear, setting UseTrailingSlash will not do any redirection it will only assure that generated urls contain a trailing slash (then hopefully there will not be that common there will be request wwithout a trailing slash)

#189723
Mar 23, 2018 11:16
Vote:
 

Also the recommended way to set options is to use Configure method in a IConfigurableModule like:

  public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.Configure<RoutingOptions>(o => o.UseTrailingSlash = true);
        }
#189724
Mar 23, 2018 11:27
Ayo
Vote:
 

OK, so the only way to do it so there is a redirection is by a URL re-write?

The issue I am having is with SSL...

When I use the rule below, it works on my Local Machine....but when I put it on the staging server I get this error,

Mixed Content: The page at 'https://www.bit.truphone.com/uk/iot-solutions/' was loaded over HTTPS, but requested an insecure stylesheet

and the CSS gets blocked.

<rules>
<rule name="add trailing slash" stopProcessing="true">
<match url="(.*[^/])$" ignoreCase="true"/> 
<conditions>
<add input="{URL}" pattern="^/(Login|episerver|util|App_Themes)" negate="true"/>
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Redirect" redirectType="Permanent" url="{R:1}/" />
</rule> 



#189729
Mar 23, 2018 11:43
Vote:
 

If you prefer then you can do the redirection in code instead of in config, like below that attaches an eventhandler to IContentRouteEvents in a IInitializableModule:

   public void Initialize(InitializationEngine context)
        {
            context.Locate.Advanced.GetInstance<IContentRouteEvents>().RoutedContent += (s, args) =>
            {
                var currentPath = args.RoutingSegmentContext.RequestUrl.AbsolutePath;
                if (!currentPath.EndsWith("/") && string.IsNullOrEmpty(VirtualPathUtility.GetExtension(currentPath))) 
                    args.RoutingSegmentContext.PermanentRedirect(VirtualPathUtility.AppendTrailingSlash(args.RoutingSegmentContext.RequestUrl.ToString()));
            };
        }
#189730
Mar 23, 2018 11:58
Ayo
Vote:
 

I tried to do in code before with this...

 
protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.Request.Url.AbsolutePath != "/" && !HttpContext.Current.Request.Url.AbsolutePath.EndsWith("/"))
{
string redirect = HttpContext.Current.Request.Url.AbsolutePath;
redirect = redirect + "/";
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location", redirect);
Response.End();
}

but the problem I have is everything over http gets this redirect so image URLS /path/path/image.jpg gets redirected to /path/path/image.jpg/ and that gets a 404

This is starting to drive me nuts... there must be a way! :-)

#189731
Mar 23, 2018 12:08
Ayo
Vote:
 

Johan Björnfot

Thank you, thank you thank you.

Doing it in code works, I had a look at your code and I get it now.... this URL redirect only applies to Routed Content that comes from episerver. THANK YOU... works in the staging server too with no SSL problems!

THANK YOU!

#189740
Mar 23, 2018 12:51
Ayo
Vote:
 

Just in case someone else finds this post, here is a quick update. I had to modify the code from Johan, to exclude the back office episerver paths, if you don't do this it will break things like thumbnail previews:

context.Locate.Advanced.GetInstance<IContentRouteEvents>().RoutedContent += (s, args) =>
{
var currentPath = args.RoutingSegmentContext.RequestUrl.AbsolutePath.ToLower();

if (!currentPath.EndsWith("/") && !currentPath.Contains("episerver") && !currentPath.Contains("util") && !currentPath.Contains("App_Themes") && string.IsNullOrEmpty(VirtualPathUtility.GetExtension(currentPath)))
args.RoutingSegmentContext.PermanentRedirect(VirtualPathUtility.AppendTrailingSlash(args.RoutingSegmentContext.RequestUrl.ToString()));
};

 



#189757
Edited, Mar 23, 2018 15:57
Vote:
 

there are lot more things to be aware of that don't need trailign slahes :) like signalr hubs is one of the first that came to my mind.

#189814
Mar 24, 2018 20:39
Ayo
Vote:
 

Hi guys, in the end this is the code that works! it's doing the redicrect on all URLs that don't have the / apart from any paths that are related to Episerver

   [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    [InitializableModule]
    public class TrailingSlash : IInitializableModule
    {
        public void Initialize(InitializationEngine context)
        {
            context.Locate.Advanced.GetInstance<IContentRouteEvents>().RoutedContent += (s, args) =>
            {
                var currentPath = args.RoutingSegmentContext.RequestUrl.AbsolutePath.ToLower();

                if (!currentPath.EndsWith("/") && !currentPath.Contains("episerver") && !currentPath.Contains("util") && !currentPath.EndsWith("App_Themes") && string.IsNullOrEmpty(VirtualPathUtility.GetExtension(currentPath)))
                    args.RoutingSegmentContext.PermanentRedirect(VirtualPathUtility.AppendTrailingSlash(args.RoutingSegmentContext.RequestUrl.ToString()));
            };

        }
}

BUT..... when redirection happens this is what it does

A. https://www.mywebsite.com/uk/products (301)

B. http://www.mywebsite.com/uk/products/ (301)

C. https://www.myserbsite.com/uk/products/ (200)

Is there a way to make it just go from A to C without going to B?




#192205
May 10, 2018 15:35
Vote:
 

which protocol is set as default for your site?

#192206
May 10, 2018 15:42
Ayo
Vote:
 

https on the live site, but on my developer machine.... I just use http

#192207
May 10, 2018 15:44
Vote:
 

why would you have different settings than production? you have to switch to ssl (even locally) and force it via IIS / episerver site bindings.

#192208
Edited, May 10, 2018 15:45
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.