Search code examples
sitecoreglass-mappercoveo

Coveo.UI.Components.Models.IBaseComponentProperties.Id is not supported by SitecoreIdMapper


I'm new to Coveo Search integrated with Sitecore. I have an odd exception happening that I can't workout why it's happening. When navigating to a search page with Coveo components on it. I see this exception.

**The type Coveo.UI.Components.Models.IBaseComponentProperties on Coveo.UI.Components.Models.IBaseComponentProperties.Id is not supported by SitecoreIdMapper
Description: An unhandled exception occurred.**

Exception Details: System.NotSupportedException: The type Coveo.UI.Components.Models.IBaseComponentProperties on Coveo.UI.Components.Models.IBaseComponentProperties.Id is not supported by SitecoreIdMapper
Source Error:
Line 3:  
Line 4:  <div class="coveo-results-header">
Line 5:      @Html.Sitecore().CoveoDynamicPlaceholder("coveo-ui-results-header-section")
Line 6:  </div>
[NotSupportedException: The type Coveo.UI.Components.Models.IBaseComponentProperties on Coveo.UI.Components.Models.IBaseComponentProperties.Id is not supported by SitecoreIdMapper]
   Glass.Mapper.Sc.DataMappers.SitecoreIdMapper.Setup(DataMapperResolverArgs args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper.Sc\DataMappers\SitecoreIdMapper.cs:66
   Glass.Mapper.Pipelines.DataMapperResolver.Tasks.DataMapperStandardResolverTask.Execute(DataMapperResolverArgs args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\DataMapperResolver\Tasks\DataMapperStandardResolverTask.cs:30
   Glass.Mapper.Pipelines.<>c__DisplayClass9_1.<.ctor>b__1(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineRunner.cs:55
   Glass.Mapper.Pipelines.AbstractPipelineTask`1.Next(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineTask.cs:33
   Glass.Mapper.Pipelines.DataMapperResolver.Tasks.DataMapperAttributeResolverTask.Execute(DataMapperResolverArgs args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\DataMapperResolver\Tasks\DataMapperAttributeResolverTask.cs:34
   Glass.Mapper.Pipelines.<>c__DisplayClass9_0.<.ctor>b__0(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineRunner.cs:65
   Glass.Mapper.Pipelines.AbstractPipelineRunner`2.Run(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineRunner.cs:77
   Glass.Mapper.Context.ProcessProperties(IEnumerable`1 properties) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Context.cs:204
   Glass.Mapper.Context.Load(IConfigurationLoader[] loaders) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Context.cs:176
   Glass.Mapper.Pipelines.ConfigurationResolver.Tasks.OnDemandResolver.ConfigurationOnDemandResolverTask`1.Execute(ConfigurationResolverArgs args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\ConfigurationResolver\Tasks\OnDemandResolver\ConfigurationOnDemandResolverTask.cs:26
   Glass.Mapper.Pipelines.<>c__DisplayClass9_1.<.ctor>b__1(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineRunner.cs:55
   Glass.Mapper.Pipelines.AbstractPipelineTask`1.Next(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineTask.cs:33
   Glass.Mapper.Pipelines.AbstractPipelineTask`1.Execute(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineTask.cs:27
   Glass.Mapper.Pipelines.ConfigurationResolver.Tasks.StandardResolver.ConfigurationStandardResolverTask.Execute(ConfigurationResolverArgs args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\ConfigurationResolver\StandardResolver\ConfigurationStandardResolverTask.cs:23
   Glass.Mapper.Pipelines.<>c__DisplayClass9_1.<.ctor>b__1(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineRunner.cs:55
   Glass.Mapper.Pipelines.AbstractPipelineTask`1.Next(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineTask.cs:33
   Glass.Mapper.Pipelines.AbstractPipelineTask`1.Execute(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineTask.cs:27
   Glass.Mapper.Sc.Pipelines.ConfigurationResolver.TemplateInferredTypeTask.Execute(ConfigurationResolverArgs args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper.Sc\Pipelines\ConfigurationResolver\TemplateInferredTypeTask.cs:60
   Glass.Mapper.Pipelines.<>c__DisplayClass9_1.<.ctor>b__1(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineRunner.cs:55
   Glass.Mapper.Pipelines.AbstractPipelineTask`1.Next(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineTask.cs:33
   Glass.Mapper.Pipelines.AbstractPipelineTask`1.Execute(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineTask.cs:27
   Glass.Mapper.Sc.Pipelines.ConfigurationResolver.SitecoreItemResolverTask.Execute(ConfigurationResolverArgs args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper.Sc\Pipelines\ConfigurationResolver\SitecoreItemResolverTask.cs:36
   Glass.Mapper.Pipelines.<>c__DisplayClass9_0.<.ctor>b__0(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineRunner.cs:65
   Glass.Mapper.Pipelines.AbstractPipelineRunner`2.Run(T args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\Pipelines\AbstractPipelineRunner.cs:77
   Glass.Mapper.AbstractService.RunConfigurationPipeline(AbstractTypeCreationContext abstractTypeCreationContext) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\AbstractService.cs:163
   Glass.Mapper.AbstractService.InstantiateObject(AbstractTypeCreationContext abstractTypeCreationContext) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper\AbstractService.cs:126
   Glass.Mapper.Sc.SitecoreService.RunCreateType(Item item, GetOptions options, Dictionary`2 parameters) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper.Sc\SitecoreService.cs:349
   Glass.Mapper.Sc.SitecoreService.GetItem(GetItemOptions options) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper.Sc\SitecoreService.cs:338
   Glass.Mapper.Sc.Pipelines.Response.GetModelFromView.GetDataSourceItem(GetModelArgs args, Type modelType) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper.Sc.Mvc\Pipelines\Response\GetModelFromView.cs:174
   Glass.Mapper.Sc.Pipelines.Response.GetModelFromView.Process(GetModelArgs args) in D:\a\Glass.Mapper\Glass.Mapper\Source\Glass.Mapper.Sc.Mvc\Pipelines\Response\GetModelFromView.cs:82
   (Object , Object ) +54
   Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +1268
   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.Rendering.GetModel() +316
   Sitecore.Mvc.Presentation.Rendering.get_Model() +31
   Sitecore.Mvc.Extensions.ObjectExtensions.ValueOrDefault(T source, Func`2 resultGetter) +51
   Sitecore.Mvc.Presentation.ViewRenderer.get_Model() +163
   Sitecore.Mvc.Presentation.ViewRenderer.Render(TextWriter writer) +160

When I peek into the DLLs, I see the IBaseComponentProperties.cs looks like this

namespace Coveo.UI.Components.Models
{
  public interface IBaseComponentProperties
  {
    string Id { get; }

    string CssClass { get; }

    string PlaceholderId { get; }

    string ItemId { get; }

    bool HasDataSource { get; }
  }
}

This ID is a typeof string

When I peek at the SitecoreIdMapper.cs, I see this:

namespace Glass.Mapper.Sc.DataMappers
{
  public class SitecoreIdMapper : AbstractDataMapper
  {
    private Func<Item, object> _getValue;

    public SitecoreIdMapper() => this.ReadOnly = true;

    public override void MapToCms(AbstractDataMappingContext mappingContext) => throw new NotImplementedException();

    public override object MapToProperty(AbstractDataMappingContext mappingContext) => this._getValue(((SitecoreDataMappingContext) mappingContext).Item);

    public override void Setup(DataMapperResolverArgs args)
    {
      if (args.PropertyConfiguration.PropertyInfo.PropertyType == typeof (Guid))
        this._getValue = (Func<Item, object>) (item => (object) item.ID.Guid);
      else if (args.PropertyConfiguration.PropertyInfo.PropertyType == typeof (ID))
        this._getValue = (Func<Item, object>) (item => (object) item.ID);
      else
        throw new NotSupportedException("The type {0} on {0}.{1} is not supported by SitecoreIdMapper".Formatted((object) args.PropertyConfiguration.PropertyInfo.ReflectedType.FullName, (object) args.PropertyConfiguration.PropertyInfo.Name));
      base.Setup(args);
    }

    public override bool CanHandle(AbstractPropertyConfiguration configuration, Context context) => configuration is SitecoreIdConfiguration;
  }
}

So it seems the SitecoreIdMapper is expecting either a GUID or ID for the PropertyType, and since it's a string, it's falling into the else clause, where it throse the not supported exception..

Since Coveo for Sitecore, and GlassMapper for Sitecore are modules, and should be configurable. I'm sure there must be something I can configure to correct this? These are both very common modules, and surly this is something seen before?!

Can anyone point me in the right direction here?


Solution

  • After a while of scraping through the project. I found some custom code that was just passing the Coveo IBaseComponentProperty Object straight into the glass mapper. So the answer was to make sure that the type of type of GUID. Taking the string of the IBaseComponentProperty and newing up a GUID with the string data. Because coveo will store the GUID in that string.

    new Guid(CoveoObj.Id);

    Unfortunately, where this hand over between these models happens will differ per-project. So you will need to work that part out. But he answer is to make sure that string is parsed into a GUID. Otherwise the NotSupportedExpection will be triggered, when GlassMapper's reflection lookup fails.

    EDIT:

    3 months later I hit the same issue and found that someone had written in content in an field that you needed to select something. Normally after selecting something in the drop down, the GUID would be populated in the field, but since they manually wrote something in there, it was a string.

    The way I located this was by attaching to the mvc.getModel pipeline just before the Glass Mapper processes. Then logging out all the guids involved. I waited for the error to trigger, then looked back on the last log to locate the problem item's GUID. From there I searched in Sitecore and eye-balled the content until I worked out what it was.

    Additionally if you just 'republish' the /sitecore/layout/Renderings/Coveo Hive include related and subitems. (Not smart publish). It'll also correct the issue in some cases.