我正在从Sitecore 8.2升级到9.1。加载仪表板时出现以下错误:
Server Error in '/' Application.
Unable to resolve service for type 'Jabberwocky.Core.Caching.ICacheProvider' while attempting to activate 'CCO.Foundation.SitecoreExtensions.Pipelines.GetXmlBasedLayoutDefinition.InsertCascadedRenderings'.
Description: An unhandled exception occurred.
Exception Details: System.InvalidOperationException: Unable to resolve service for type 'Jabberwocky.Core.Caching.ICacheProvider' while attempting to activate 'CCO.Foundation.SitecoreExtensions.Pipelines.GetXmlBasedLayoutDefinition.InsertCascadedRenderings'.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: Unable to resolve service for type 'Jabberwocky.Core.Caching.ICacheProvider' while attempting to activate 'CCO.Foundation.SitecoreExtensions.Pipelines.GetXmlBasedLayoutDefinition.InsertCascadedRenderings'.]
Microsoft.Extensions.DependencyInjection.ConstructorMatcher.CreateInstance(IServiceProvider provider) +405
Sitecore.Configuration.DefaultFactory.CreateFromServiceProvider(XmlNode configNode, Boolean assert) +481
[ConfigurationException: Could not create object from service provider . Config XML: <processor type="CCO.Foundation.SitecoreExtensions.Pipelines.GetXmlBasedLayoutDefinition.InsertCascadedRenderings, CCO.Foundation.SitecoreExtensions" resolve="true" patch:source="CCO.Foundation.SitecoreExtensions.config" xmlns:patch="http://www.sitecore.net/xmlconfig/" />]
Sitecore.Configuration.DefaultFactory.CreateFromServiceProvider(XmlNode configNode, Boolean assert) +641
Sitecore.Configuration.DefaultFactory.CreateObject(XmlNode configNode, String[] parameters, Boolean assert, IFactoryHelper helper) +138
Sitecore.Configuration.DefaultFactory.CreateObject(XmlNode configNode, Boolean assert) +68
Sitecore.Pipelines.CorePipelineFactory.GetObjectFromType(XmlNode processorNode) +91
Sitecore.Pipelines.CorePipelineFactory.GetProcessorObject(XmlNode processorNode) +145
Sitecore.Pipelines.CoreProcessor.GetMethod(Object[] parameters) +136
Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +470
Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists) +236
Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain) +22
Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args) +195
Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args, Func`2 resultGetter) +161
Sitecore.Mvc.Pipelines.Response.BuildPageDefinition.ProcessXmlBasedLayoutDefinition.AddRenderings(PageDefinition pageDefinition, BuildPageDefinitionArgs args) +265
(Object , Object ) +14
Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +484
Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain, Boolean failIfNotExists) +236
Sitecore.Pipelines.DefaultCorePipelineManager.Run(String pipelineName, PipelineArgs args, String pipelineDomain) +22
Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args) +195
Sitecore.Mvc.Pipelines.PipelineService.RunPipeline(String pipelineName, TArgs args, Func`2 resultGetter) +161
Sitecore.Mvc.Presentation.PageContext.GetPageDefinition() +297
Sitecore.Mvc.Presentation.PageContext.get_PageDefinition() +31
Sitecore.Mvc.Presentation.PageContext.GetPageView() +126
Sitecore.Mvc.Presentation.PageContext.get_PageView() +31
Sitecore.Mvc.Controllers.SitecoreController.GetDefaultAction() +26
lambda_method(Closure , ControllerBase , Object[] ) +90
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +35
System.Web.Mvc.Async.<>c.<BeginInvokeSynchronousActionMethod>b__9_0(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +39
System.Web.Mvc.Async.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult) +70
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__11_0() +72
System.Web.Mvc.Async.<>c__DisplayClass11_1.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +387
System.Web.Mvc.Async.<>c__DisplayClass11_1.<InvokeActionMethodFilterAsynchronouslyRecursive>b__2() +387
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.<>c__DisplayClass3_6.<BeginInvokeAction>b__3() +50
System.Web.Mvc.Async.<>c__DisplayClass3_1.<BeginInvokeAction>b__5(IAsyncResult asyncResult) +39
Startup.cs:
using CCO.Foundation.SitecoreExtensions.Pipelines.GetXmlBasedLayoutDefinition;
using Microsoft.Extensions.DependencyInjection;
using Jabberwocky.Core.Caching;
namespace CCO.Foundation.SitecoreExtensions.App_Start
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(typeof(ICacheProvider), typeof(InsertCascadedRenderings));
}
}
}
被调用的类使用Jabberwocky ICacheProvider接口:
using System;
using Jabberwocky.Core.Caching;
using Jabberwocky.DependencyInjection.Autowire.Attributes;
namespace CCO.Foundation.SitecoreExtensions.Pipelines.GetXmlBasedLayoutDefinition
{
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Sitecore;
using Sitecore.Data.Fields;
using Sitecore.Data.Items;
using Sitecore.Diagnostics;
using Sitecore.Layouts;
using Sitecore.Mvc.Devices;
using Sitecore.Mvc.Pipelines.Response.GetXmlBasedLayoutDefinition;
using PageContext = Sitecore.Mvc.Presentation.PageContext;
using Extensions;
using Sitecore.Data;
[AutowireService]
public class InsertCascadedRenderings : GetXmlBasedLayoutDefinitionProcessor
{
private readonly ICacheProvider _cacheProvider;
public InsertCascadedRenderings(ICacheProvider cacheProvider)
{
_cacheProvider = cacheProvider;
}
public override void Process(GetXmlBasedLayoutDefinitionArgs args)
{
if (args?.Result == null) return;
Item item = PageContext.Current.Item;
Device device = PageContext.Current.Device;
if (item?.Parent == null || device == null) return;
if (Context.PageMode.IsNormal)
{
args.Result = _cacheProvider.GetFromCache($"CascadedRenderings:{item.ID}:{device.Id}",
() => MergeWithCascadedRenderings(args.Result, item, device));
}
else
{
args.Result = MergeWithCascadedRenderings(args.Result, item, device);
}
Log.Debug($"The result of merge is:\n{args.Result}");
}
protected virtual XElement MergeWithCascadedRenderings(XElement self, Item currentItem, Device device)
{
Assert.ArgumentNotNull(self, "self");
Assert.ArgumentNotNull(currentItem, "currentItem");
Assert.ArgumentNotNull(device, "device");
LayoutDefinition selfParsed = LayoutDefinition.Parse(self.ToString());
string deviceId = $"{{{device.Id.ToString().ToUpper()}}}";
DeviceDefinition selfDevice = selfParsed.GetDevice(deviceId);
var renderings = new List<RenderingDefinition>();
var pageRenderings = Enumerable.Empty<RenderingDefinition>();
Field layoutField = currentItem.Fields[FieldIDs.FinalLayoutField];
LayoutDefinition pageParsed = LayoutDefinition.Parse(LayoutField.GetFieldValue(layoutField));
DeviceDefinition pageDevice = pageParsed.GetDevice(deviceId);
if (pageDevice.Renderings != null)
{
pageRenderings = pageDevice.Renderings.Cast<RenderingDefinition>();
}
//start cascaded renderings from item parent and iterate up to home item
foreach (var ancestor in currentItem.Axes.GetAncestors().Reverse())
{
if(ancestor.Visualization.Layout == null)continue;
renderings.AddRange(GetItemRenderingDefinitions(ancestor, deviceId, pageRenderings));
}
//iterate through all renderings set to cascade
foreach (var rendering in renderings.Distinct(new RenderingDefinitionEqualityComparer()))
{
if (rendering == null)
{
continue;
}
//verify that each rendering only cascades once
if (!selfDevice.Renderings.Cast<RenderingDefinition>()
.Any(x => x.ItemID == rendering.ItemID
&& StringUtil.ExtractParameter("Cascade", x.Parameters ?? "") == "1"))
{
// we're inserting first due to page banners and heros that can be cascaded.
// these will (should?) always be the first components in body content
selfDevice.AddRendering(rendering);
}
}
return XDocument.Parse(selfParsed.ToXml()).Root;
}
/// <summary>
/// Get cascaded renderings defined on item
/// </summary>
/// <param name="item"></param>
/// <param name="deviceId"></param>
/// <returns></returns>
protected virtual IEnumerable<RenderingDefinition> GetItemRenderingDefinitions(Item item, string deviceId, IEnumerable<RenderingDefinition> pageRenderings)
{
Assert.ArgumentNotNull(item, "item");
Field layoutField = item.Fields[FieldIDs.FinalLayoutField];
LayoutDefinition parentParsed = LayoutDefinition.Parse(LayoutField.GetFieldValue(layoutField));
DeviceDefinition parentDevice = parentParsed.GetDevice(deviceId);
if (parentDevice.Renderings == null) return Enumerable.Empty<RenderingDefinition>(); // empty layout
var allRenderings = parentDevice.Renderings.Cast<RenderingDefinition>();
var cascadedRenderings = allRenderings.Where(r => StringUtil.ExtractParameter("Cascade", r.Parameters ?? string.Empty) == "1");
var allAddedRenderings = new List<RenderingDefinition>();
foreach (var rendering in cascadedRenderings)
{
rendering.Parameters = $"{rendering.Parameters}&Editable=0";
// all containers use dynamic placholders.
if (rendering.IsInDynamicPlaceholder())
{
var parentId = rendering.GetIdFromDynamicPlaceholder();
var parentRendering = allRenderings.FirstOrDefault(r => r.UniqueId == new ID(parentId).ToString());
var parentPageRendering = pageRenderings.FirstOrDefault(r => r.ItemID == parentRendering.ItemID);
if (parentPageRendering != null)
{
rendering.Placeholder = rendering.Placeholder.Replace(parentId, new Guid(parentPageRendering.UniqueId).ToString());
}
else
{
allAddedRenderings.Add(parentRendering);
}
}
allAddedRenderings.Add(rendering);
}
return allAddedRenderings;
}
}
public class RenderingDefinitionEqualityComparer : IEqualityComparer<RenderingDefinition>
{
public bool Equals(RenderingDefinition x, RenderingDefinition y)
{
return x?.ItemID == y?.ItemID;
}
public int GetHashCode(RenderingDefinition obj)
{
return obj?.ItemID?.GetHashCode() ?? 0;
}
}
}
我已经研究了好几天,尝试了所有发现的建议,但仍然无法解决此错误。我对使用DI很陌生。
谢谢。