Don't miss out Virtual Happy Hour this Friday (April 26).

Try our conversational search powered by Generative AI!

Custom UrlResolver in v12?

Ian
Ian
Vote:
 

It seems that the EPiServer.Web.Routing.Internal.DefaultUrlResolver class is marked as internal and can no longer be inherted as a base class. Is there an alternate approach to creating a custom UrlResolver in v12?

This was the previous approach in v11 and lower that worked great. Existing example thread @ https://world.optimizely.com/forum/developer-forum/CMS/Thread-Container/2016/12/use-own-urlresolver-/

    public class CustomUrlResolver : EPiServer.Web.Routing.Internal.DefaultUrlResolver
    {
        private readonly IContentLoader _contentLoader;

        public CustomUrlResolver(
            RouteCollection routes,
            IContentLoader contentLoader,
            ISiteDefinitionRepository siteDefinitionRepository,
            TemplateResolver templateResolver,
            IPermanentLinkMapper permanentLinkMapper,
            IContentLanguageSettingsHandler contentLanguageSettingsHandler) :
            base(
                routes,
                contentLoader,
                siteDefinitionRepository,
                templateResolver,
                permanentLinkMapper,
                contentLanguageSettingsHandler)
        {
            _contentLoader = contentLoader;
        }

        // Code omitted for brevity
}
#292343
Edited, Nov 28, 2022 16:40
Vote:
 

Could you create your own implementation of IUrlResolver or Inherit UrlResolver instead ? 

e.g. 

using EPiServer.Framework.Web;
using EPiServer.Web;
using EPiServer.Web.Routing;

namespace AlloyTech1
{
    public class CustomUrlResolver : UrlResolver
    {
        private readonly IContentLoader _contentLoader;

        private readonly IUrlResolver _baseUrlResolver;
        private readonly TemplateResolver _templateResolver;
        private readonly IContextModeResolver _contextModeResolver;
        private const string _defaultAction = "index";
        private readonly LoaderOptions _masterLanguageLoaderOption;

        public CustomUrlResolver(
            RouteCollection routes,
            IContentLoader contentLoader,
            ISiteDefinitionRepository siteDefinitionRepository,
            TemplateResolver templateResolver,
            IPermanentLinkMapper permanentLinkMapper,
            IContentLanguageSettingsHandler contentLanguageSettingsHandler)
        {
            _contentLoader = contentLoader;
        }

        // Code omitted for brevity
        public override VirtualPathData GetVirtualPathForNonContent(
           object partialRoutedObject,
           string language,
           VirtualPathArguments virtualPathArguments)
        {
            UrlResolverArguments urlResolverArguments = (UrlResolverArguments)virtualPathArguments ?? new UrlResolverArguments();
            return VirtualPathDataBuilder(this._baseUrlResolver.GetPartialRoutedUrl(partialRoutedObject, urlResolverArguments));
        }

        public override IContent Route(UrlBuilder urlBuilder, ContextMode contextMode) => this._baseUrlResolver.Route(urlBuilder, contextMode);

        public override ContentRouteData Route(
          UrlBuilder url,
          RouteArguments routeArguments)
        {
            return this._baseUrlResolver.Route(url, routeArguments);
        }

        public override bool TryToPermanent(string url, out string permanentUrl) => this._baseUrlResolver.TryToPermanent(url, out permanentUrl);

        protected override string GetUrlCore(
          ContentReference contentLink,
          string language,
          UrlResolverArguments urlResolverArguments)
        {
            return this._baseUrlResolver.GetUrl(contentLink, language, urlResolverArguments);
        }

        protected override string GetUrlCore(
          UrlBuilder urlBuilderWithInternalUrl,
          UrlResolverArguments arguments)
        {
            return this._baseUrlResolver.GetUrl(urlBuilderWithInternalUrl, arguments);
        }

