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>()));
}
}