I needed to do this on a project last year. I meant to share my solution but I forget.
Here is the code if you are looking for it.
using System;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.SessionState;
using CodeShare.Core.Extensions;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Web;
namespace CodeShare.Core.Handlers
{
public class HtmlHandler : IHttpHandler, IRequiresSessionState
{
public void ProcessRequest(HttpContext context)
{
var contextBase = context.ToBase();
var originalUrl = context.Request.Url.PathAndQuery;
if (originalUrl.StartsWith("/umbraco"))
{
UseExistingStaticFileHandler(context);
return;
}
string path = context.Server.MapPath(context.Request.RawUrl);
// Is there a file that already exists on the file system?
// If so, always serve that.
if (System.IO.File.Exists(path))
{
Umbraco.Web.Composing.Current.Logger.Debug<HtmlHandler>("Streaming specified static file from disk.");
contextBase.Response.TransmitFileContent(path);
return;
}
// Ensure there is an Umbraco context that is necessary for data access.
var umbracoContextFactory = Umbraco.Web.Composing.Current.Factory.GetInstance(typeof(IUmbracoContextFactory)) as IUmbracoContextFactory;
var umbracoContext = umbracoContextFactory?.EnsureUmbracoContext(contextBase)?.UmbracoContext;
if (umbracoContext == null)
{
Umbraco.Web.Composing.Current.Logger.Warn<HtmlHandler>("Umbraco context is null even after ensuring there is one!");
throw new HttpException((int)HttpStatusCode.NotFound, "Page Not Found");
}
//use the correct content type alias here for your root node
var homeNode = umbracoContext.Content.GetAtRoot().FirstOrDefault(x => x.ContentType.Alias == "homePage");
IPublishedContent content = null;
if (homeNode != null)
{
content = GetContentWithMatchingLegacyUrl(homeNode, path: originalUrl);
}
if (content != null)
{
context.Response.RedirectPermanent(content.Url);
}
else
{
UseExistingStaticFileHandler(context);
}
}
private static void UseExistingStaticFileHandler(HttpContext context)
{
Type type = typeof(HttpApplication).Assembly.GetType("System.Web.StaticFileHandler", true);
IHttpHandler handler = (IHttpHandler)Activator.CreateInstance(type, true);
handler.ProcessRequest(context);
}
public bool IsReusable => false;
private static IPublishedContent GetContentWithMatchingLegacyUrl(IPublishedContent rootNode, string path)
{
return rootNode.DescendantsOrSelf().FirstOrDefault(
x => x.HasValue("legacyUrl") && x.Value<string>("legacyUrl") == path);
}
}
}
I hope it helps you, and more importantly me when I need the code in 6 months time