        public override VirtualPathData GetVirtualPath(
          ContentReference contentLink,
          string language,
          VirtualPathArguments virtualPathArguments)
        {
            if (virtualPathArguments == null)
                virtualPathArguments = new VirtualPathArguments();
            VirtualPathData virtualPath = base.GetVirtualPath(contentLink, language, virtualPathArguments);
            if (virtualPath != null && virtualPathArguments.ValidateTemplate && !this.HasTemplate(contentLink, this.GetOrResolveContextMode(virtualPathArguments.ContextMode)))
                return (VirtualPathData)null;
            if (virtualPath != null)
                virtualPath.VirtualPath = CustomUrlResolver.AppendActionIfPresent(virtualPath?.VirtualPath, virtualPathArguments.Action);
            return virtualPath;
        }

        public override string GetUrl(
          UrlBuilder urlBuilderWithInternalUrl,
          VirtualPathArguments virtualPathArguments)
        {
            if (virtualPathArguments == null)
                virtualPathArguments = new VirtualPathArguments();
            string url = base.GetUrl(urlBuilderWithInternalUrl, virtualPathArguments);
            if (!string.Equals(url, (string)urlBuilderWithInternalUrl) && virtualPathArguments.ValidateTemplate)
            {
                Guid guid = PermanentLinkUtility.GetGuid(urlBuilderWithInternalUrl, out string _);
                if (guid != Guid.Empty && !this.HasTemplate(guid, this.GetOrResolveContextMode(virtualPathArguments.ContextMode)))
                    return (string)null;
            }
            return CustomUrlResolver.AppendActionIfPresent(url, virtualPathArguments.Action);
        }

        private bool HasTemplate(ContentReference contentLink, ContextMode contextMode)
        {
            IContent content;
            return this._contentLoader.TryGet<IContent>(contentLink, this._masterLanguageLoaderOption, out content) && this._templateResolver.HasTemplate((IContentData)content, TemplateTypeCategories.Page, contextMode);
        }

        private bool HasTemplate(Guid contentGuid, ContextMode contextMode)
        {
            IContent content;
            return this._contentLoader.TryGet<IContent>(contentGuid, this._masterLanguageLoaderOption, out content) && this._templateResolver.HasTemplate((IContentData)content, TemplateTypeCategories.Page, contextMode);
        }

        private ContextMode GetOrResolveContextMode(ContextMode contextMode) => contextMode == ContextMode.Undefined ? this._contextModeResolver.CurrentMode : contextMode;

        private static string AppendActionIfPresent(string url, string action)
        {
            if (string.IsNullOrEmpty(action) || string.IsNullOrEmpty(url) || action.Equals("index", StringComparison.OrdinalIgnoreCase))
                return url;
            UrlBuilder urlBuilder = new UrlBuilder(url);
            urlBuilder.Path = VirtualPathUtilityEx.Combine(urlBuilder.Path, action);
            return (string)urlBuilder;
        }

        public static VirtualPathData VirtualPathDataBuilder(string url)
        {
            if (string.IsNullOrEmpty(url))
                return (VirtualPathData)null;
            UrlBuilder urlBuilder = new UrlBuilder(url);
            VirtualPathData virtualPathData = new VirtualPathData((IRouter)ContentRouter.Instance, urlBuilder.Path);
            foreach (string allKey in urlBuilder.QueryCollection.AllKeys)
                virtualPathData.DataTokens.Add(allKey, (object)urlBuilder.QueryCollection[allKey]);
            if (urlBuilder.HasAuthorityPart)
                virtualPathData.DataTokens[RoutingConstants.RootPath] = (object)urlBuilder.Uri.GetComponents(UriComponents.SchemeAndServer, UriFormat.Unescaped);
            return virtualPathData;
        }
    }
}

#292351
Nov 28, 2022 20:43
Vote:
 

Yes, you now have to implement IUrlResolver, or extend UrlResolver.

#292397
Nov 29, 2022 9:45
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.