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'.)
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...
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,
However, I feel un-easy newing up those core content finders, I tried asking for them via constructor parameters but I get this error:
Does anyone have any advice?
Cheers.
Murray.
Hi,
Did you find a solution ?
No.
What I have works, but it has a bad 'smell'
You can inject
ContentFinderCollection
The query it using Linq
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:
with this composer (to make sure it hadn't removed the content finders I needed
And I get this exception
is working on a reply...