1

I am using solution with (the latest for today) Glass Mapper 5.8.173 along with Sitecore 10.0 update 1, where I have upgraded the whole large solution from old Sitecore 8.2 and Glass Mapper 4.

I have a temporal setup used for upgrade, with both old and new instances running in parallel against the same databases (those been updated to 10.0 already, but perfectly work for older versions).

For the example of problem, I take main navigation panel at the top of each page, perfectly works on old solution, however not showing up on the updated one.

So digging deeper I noticed having a problem with inherited models. Will try to explain what I mean below:

There is a view to show the menu items and children of 3-level depth, the code looks as:

ul class="main-nav__list">
    @RenderMenu(Model, 3)
</ul>

@helper RenderMenu(NavDatasource datasource, int maxDepth = 1)
{
    foreach (var defn in datasource.Children)
    {
        @RenderDefinition(defn, maxDepth)
    }
}

When I watch the above code in debugger, Model comes of the right type but with many properties on lower hierarchies levels as null, while top level mapped properties get correctly. I also know the rendering is getting cached so clean cache each time.

The inheritance comes as:

    [SitecoreType(TemplateId = "{SOME-EXISTING-GUID}", AutoMap = true)]
    public partial class NavDatasource : NavLink
    {
    }

    [SitecoreType(TemplateId = "{ANOTHER-VALID-GUID}", AutoMap = true)]
    public partial class NavLink : CoreDataItem, INavDefn, ICss
    {
        [SitecoreField(UrlOptions = SitecoreInfoUrlOptions.SiteResolving)]
        public virtual Link Link { get; set; }

        public virtual CssItem Icon { get; set; }

        public virtual string Css1 { get; set; }
        public virtual string Css2 { get; set; }
        public virtual string LanguageAttribute { get; set; }

        public virtual SvgItem SvgIcon { get; set; }
    }

    [SitecoreType(TemplateId = "{HIGHER-LEVEL-GUID}", AutoMap = true)]
    public partial class CoreDataItem : CoreInferred, ICoreDataItem
    {
        private readonly SitecoreService _sitecoreService;
        protected IRequestContext RequestContext { get; }

        public CoreDataItem()
        {
            _sitecoreService = new SitecoreService(Sitecore.Context.Database);
            RequestContext = new RequestContext(_sitecoreService);
        }

        [SitecoreParent(InferType = true)]
        public virtual CoreInferred Parent { get; set; }

        [SitecoreItem]
        public virtual Item Item { get; set; }

        [SitecoreChildren(InferType = true)]
        public IEnumerable<CoreInferred> InnerChildren { get; set; }

        private List<CoreDataItem> _children;
        [SitecoreIgnore]
        public List<CoreDataItem> Children {
            get {
                if (_children != null)
                    return _children;
                _children = InnerChildren == null ? new List<CoreDataItem>() : InnerChildren.OfType<CoreDataItem>().ToList();
                return _children;
            }
            set {
                InnerChildren = _children = value;
            }
        }

        [SitecoreIgnore]
        public ItemPath Paths => InnerItem.Paths;
    }

    [SitecoreType(TemplateId = "{GUID}", AutoMap = true)]
    public partial class CoreInferred : CoreGlass, ICoreInferred
    {

        [IndexField("_template")]
        [TypeConverter(typeof(IndexFieldIDValueConverter))]
        public virtual ID TemplateId { get; set; }

        [IndexField("_name")]
        public virtual String Name { get; set; }

        [SitecoreInfo(SitecoreInfoType.DisplayName)]
        public virtual String InternalDisplayName { get; set; }

        [SitecoreItem]
        public virtual Item InnerItem { get; set; }

        [SitecoreIgnore]
        public String DisplayName
        {
            get
            {
                if (String.IsNullOrEmpty(InternalDisplayName))
                    return Name;

                return InternalDisplayName;
            }
            set { InternalDisplayName = value;}
        }
                
        [Obsolete("Use InnerItem property instead",false)]
        public Item AsItem()
        {
            return InnerItem;
        }
    }

So what, I am getting some CoreDataItem properties get mapped correctly but others not. Namely, Children comes up as an empty list as InnerChildren is null.

What else should I mention? These classes are located in different projects (DLLs), and that could potentially affect: NavDatasource and NavLink and located within Platform.Feature.Foundation and others are within Platform.Foundation.Glass itself. Taking a look at ShowConfig.aspx shows me:

<foundation patch:source="Foundation.Glass.config">
  <glass>
    <map hint="Platform.Foundation.Glass" dll="Platform.Foundation.Glass"/>
    <map hint="Platform.Foundation.Location" dll="Platform.Foundation.Location" patch:source="Platform.Foundation.Location.config"/>
    <map hint="Platform.Feature.Navigation" dll="Platform.Feature.Navigation" patch:source="Feature.Navigation.Glass.config"/>
  </glass>
</foundation>

Also worth mentioning that Resolver is a default one, as it comes:

    public static  class GlassMapperScCustom
    {
        public static IDependencyResolver CreateResolver(){
            var config = new GM.Sc.Config();

            //config.OnDemandMappingEnabled = true; // tried that with no luck
            var dependencyResolver = new DependencyResolver(config);

            // Tried that as well assuming ITEM VERSION COUNT TASK affects children
            //dependencyResolver.ObjectConstructionFactory.Replace<ItemVersionCountByRevisionTask, ItemVersionCountTask>(() => new ItemVersionCountTask());
            
            return dependencyResolver;
        }
        /// the rest of class go here as comes by default (therefore skipped)
}

DI is also registered, as normal:

    public class ServicesConfigurator : IServicesConfigurator
    {
        public void Configure(IServiceCollection serviceCollection)
        {
            serviceCollection.AddScoped<ISitecoreService>(sp => new SitecoreService(Context.Database));
            serviceCollection.AddScoped<IMvcContext>(sp => new MvcContext(sp.GetService<ISitecoreService>()));
            serviceCollection.AddScoped<IRequestContext>(sp => new RequestContext(sp.GetService<ISitecoreService>()));
        }
    }
2

Eventually, with the helps of senior colleagues I came across the correct answer that works it out.

The virtual modifier was missing in the code (not sure then how it worked in 8.2 with Glass 4 in that case). The correct property looks as:

[SitecoreChildren(InferType = true)]
public virtual IEnumerable<CoreInferred> InnerChildren { get; set; }

After recompilation, this and another properties got mapped.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.