Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save enkelmedia/ca1933f1e7c016df79a87992e647cac4 to your computer and use it in GitHub Desktop.
Save enkelmedia/ca1933f1e7c016df79a87992e647cac4 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Web.Routing;
namespace Obviuse.Utilities.Umbraco.Routing
{
// Based on the original ContentFinderByRedirectUrl from Umbraco-Core: https://github.com/umbraco/Umbraco-CMS/blob/1bb593d264a085f94a3ce3bd710392b350561430/src/Umbraco.Web/Routing/ContentFinderByRedirectUrl.cs#L47
/// <summary>
/// Provides an implementation of <see cref="IContentFinder"/> that handles page url rewrites
/// This implementation is based on the <see cref="ContentFinderByRedirectUrl" /> but is extended with support for QueryStrigs.
/// that are stored when moving, saving, or deleting a node.
/// </summary>
/// <remarks>
/// <para>Assigns a permanent redirect notification to the request.</para>
/// </remarks>
public class ContentFinderByRedirectUrlWithQueryStrings : IContentFinder
{
/// <summary>
/// Tries to find and assign an Umbraco document to a <c>PublishedContentRequest</c>.
/// </summary>
/// <param name="contentRequest">The <c>PublishedContentRequest</c>.</param>
/// <returns>A value indicating whether an Umbraco document was found and assigned.</returns>
/// <remarks>Optionally, can also assign the template or anything else on the document request, although that is not required.</remarks>
public bool TryFindContent(PublishedContentRequest contentRequest)
{
var route = contentRequest.HasDomain
? contentRequest.UmbracoDomain.RootContentId + DomainHelper.PathRelativeToDomain(contentRequest.DomainUri, contentRequest.Uri.GetAbsolutePathDecoded())
: contentRequest.Uri.GetAbsolutePathDecoded();
var service = contentRequest.RoutingContext.UmbracoContext.Application.Services.RedirectUrlService;
var redirectUrl = service.GetMostRecentRedirectUrl(route);
if (redirectUrl == null)
{
LogHelper.Debug<ContentFinderByRedirectUrlWithQueryStrings>("No match for route: \"{0}\".", () => route);
return false;
}
var content = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetById(redirectUrl.ContentId);
var url = content == null ? "#" : content.Url;
if (url.StartsWith("#"))
{
LogHelper.Debug<ContentFinderByRedirectUrlWithQueryStrings>("Route \"{0}\" matches content {1} which has no url.", () => route, () => redirectUrl.ContentId);
return false;
}
LogHelper.Debug<ContentFinderByRedirectUrlWithQueryStrings>("Route \"{0}\" matches content {1} with url \"{2}\", redirecting.", () => route, () => content.Id, () => url);
// From: http://stackoverflow.com/a/22468386/5018
// See http://issues.umbraco.org/issue/U4-8361#comment=67-30532
// Setting automatic 301 redirects to not be cached because browsers cache these very aggressively which then leads
// to problems if you rename a page back to it's original name or create a new page with the original name
HttpContextBase cb = new HttpContextWrapper(HttpContext.Current);
cb.Response.Cache.SetCacheability(HttpCacheability.NoCache);
cb.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
cb.Response.AppendHeader("Pragma", "no-cache");
cb.Response.AppendHeader("Expires", "0");
// Can't set these values since they are internal.
//contentRequest.Cacheability = HttpCacheability.NoCache;
//contentRequest.CacheExtensions = new List<string> { "no-store, must-revalidate" };
//contentRequest.Headers = new Dictionary<string, string> { { "Pragma", "no-cache" }, { "Expires", "0" } };
// Check if the incomming request has a querystring, in that add the querystring to the redirect.
url = string.IsNullOrEmpty(contentRequest.Uri.Query) ? url : url + contentRequest.Uri.Query;
contentRequest.SetRedirectPermanent(url);
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment