using System.Collections.Generic;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Logging;
using Umbraco.Core.Services;
namespace Umbraco.Web.Routing
{
///
/// Provides an implementation of that handles page url rewrites
/// that are stored when moving, saving, or deleting a node.
///
///
/// Assigns a permanent redirect notification to the request.
///
public class ContentFinderByRedirectUrl : IContentFinder
{
private readonly IRedirectUrlService _redirectUrlService;
private readonly ILogger _logger;
public ContentFinderByRedirectUrl(IRedirectUrlService redirectUrlService, ILogger logger)
{
_redirectUrlService = redirectUrlService;
_logger = logger;
}
///
/// Tries to find and assign an Umbraco document to a PublishedContentRequest.
///
/// The PublishedContentRequest.
/// A value indicating whether an Umbraco document was found and assigned.
/// Optionally, can also assign the template or anything else on the document request, although that is not required.
public bool TryFindContent(PublishedRequest frequest)
{
var route = frequest.HasDomain
? frequest.Domain.ContentId + DomainHelper.PathRelativeToDomain(frequest.Domain.Uri, frequest.Uri.GetAbsolutePathDecoded())
: frequest.Uri.GetAbsolutePathDecoded();
var redirectUrl = _redirectUrlService.GetMostRecentRedirectUrl(route);
// 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
frequest.Cacheability = HttpCacheability.NoCache;
frequest.CacheExtensions = new List { "no-store, must-revalidate" };
frequest.Headers = new Dictionary { { "Pragma", "no-cache" }, { "Expires", "0" } };
if (redirectUrl == null)
{
_logger.Debug(() => $"No match for route: \"{route}\".");
return false;
}
var content = frequest.UmbracoContext.ContentCache.GetById(redirectUrl.ContentId);
var url = content == null ? "#" : content.Url;
if (url.StartsWith("#"))
{
_logger.Debug(() => $"Route \"{route}\" matches content {redirectUrl.ContentId} which has no url.");
return false;
}
_logger.Debug(() => $"Route \"{route}\" matches content {content.Id} with url \"{url}\", redirecting.");
frequest.SetRedirectPermanent(url);
return true;
}
}
}