SEO redirects in .NET
It's way more complicated to be unique nowadays. Having a website is one of the main ways to represent the company and basically, a must-have. But as important as to HAVE the website, it is also crucial to MAKE it easily searchable, especially in an environment of strong competition.
Apart from that, the website must also be highly positioned in the search results and to make it happen, it must meet many of the SEO conditions.
It usually ends with making the website follow one common pattern in the URLs, such as allowing only lowercase characters, ending (or not) with trailing slashes, or forcing the user to use www at the beginning of the URI. Thankfully, .NET comes with easy-to-use middleware to add rewrite rules, helping meet the SEO requirements.
All that needs to be done is to add URL Rewrite middleware in the Configure method of the Startup file.
app.UseRewriter(new RewriteOptions()
.SkipStaticFiles()
.SkipCmsUrls()
.AddRedirectToTrailingSlashesPermanent()
.AddRedirectToLowercaseUrlPermanent()
.SkipRemainingRulesIfDxp()
.AddRedirectToWwwPermanent());
Worth mentioning is that the order matters and the first one executed will be the top one, so it might be good to put the most frequently used rule there.
The rules in the example above use extension methods so the Startup file is clean and easy to read. The actual logic can be seen in the implementation of the methods. The first rule skips the static files, so the middleware doesn't apply the next rules when it discovers any file extension.
public static RewriteOptions SkipStaticFiles(this RewriteOptions options)
{
options.Add(context =>
{
bool hasFileExtension = Regex.IsMatch(context.HttpContext.Request.Path.Value, @".*/[^.]*\.[\d\w]+$");
if (hasFileExtension)
{
context.Result = RuleResult.SkipRemainingRules;
}
});
return options;
}
The next one is related to the CMS environment where we don't want to force any redirects which probably will result in breaking the platform. It adds URLs patterns that should not be redirected by the next rules. We can see URLs like util or episerver known from Optimizely CMS. It is also important to add URLs of any of the external tools installed in the CMS, like Localization DB provider or GETA Sitemaps. They can malfunction without those rules.
public static RewriteOptions SkipCmsUrls(this RewriteOptions options)
{
options.Add(context =>
{
if (context.HttpContext.Request.Path.StartsWithSegments("/util") ||
context.HttpContext.Request.Path.StartsWithSegments("/episerver") ||
context.HttpContext.Request.Path.StartsWithSegments("/modules") ||
context.HttpContext.Request.Path.StartsWithSegments("/localization-admin") ||
context.HttpContext.Request.Path.StartsWithSegments("/getaoptimizelysitemaps"))
{
context.Result = RuleResult.SkipRemainingRules;
}
});
return options;
}
Next, we have the trailing slashes rule which is just a simple regex redirection
public static RewriteOptions AddRedirectToTrailingSlashesPermanent(this RewriteOptions options)
{
options.AddRedirect("(.*[^/])$", "$1/", (int)HttpStatusCode.MovedPermanently);
return options;
}
The AddRedirectToLowercaseUrlPermanent is a bit more complicated as it requires the creation of a custom implementation of the Microsoft.AspNetCore.Rewrite.IRule interface, which exposes a method called ApplyRule
public void ApplyRule(RewriteContext context)
{
var request = context.HttpContext.Request;
var path = context.HttpContext.Request.Path;
var host = context.HttpContext.Request.Host;
if (path.HasValue && path.Value.Any(char.IsUpper) || host.HasValue && host.Value.Any(char.IsUpper))
{
var response = context.HttpContext.Response;
response.StatusCode = StatusCode;
response.Headers[HeaderNames.Location] =
(request.Scheme + "://" + host.Value + request.PathBase.Value + request.Path.Value).ToLower() +
request.QueryString;
context.Result = RuleResult.EndResponse;
}
else
{
context.Result = RuleResult.ContinueRules;
}
}
The last rule is built in .NET and adds a permanent redirect to www. When doing this in the Optimizely environment called DXP it is important to remember that this redirection can break access by using the default DXP URLs. This is the main reason why before the www redirection rule there was a rule checking if there is a URL other than the DXP one. The rule is another implementation of the IRule which looks like this:
public void ApplyRule(RewriteContext context)
{
var host = context.HttpContext.Request.Host;
if (host.HasValue && host.Value.EndsWith(".dxcloud.episerver.net"))
{
context.Result = RuleResult.SkipRemainingRules;
}
else
{
context.Result = RuleResult.ContinueRules;
}
}
That would be all. Now, our website can get a few more points in the global SEO race.
More articles
Custom payment in Optimizely Commerce 14
Create a payment flow perfectly suitable to your individual needs
Global Components Builders
Implementing global common components every site consists of