How to enable VersionCountDisabler for Glass Mapper in Sitecore for SitecoreQuery and SitecoreChildren attributes

拈花ヽ惹草 提交于 2019-12-12 06:58:22

问题


The glass mapper will return null object or (no items) for SitecoreQuery and SitecoreChildren attribute that are placed on the GlassModels. These attributes don't take any such parameter where I can specify them to return items if they don't exist in the the context lanaguge. The items e.g. exist in EN but don't exist in en-ES. I need to put a lot of null check in my views to avoid Null exception and makes the views or controller very messy. It is lot of boiler plate code that one has to write to make it work. In Page Editor the SitecoreChildren returns item and content authors can create items in that langauge version by editing any field on the item. This automatically creates the item in that langauge. However the same code will fail in Preview mode as SitecoreChidren will return null and you see null pointer exception. SitecoreQuery doesn't return any items in page editor and then Content Authors wont be able to create items in Page editor. To make the experience good if we can pass a parameter to SiteocreQuery attribute so it disable VsersionCount and returns the items if they dont exist in that langauge.


回答1:


This is actually not possible. There is an issue on GitHub which would make it easy to create a custom attribute to handle this very easy. Currently you need to create a new type mapper and copy all the code from the SitecoreQueryMapper. I have written a blog post here about how you can create a custom type mapper. You need to create the following classes (example for the SitecoreQuery).

New configuration:

public class SitecoreSharedQueryConfiguration : SitecoreQueryConfiguration
{
}

New attribute:

public class SitecoreSharedQueryAttribute : SitecoreQueryAttribute
{
    public SitecoreSharedQueryAttribute(string query) : base(query)
    {
    }

    public override AbstractPropertyConfiguration Configure(PropertyInfo propertyInfo)
    {
        var config = new SitecoreSharedQueryConfiguration();
        this.Configure(propertyInfo, config);
        return config;
    }
}

New type mapper:

public class SitecoreSharedQueryTypeMapper : SitecoreQueryMapper
{
    public SitecoreSharedQueryTypeMapper(IEnumerable<ISitecoreQueryParameter> parameters)
        : base(parameters)
    {
    }

    public override object MapToProperty(AbstractDataMappingContext mappingContext)
    {
        var scConfig = Configuration as SitecoreQueryConfiguration;
        var scContext = mappingContext as SitecoreDataMappingContext;

        using (new VersionCountDisabler())
        {
            if (scConfig != null && scContext != null)
            {
                string query = this.ParseQuery(scConfig.Query, scContext.Item);

                if (scConfig.PropertyInfo.PropertyType.IsGenericType)
                {
                    Type outerType = Glass.Mapper.Sc.Utilities.GetGenericOuter(scConfig.PropertyInfo.PropertyType);

                    if (typeof(IEnumerable<>) == outerType)
                    {
                        Type genericType = Utilities.GetGenericArgument(scConfig.PropertyInfo.PropertyType);

                        Func<IEnumerable<Item>> getItems;
                        if (scConfig.IsRelative)
                        {
                            getItems = () =>
                                {
                                    try
                                    {
                                        return scContext.Item.Axes.SelectItems(query);
                                    }
                                    catch (Exception ex)
                                    {
                                        throw new MapperException("Failed to perform query {0}".Formatted(query), ex);
                                    }
                                };
                        }
                        else
                        {
                            getItems = () =>
                                {
                                    if (scConfig.UseQueryContext)
                                    {
                                        var conQuery = new Query(query);
                                        var queryContext = new QueryContext(scContext.Item.Database.DataManager);

                                        object obj = conQuery.Execute(queryContext);
                                        var contextArray = obj as QueryContext[];
                                        var context = obj as QueryContext;

                                        if (contextArray == null)
                                            contextArray = new[] { context };

                                        return contextArray.Select(x => scContext.Item.Database.GetItem(x.ID));
                                    }

                                    return scContext.Item.Database.SelectItems(query);
                                };
                        }

                        return Glass.Mapper.Sc.Utilities.CreateGenericType(typeof(ItemEnumerable<>), new[] { genericType }, getItems, scConfig.IsLazy, scConfig.InferType, scContext.Service);
                    }

                    throw new NotSupportedException("Generic type not supported {0}. Must be IEnumerable<>.".Formatted(outerType.FullName));
                }

                {
                    Item result;
                    if (scConfig.IsRelative)
                    {
                        result = scContext.Item.Axes.SelectSingleItem(query);
                    }
                    else
                    {
                        result = scContext.Item.Database.SelectSingleItem(query);
                    }

                    return scContext.Service.CreateType(scConfig.PropertyInfo.PropertyType, result, scConfig.IsLazy, scConfig.InferType, null);
                }
            }
        }

        return null;
    }

    public override bool CanHandle(AbstractPropertyConfiguration configuration, Context context)
    {
        return configuration is SitecoreSharedQueryConfiguration;
    }
}

And configure the new type mapper in your glass config (mapper and parameters for the constructor):

container.Register(Component.For<AbstractDataMapper>().ImplementedBy<SitecoreSharedQueryTypeMapper>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemPathParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemIdParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemIdNoBracketsParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemEscapedPathParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemDateNowParameter>>().LifeStyle.Transient);

You can then simply change the SitecoreQuery attribute on your model to SitecoreSharedQuery:

[SitecoreSharedQuery("./*")]
public virtual IEnumerable<YourModel> YourItems { get; set; }

For the children you could either use the shared query mapper and querying the children or create the same classes for a new SitecoreSharedChildren query.

Edit: Added bindings for IEnumerable<ISitecoreQueryParameter> as they are missing and therefor it threw an error.



来源:https://stackoverflow.com/questions/26637652/how-to-enable-versioncountdisabler-for-glass-mapper-in-sitecore-for-sitecorequer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!