Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Murray Roke 503 posts 967 karma points c-trib
    Oct 11, 2021 @ 00:21
    Murray Roke
    0

    Optimise my ContentFinder Decorator in v9

    Hi Everyone,
    I'm creating a ContentFinder which decorates and replaces the core content finders, to do a few things like redirect in order to add the trailing slash, or redirect to another page etc. The following code works ok,

    public CanonicalContentFinder(ILogger<CanonicalContentFinder> logger, 
            ILogger<ContentFinderByIdPath> loggerForFinderByIdPath,
            ILogger<ContentFinderByUrl> loggerForFinderByUrl,
            IOptions<Umbraco.Cms.Core.Configuration.Models.WebRoutingSettings> options,
            IRequestAccessor requestAccessor,
            IUmbracoContextAccessor umbracoContextAccessor)
    {
            _logger = logger;
            _finderByUrl = new ContentFinderByUrl(loggerForFinderByUrl, umbracoContextAccessor);
            _finderByIdPath = new ContentFinderByIdPath(options, loggerForFinderByIdPath, requestAccessor, umbracoContextAccessor);
    }
    

    However, I feel un-easy newing up those core content finders, I tried asking for them via constructor parameters but I get this error:

    AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Dls.ContentFinders.CanonicalContentFinder Lifetime: Singleton ImplementationType: Dls.ContentFinders.CanonicalContentFinder': Unable to resolve service for type 'Umbraco.Cms.Core.Routing.ContentFinderByUrl' while attempting to activate 'Dls.ContentFinders.CanonicalContentFinder'.)

    Does anyone have any advice?
    Cheers.
    Murray.

  • Thomas 319 posts 606 karma points c-trib
    Nov 16, 2021 @ 15:54
    Thomas
    0

    Hi,

    Did you find a solution ?

  • Murray Roke 503 posts 967 karma points c-trib
    Nov 24, 2021 @ 00:40
    Murray Roke
    0

    No.
    What I have works, but it has a bad 'smell'

  • Matthew Wise 271 posts 1373 karma points MVP 5x c-trib
    Nov 24, 2021 @ 10:00
    Matthew Wise
    0

    You can inject ContentFinderCollection

    The query it using Linq

            var contentFinderByUrl = contentFinderCollection.FirstOrDefault(x => x is ContentFinderByUrl);
            contentFinderByUrl.TryFindContent
    
  • Murray Roke 503 posts 967 karma points c-trib
    Nov 30, 2021 @ 21:27
    Murray Roke
    0

    I don't think this will work because I want to remove the ContentFinderByUrl from the collection and replace it with mine... but I did try just in case...

    I tried this:

    public class CanonicalContentFinder : IContentFinder
    {
        private readonly ILogger<CanonicalContentFinder> _logger;
        private readonly IRequestAccessor _requestAccessor;
        private readonly ContentFinderByUrl _finderByUrl;
        private readonly ContentFinderByIdPath _finderByIdPath;
    
        public CanonicalContentFinder(ILogger<CanonicalContentFinder> logger, 
            ILogger<ContentFinderByIdPath> loggerForFinderByIdPath,
            ILogger<ContentFinderByUrl> loggerForFinderByUrl,
            IOptions<Umbraco.Cms.Core.Configuration.Models.WebRoutingSettings> options,
            IRequestAccessor requestAccessor,
            IUmbracoContextAccessor umbracoContextAccessor,
            ContentFinderCollection cfc)
        {
            _logger = logger;
            _requestAccessor = requestAccessor;
            _finderByUrl = (ContentFinderByUrl)cfc.FirstOrDefault(x => x is ContentFinderByUrl);
            _finderByIdPath = (ContentFinderByIdPath)cfc.FirstOrDefault(x => x is ContentFinderByIdPath);
            //_finderByUrl = new ContentFinderByUrl(loggerForFinderByUrl, umbracoContextAccessor);
            //_finderByIdPath = new ContentFinderByIdPath(options, loggerForFinderByIdPath, requestAccessor, umbracoContextAccessor);
        }
    

    with this composer (to make sure it hadn't removed the content finders I needed

    public class DxpContentFindersComposer : IComposer
    {
        public void Compose(IUmbracoBuilder builder)
        {
            builder.ContentFinders().InsertBefore<ContentFinderByUrl, CanonicalContentFinder>();
            //builder.ContentFinders().Remove<ContentFinderByUrl>();
            //builder.ContentFinders().Remove<ContentFinderByIdPath>();
            builder.ContentFinders().InsertAfter<CanonicalContentFinder, RedirectsContentFinder>();
            builder.SetContentLastChanceFinder<NotFoundContentFinder>();
        }
    }
    

    And I get this exception

    InvalidOperationException: ValueFactory attempted to access the Value property of this instance.
    System.Lazy<T>.ViaFactory(LazyThreadSafetyMode mode)
    System.Lazy<T>.ExecutionAndPublication(LazyHelper executionAndPublication, bool useDefaultConstructor)
    System.Lazy<T>.CreateValue()
    System.Lazy<T>.get_Value()
    Umbraco.Cms.Core.Composing.LazyReadOnlyCollection<T>.EnsureCollection()
    Umbraco.Cms.Core.Composing.LazyReadOnlyCollection<T>.get_Value()
    Umbraco.Cms.Core.Composing.LazyReadOnlyCollection<T>.GetEnumerator()
    Umbraco.Cms.Core.Composing.BuilderCollectionBase<TItem>.GetEnumerator()
    System.Linq.Enumerable.TryGetFirst<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate, out bool found)
    System.Linq.Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource> source, Func<TSource, bool> predicate)
    DXP.ContentFinders.CanonicalContentFinder..ctor(ILogger<CanonicalContentFinder> logger, ILogger<ContentFinderByIdPath> loggerForFinderByIdPath, ILogger<ContentFinderByUrl> loggerForFinderByUrl, IOptions<WebRoutingSettings> options, IRequestAccessor requestAccessor, IUmbracoContextAccessor umbracoContextAccessor, ContentFinderCollection cfc) in CanonicalContentFinder.cs
    +
                _finderByUrl = (ContentFinderByUrl)cfc.FirstOrDefault(x => x is ContentFinderByUrl);
    System.RuntimeMethodHandle.InvokeMethod(object target, object[] arguments, Signature sig, bool constructor, bool wrapExceptions)
    System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
    ...etc...
    
  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies