1
votes

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?
1
Do you have the stack trace?Michael Edwards
Here is the glass custom config class code: var attributes = new AttributeConfigurationLoader("x.Data"); return new IConfigurationLoader[] {attributes};chrishey
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.<LoadPropertiesFromType>d__2.MoveNext() +169chrishey
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.<Load>b__0(String assemblyName) +94 System.Linq.WhereSelectArrayIterator2.MoveNext() +82 System.Linq.Enumerable.Aggregate(IEnumerable1 source, Func`3 func) +123chrishey
This issue can happen if you have any classes with an indexer.Michael Edwards

1 Answers

1
votes

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