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.