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 966 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 315 posts 602 karma points c-trib
    Nov 16, 2021 @ 15:54
    Thomas
    0

    Hi,

    Did you find a solution ?

  • Murray Roke 503 posts 966 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 4x 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 966 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...
    
Please Sign in or register to post replies

Write your reply to:

Draft