Last active
May 24, 2020 16:49
-
-
Save sotirisf/a8d83e8fca45887cfb3ccc73860526f8 to your computer and use it in GitHub Desktop.
Umbraco Poor Man's Old Url Redirector
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using Umbraco.Core; | |
| using Umbraco.Core.Cache; | |
| using Umbraco.Core.Composing; | |
| using Umbraco.Web; | |
| using Umbraco.Web.PublishedModels; | |
| using Umbraco.Web.Routing; | |
| namespace Site.Core | |
| { | |
| public class OldUrlContentFinder : IContentFinder | |
| { | |
| public virtual bool TryFindContent(PublishedRequest contentRequest) | |
| { | |
| //Get the ORIGINAL request (before cleaning up) | |
| //We actually need the original request, since this is what we're going to redirect from. | |
| //After cleanup url changes e.g. test.aspx?a=1 becomes test?a=1. | |
| var req = contentRequest.UmbracoContext.HttpContext.Request; | |
| var oldUrl = req.ServerVariables["HTTP_HOST"] + req.RawUrl; //Could use Uri.Authority too | |
| var nodesWithRedirects = | |
| (IEnumerable<string[]>)Current.AppCaches.RuntimeCache.GetCacheItem("cachedoldurls", () => | |
| contentRequest | |
| .UmbracoContext | |
| .Content | |
| .GetAtRoot() | |
| .Where(x => x.TemplateId > 0) | |
| .SelectMany(x => x.Descendants<IAbstractPage>()) | |
| .Where(x => x.HasProperty("oldUrl") && !string.IsNullOrEmpty(x.Value<string>("oldUrl"))) | |
| .Select(x => new string[] { x.Value<string>("oldUrl"), x.Url }) | |
| ); | |
| string[] actualNodeEntry = nodesWithRedirects | |
| .Where(x => x[0].UrlEquals(oldUrl)) | |
| .FirstOrDefault(); | |
| string actualUrl = actualNodeEntry?[1]; | |
| if (actualUrl != null) | |
| { | |
| contentRequest.SetRedirectPermanent(actualUrl); | |
| return true; | |
| } | |
| return false; | |
| } | |
| } | |
| public static class UrlUtils | |
| { | |
| public static bool UrlEquals(this string oldUrl, string currentUrl) | |
| { | |
| //Get rid of protocol, since our new url hasn't got one, we're going to compare | |
| //urls without it. | |
| Uri oldUrlUri = new Uri(oldUrl.Replace("https://", "").Replace("http://", "")); | |
| Uri currentUrlUri = new Uri(currentUrl); | |
| UriBuilder ub1 = new UriBuilder(oldUrlUri); | |
| ub1.Query = string.Join("&", oldUrlUri.Query.Replace("?", "").Split('&').OrderBy(x => x)); | |
| UriBuilder ub2 = new UriBuilder(currentUrlUri); | |
| ub2.Query = string.Join("&", currentUrlUri.Query.Replace("?", "").Split('&').OrderBy(x => x)); | |
| return Uri.Compare(ub1.Uri, ub2.Uri, UriComponents.AbsoluteUri, UriFormat.UriEscaped, StringComparison.InvariantCultureIgnoreCase) == 0; | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using Umbraco.Core; | |
| using Umbraco.Core.Composing; | |
| using Umbraco.Web; | |
| using Umbraco.Web.Routing; | |
| namespace Site.Core | |
| { | |
| [RuntimeLevel(MinLevel = RuntimeLevel.Run)] | |
| public class OldUrlContentFinderComposer : IUserComposer | |
| { | |
| public void Compose(Composition composition) | |
| { | |
| composition.ContentFinders().InsertBefore<ContentFinderByUrl, OldUrlContentFinder>(); | |
| } | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections.Generic; | |
| using System.Linq; | |
| using Umbraco.Core; | |
| using Umbraco.Core.Composing; | |
| using Umbraco.Core.Events; | |
| using Umbraco.Core.Models; | |
| using Umbraco.Core.Persistence; | |
| using Umbraco.Core.Persistence.Querying; | |
| using Umbraco.Core.Services; | |
| using Umbraco.Core.Services.Implement; | |
| using Umbraco.Web.PublishedModels; | |
| namespace Site.Core | |
| { | |
| public class SiteEvents : IUserComposer | |
| { | |
| public void Compose(Composition composition) | |
| { | |
| composition.Components().Append<SubscribeToEvents>(); | |
| } | |
| } | |
| public class SubscribeToEvents : IComponent | |
| { | |
| private readonly IContentTypeService _contentTypeService; | |
| private readonly ISqlContext _sqlContext; | |
| private readonly IContentService _contentService; | |
| public SubscribeToEvents(IContentTypeService contentTypeService, IContentService contentService, ISqlContext sqlContext) | |
| { | |
| _contentTypeService = contentTypeService; | |
| _contentService = contentService; | |
| _sqlContext = sqlContext; | |
| } | |
| public void Initialize() | |
| { | |
| ContentService.Published += ContentService_Published; | |
| ContentService.Deleted += ContentService_Deleted; | |
| ContentService.Copied += ContentService_Copied; | |
| ContentService.Moved += ContentService_Moved; | |
| ContentService.RolledBack += ContentService_RolledBack; | |
| ContentService.Saved += ContentService_Saved; | |
| ContentService.Publishing += ContentService_Publishing; | |
| ContentService.Unpublished += ContentService_UnPublished; | |
| ClearRuntimeCache(); | |
| } | |
| public void Terminate() | |
| { | |
| } | |
| private void ContentService_UnPublished(IContentService sender, PublishEventArgs<IContent> e) | |
| { | |
| ClearRuntimeCache(); | |
| } | |
| private void ContentService_Publishing(IContentService sender, ContentPublishingEventArgs e) | |
| { | |
| ClearRuntimeCache(); | |
| } | |
| private void ContentService_Saved(IContentService sender, ContentSavedEventArgs e) | |
| { | |
| ClearRuntimeCache(); | |
| } | |
| private void ContentService_RolledBack(IContentService sender, RollbackEventArgs<IContent> e) | |
| { | |
| ClearRuntimeCache(); | |
| } | |
| private void ContentService_Moved(IContentService sender, MoveEventArgs<IContent> e) | |
| { | |
| ClearRuntimeCache(); | |
| } | |
| private void ContentService_Copied(IContentService sender, CopyEventArgs<IContent> e) | |
| { | |
| ClearRuntimeCache(); | |
| } | |
| private void ContentService_Deleted(IContentService sender, DeleteEventArgs<IContent> e) | |
| { | |
| ClearRuntimeCache(); | |
| } | |
| private void ContentService_Published(IContentService sender, PublishEventArgs<IContent> e) | |
| { | |
| ClearRuntimeCache(); | |
| } | |
| private void ClearRuntimeCache() | |
| { | |
| Current.AppCaches.RuntimeCache.ClearByKey("cachedoldurls"); | |
| //Add any other stuff you need to do here | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment