How to redirect to www. using Blazor

For SEO it’s important that every page on your website only has one canonical URL. A problem that occurs often is that it’s not clear for search engines if the page URL should include the www. prefix.

There are multiple ways of trying to indicate which URL is correct. Your Sitemap can give google and other search engines an indication of what the canonical URL should be, and you can add a link canonicalization tag in the page’s headers as well.

However when it comes to www. versus non-www (also sometimes referred to as a naked domain), the most clear way to make the distinction is to always redirect one to the other. For my website I have chosen to make www. the canonical URL.

To setup a redirect like this in a Blazor Server application, you’re going to have the use the `Microsoft.AspNetCore.Rewrite` namespace. It’s included in a standard Blazor Server project, so no need to find the nuget packager for it.

First you’re going to have to create the Rewrite rules that implements the IRule interface:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Net.Http.Headers;
using System;

namespace WebApplication.Rules
{
    public class RedirectToWwwRule : IRule
    {
        public virtual void ApplyRule(RewriteContext context)
        {
            var req = context.HttpContext.Request;

            // Skip this rule when testing locally
            if (req.Host.Value.Contains("localhost", StringComparison.OrdinalIgnoreCase))
            {
                context.Result = RuleResult.ContinueRules;
                return;
            }

            // Skip this rule when page already includes the www. prefix
            if (req.Host.Value.StartsWith("www.", StringComparison.OrdinalIgnoreCase))
            {
                context.Result = RuleResult.ContinueRules;
                return;
            }

            // Create the url you want to redirect to
            var wwwHost = new HostString($"www.{req.Host.Value}");
            var newUrl = UriHelper.BuildAbsolute(req.Scheme, wwwHost, req.PathBase, req.Path, req.QueryString);

            // Set the statuscode of the response to 301 (Moved Permanently)
            context.HttpContext.Response.StatusCode = 301;

            // Set the new url in the response location header
            context.HttpContext.Response.Headers[HeaderNames.Location] = newUrl;
            context.Result = RuleResult.EndResponse;
        }
    }
}

Next you’re going to have to add the rewrite rule Startup.Configure method as shown here:

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Rewrite;
using Microsoft.Extensions.Hosting;
using WebApplication.Rules;

namespace WebApplication
{
    public class Startup
    {
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

            // Add your rule as shown here:
            var options = new RewriteOptions();
            options.AddRedirectToHttps();
            options.Rules.Add(new RedirectToWwwRule());
            app.UseRewriter(options);

            // app.UseHttpsRedirection(); <-- Remove this line since it's already part of the rewrite options
            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });
        }
    }
}

And that’s it. As soon as you publish your website the redirect should be working. When testing, do pay attention that Chrome nowadays always tries to hide everything before the domain (http(s) and www). When testing with Chrome just type your URL including https:// but without the www. and then click in the address bar twice to force it to show the full page URL. The Method provided in this article was based on hankor's answer on this stackoverflow question.