Try our conversational search powered by Generative AI!

Can I change the trailing-slash redirection from a 302 to a 301?

Vote:
 

When a request comes in for a page without a trailing slash, EPiServer redirects it to the same page but with a trailing slash.  However, it does this with a 302 Found, instead of a 301 Moved Permanently.

I think this is EPiServer-specific behavior, not IIS behavior.  I found an ASP.Net site not running EPiServer, and used Curl to request a directory without the trailing slash.  It redirected me with a 301, rather than a 302.  So, somewhere, EPiServer is specifically using a 302, and my client wants a 301.

Is there any way to change this?

#57224
Mar 02, 2012 23:04
Vote:
 

Yes, this happens in the url rewriter.

You can write your own and handle the redirect in a nicer way.

#57225
Mar 02, 2012 23:36
Vote:
 

In what method in the rewriter?  They already have a custom one, so it wouldn't be a big stretch to override something else.

#57226
Mar 02, 2012 23:47
Vote:
 

It happens in:

public override bool TryConvertToInternal(UrlBuilder url, out CultureInfo preferredCulture, out object internalObject)
{
}

 I think there is just a simple check like this:

if (!url.Path.EndsWith("/"))
{
    HttpContext.Current.Response.Redirect(url.Path + "/" + url.Query + url.Fragment);
}

    

#57232
Mar 03, 2012 0:53
Vote:
 

Oh, this goes for 6 R2, in earlier versions the method is just called ConvertToInternal.

#57233
Mar 03, 2012 0:56
Vote:
 

Your client is right. It really should be a 301 so someone ought to get it filed as a bug.

#57234
Mar 03, 2012 20:53
Vote:
 

Thanks, we changed to permanent redirect in vNext.

#57251
Mar 05, 2012 10:39
Vote:
 

It's actually not in the FriendlyUrlRewriter.  Rather, it's out in the UrlRewriteModule.  The FriendlyUrlRewriter just returns something called a RedirectPageReference, which the module picks up.

I think I was able to fix this by extended UrlWriteModule, overriding one method, and changing about three lines of code.  Based on my testing, this works correctly.

using System.Web;
using EPiServer.Core;
using EPiServer.Web;
using log4net;

namespace EPiServer
{
    public class CorrectedUrlRewriteModule : UrlRewriteModule
    {
        private static ILog _log = LogManager.GetLogger(typeof(UrlRewriteModule));

        protected override void HttpUrlRewriteToInternal(UrlBuilder url)
        {
            UrlRewriteEventArgs e = new UrlRewriteEventArgs(url, new UrlRewriteEventArgs.Context(this.UrlInternal, this.UrlExternal));
            this.OnHttpRewritingToInternal(e);
            if (e.Cancel)
            {
                if (!_log.IsDebugEnabled)
                    return;
                _log.DebugFormat("Further URL rewriting stopped. Returning URL {0}", (object)e.Url);
            }
            else
            {
                Global.UrlRewriteProvider.ValidateRewriteToInternal(e, this.UrlExternal.Path);
                if (e.Cancel)
                {
                    if (!_log.IsDebugEnabled)
                        return;
                    _log.DebugFormat("Url is not valid for rewrite. Returning URL {0}", (object)e.Url);
                }
                else
                {
                    object internalObject;
                    if (Global.UrlRewriteProvider.ConvertToInternal(e.Url, out internalObject))
                    {
                        if (internalObject is RedirectPageReference)
                        {
                            // This is the only code that has changed in this overridden method.  This changes the redirect from the default 302 to a 301.
                            HttpContext.Current.Response.StatusCode = 301;
                            HttpContext.Current.Response.StatusDescription = "Moved Permanently";
                            HttpContext.Current.Response.RedirectLocation = (string) e.Url;
                            HttpContext.Current.ApplicationInstance.CompleteRequest();
                            return;
                        }
                        else
                        {
                            e.IsModified = true;
                            PageReference pageReference = internalObject as PageReference;
                            if (_log.IsDebugEnabled)
                                _log.DebugFormat("Returning URL {0} as PageReference {0}", (object)e.Url, pageReference == (PageReference)null ? (object)"(NULL)" : (object)pageReference.ToString());
                        }
                    }
                    else if (_log.IsDebugEnabled)
                        _log.DebugFormat("Returning URL {0}", (object)e.Url.ToString());
                    this.OnHttpRewroteToInternal(e);
                }
            }
        }
    }
}

    

#57317
Mar 10, 2012 23:04
Vote:
 

We've found a bizarre problem with this, and I have no idea how to fix it.  Our app is running in a Virtual Directory.  When you have an EPiServer page that shortcuts to a page on the same server (same domain), but not in the same Virtual Directory, you get this:

The virtual path '/beneficiary/FeePayment/AcctInfo.aspx' maps to another application, which is not allowed.

I only changed those four lines of code, so I have NO idea where this error could be coming from.

#57832
Mar 29, 2012 16:07
Vote:
 

HI All

The solution by "Deane Barker" is the correct one with change in "UrlRewriteModule".  Fully tested and works great.

Thanks

Kind Regards

Sandeep

#60840
Aug 28, 2012 12:46
Vote:
 

If I were to use Deane Barkers UrlRewriteModule-solution, how do I configure EPi to use it? Is it in episerver.config ?

All the best

Linus

#77193
Nov 12, 2013 17:09
Vote:
 

In case somebody is interested: you have to set the type to the namespace and dll name of the 'UrlRewriteModule' in the web.config

#86503
May 22, 2014 16:32
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.
* 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.