1

I am using the Glass Mapper on a Sitecore instance where I have a basic data template structure of

  • Base
    • BaseWithList
    • BaseWithExtraContent
      • BaseWithExtraContentAndCallToActionLink

I have added model classes in my project to follow this structure too. My class names match my template names.

[SitecoreType(TemplateId = "{5D19BD92-799E-4DC1-9A4E-1DDE3AD68DAD}", AutoMap = true)]
public class Base
{
   public virtual string Title {get;set;}
   public virtual string Content {get;set;}
}

[SitecoreType(TemplateId = "{0491E3D6-EBAA-4E21-B255-80F0607B176D}", AutoMap = true)]
public class BaseWithExtraContent : Base
{
    public virtual string ExtraContent {get;set;}
}

[SitecoreType(TemplateId = "{95563412-7A08-46A3-98CB-ABC4796D57D4}", AutoMap = true)]
public class BaseWithExtraContentAndCallToActionLink : BaseWithExtraContent
{
    public virtual string CallToActionLink {get;set;}
}

These data models are used from another class that has a list of base type, I want to be able to store any derived type in here so I added attributes as detailed in this tutorial

[SitecoreType(AutoMap = true)]
public class HomePage
{
    [SitecoreChildren(InferType = true)]
    [SitecoreField(FieldName = "Widgets")]
    public virtual IEnumerable<Base> Widgets { get; set; }
}

According to the tutorial this should work. However the list of widget just contains class of the base type.

I then found a later tutorial that said that if you have separated out the models to a different assemblies than the one Glass is installed in you have to add an AttributeConfigurationLoader pointing to the assembly your models are in. The base and derived types are all in the same assembly so I wasn't sure this would solve the issue, but I tried it anyway.

My custom loader config looks like this:

public static  class GlassMapperScCustom
{
    public static void CastleConfig(IWindsorContainer container)
    {
        var config = new Config {UseWindsorContructor = true};

        container.Install(new SitecoreInstaller(config));
    }

    public static IConfigurationLoader[] GlassLoaders()
    {

        var attributes = new AttributeConfigurationLoader("Project.Data");

        return new IConfigurationLoader[] {attributes};
    }
    public static void PostLoad(){
        //Remove the comments to activate CodeFist
        /* CODE FIRST START
        var dbs = Sitecore.Configuration.Factory.GetDatabases();
        foreach (var db in dbs)
        {
            var provider = db.GetDataProviders().FirstOrDefault(x => x is GlassDataProvider) as GlassDataProvider;
            if (provider != null)
            {
                using (new SecurityDisabler())
                {
                    provider.Initialise(db);
                }
            }
        }
         * CODE FIRST END
         */
    }
}

Upon doing the custom loader config I now get an "Ambiguous match found" exception. I have checked to see if there are any other non Glass attributes set in the classes in that assembly and there aren't.

Any ideas? I guess there are 2 questions.

  1. Why does using the inferred type attribute not load the correct types and only the base types?
  2. Why when I attempt to solve this by adding a custom attribute loader do I get the exception?
chrishey
  • 451
  • 6
  • 11
  • Do you have the stack trace? – Michael Edwards Jul 24 '14 at 08:13
  • Here is the glass custom config class code: var attributes = new AttributeConfigurationLoader("x.Data"); return new IConfigurationLoader[] {attributes}; – chrishey Jul 24 '14 at 19:52
  • the stack trace is too long to post in full: [AmbiguousMatchException: Ambiguous match found.] System.RuntimeType.GetPropertyImpl(String name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers) +13922767 System.Type.GetProperty(String name) +65 Glass.Mapper.Utilities.GetProperty(Type type, String name) +330 Glass.Mapper.Utilities.GetAllProperties(Type type) +710 Glass.Mapper.Configuration.Attributes.d__2.MoveNext() +169 – chrishey Jul 24 '14 at 20:04
  • Glass.Mapper.Configuration.Attributes.AttributeTypeLoader.LoadType(Type type) +641 Glass.Mapper.Configuration.Attributes.AttributeTypeLoader.Load() +100 Glass.Mapper.Configuration.Attributes.AttributeConfigurationLoader.LoadFromAssembly(Assembly assembly) +391 Glass.Mapper.Configuration.Attributes.AttributeConfigurationLoader.b__0(String assemblyName) +94 System.Linq.WhereSelectArrayIterator`2.MoveNext() +82 System.Linq.Enumerable.Aggregate(IEnumerable`1 source, Func`3 func) +123 – chrishey Jul 24 '14 at 20:04
  • Glass.Mapper.Configuration.Attributes.AttributeConfigurationLoader.Load() +273 Glass.Mapper.Context.b__0(IConfigurationLoader loader) +76 System.Linq.WhereSelectArrayIterator`2.MoveNext() +82 System.Linq.Enumerable.Aggregate(IEnumerable`1 source, Func`3 func) +123 Glass.Mapper.Context.Load(IConfigurationLoader[] loaders) +396 – chrishey Jul 24 '14 at 20:05
  • Those are the exact classes you use? Looking at Glass source on Utilities.GetProperty and the AmbiguousMatchException is catched before trying to load the property from interfaces but I do not see Interfaces in your example. – RvanDalen Jul 24 '14 at 22:07
  • 1
    This issue can happen if you have any classes with an indexer. – Michael Edwards Jul 25 '14 at 07:33
  • Indexer? Like an ienumerable or list? – chrishey Jul 27 '14 at 20:13
  • @RvanDalen - yes, the structure is the same, obviously the names aren't. I have attributes on some properties where the property name is more than 1 word. This is relates to the Sitecore field name. I haven't used interfaces anywhere. – chrishey Jul 28 '14 at 09:38
  • I realised I was using inferred types, so tried the attributes in this tutorial - http://glass.lu/docs/tutorial/sitecore/tutorial17/tutorial17.html. This didn't changed anything, everything is still coming back as the base type. – chrishey Jul 29 '14 at 09:39
  • So the ambiguous exception is gone? maybe update your question, now we have to read all comments to figure out the problem/question. As I understand, you use infertype but baseclass is loaded/returned. The TemplateInferredTypeTask will try to find a TypeConfiguration with a matching templateId, so this means that you have an item with a templateId but no matching typeconfiguration. Things to rule out: templates are published, correct template id's are configured, all typeconfigurations are loaded. And to be complete: could you post how you get the item? – RvanDalen Jul 30 '14 at 05:40

1 Answers1

1

Widgets property has two attributes - it's either mapped to the children elements of the item, or a field, can't be both.

Zenima
  • 380
  • 2
  • 14