页面编辑器模式下 Sitecore 的玻璃映射器中的异常

本文关键字:玻璃 映射 异常 Sitecore 编辑器 模式 | 更新日期: 2023-09-27 18:30:37

对于代码:

strMenuText.Append(RenderLink(mainlinkitem, 
        x => x.NavigationItem.Url.StringToLink(), 
        isEditable: true,            
        contents: mainlinkitem.NavigationTitle));

这里mainlinkitem是为数据模板创建的接口的导航对象。在这种情况下,我正在使用接口,温莎城堡为此创建了动态代理对象。

一切正常,直到我尝试使用页面编辑器模式,并且玻璃映射器 API 出现以下错误。

表达式不计算成员 x.NavigationItem.Url.StringToLink() at Glass.Mapper.Sc.GlassHtml.MakeEditable[T](表达式 1 field, Expression 1 标准输出, T 模型, 字符串参数, 上下文 上下文、数据库数据库、文本编写器)

注意:StringToLink是将string形式的外部URL转换为玻璃映射器Glass.Mapper.Sc.Fields.Link类型的扩展方法。

public static Link StringToLink(this string urlvalue)
{
    Link itemLink = new Link();
    itemLink.Url = urlvalue;
    return itemLink;
}

更新

菜单用户控件的代码:

public partial class MenuControl : GlassUserControl<INavigationFolder>
{
    protected override void GetModel()
    {
        base.GetModel();
        SiteLevelSettings siteSettings = SitecoreContext.GetItem<SiteLevelSettings>(Guid.Parse("Some GUID"));
        Model = siteSettings.HeaderMenuFolder;
    }
    protected void Page_Load()
    {
        if (!Page.IsPostBack)
        {
            LoadMenu();
        }
    }
    private void LoadMenu()
    {
        StringBuilder strMenuText = new StringBuilder();
        foreach (INavigationLink mainlinkitem in Model.ChildLinks)
        {
            if (CanRead(mainlinkitem))
            {
                strMenuText.Append("<td class='menu-item'>");
                if (mainlinkitem.ChildLinks != null && mainlinkitem.ChildLinks.Count() > 0)
                {
                    strMenuText.Append("<ul>");
                    foreach (INavigationLink linkitem in mainlinkitem.ChildLinks)
                    {
                        if (CanRead(linkitem))
                        {
                            strMenuText.Append("<li>");
                            if (linkitem.NavigationItem != null)
                            {
                                strMenuText.Append(RenderLink(linkitem, x => x.NavigationItem.Url.StringToLink(), isEditable: false, contents: linkitem.NavigationTitle));
                            }
                            else if (linkitem.NavigationGeneralLink != null)
                            {
                                strMenuText.Append(RenderLink(linkitem, x => x.NavigationGeneralLink, isEditable: false, contents: linkitem.NavigationTitle));
                            }
                            strMenuText.Append("</li>");
                        }
                    }
                    strMenuText.Append("</ul>");
                }
                strMenuText.Append("<div class='nav-divider'>");
                if (mainlinkitem.NavigationItem != null)
                {
                    strMenuText.Append(RenderLink(mainlinkitem, x => x.NavigationItem.Url.StringToLink(), isEditable: false, contents: mainlinkitem.NavigationTitle));
                }
                else if (mainlinkitem.NavigationGeneralLink != null)
                {
                    strMenuText.Append(RenderLink(mainlinkitem, x => x.NavigationGeneralLink, isEditable: true, contents: mainlinkitem.NavigationTitle));
                }
                strMenuText.Append("</div></td>");
            }
        }
        ltrMenu.Text = strMenuText.ToString();
    }
    private bool CanRead(IItem mainlinkitem)
    {
        var ItemId = mainlinkitem.TemplateId;
        var ItemIDObj = new Sitecore.Data.ID(ItemId);
        var contentdatabase = Sitecore.Context.Database;
        var item = contentdatabase.GetItem(ItemIDObj);
        return item.Access.CanRead();
    }
}

玻璃映射仪的导航文件夹界面:

[SitecoreType(TemplateId = "{Some GUID}")]
public interface INavigationFolder : IItem
{
    [SitecoreChildren(IsLazy = false)]
    IEnumerable<INavigationLink> ChildLinks { get; set; }
}

玻璃测绘仪导航链接接口:

[SitecoreType(TemplateId = "{Some GUID}")]
public interface INavigationLink : IItem
{
    [SitecoreField(FieldId = "{Some GUID}")]
    string NavigationTitle { get; set; }
    [SitecoreField(FieldId = "{Some GUID}")]
    IItem NavigationItem { get; set; }
    [SitecoreField(FieldId = "{Some GUID}")]
    Link NavigationGeneralLink { get; set; }
    [SitecoreField(FieldId = "{Some GUID}")]
    string ShortDescription { get; set; }
    [SitecoreChildren(IsLazy = false)]
    IEnumerable<INavigationLink> ChildLinks { get; set; }
}

注意:这将代码生成类似于 sitecore 网站的菜单

更新

接口 IItem 中的 url 属性定义如下:

[SitecoreType(TemplateId = "{Some GUID}")]
public interface IItem
{
    [SitecoreId()]
    Guid ID { get; }
    [SitecoreInfo(Type = SitecoreInfoType.Language)]
    Language Language { get; }
    [SitecoreInfo(Type = SitecoreInfoType.Version)]
    int Version { get; }
    [SitecoreInfo(Type = SitecoreInfoType.Url)]
    string Url { get; }
    [SitecoreInfo(Type = SitecoreInfoType.TemplateId)]
    Guid TemplateId { get; }
    [SitecoreInfo(Type = SitecoreInfoType.Key)]
    string Key { get; }
}

页面编辑器模式下 Sitecore 的玻璃映射器中的异常

RenderLink 方法中的第二个表达式应解析为表示您希望在页面编辑器中可编辑的字段的属性,例如:

RenderLink(linkitem, x => x.NavigationItem.Url, isEditable: false, contents: linkitem.NavigationTitle));

将附加方法调用添加到表达式的末尾时,Glass.Mapper 无法计算要正确编辑的字段。

相反,如果你想做这样的事情,你可能应该使用 if 语句在两个渲染之间切换:

        if (IsInEditingMode)
        {
            strMenuText.Append(RenderLink(
                linkitem,
                x => x.NavigationItem.Url
                isEditable: false,
                contents: linkitem.NavigationTitle));
        }
        else
        {
            strMenuText.Append(RenderLink(
                linkitem,
                x => x.NavigationItem.Url.StringToLink(),
                isEditable: false,
                contents: linkitem.NavigationTitle));
        }

但是我还没有对此进行测试,相反,您应该将您的属性更新为 Link 字段类型,它会自动映射它:

  [SitecoreField]
  public virtual Glass.Mapper.Sc.Fields.Link Url{get;set;}

然后,您可以将菜单代码更新为:

            strMenuText.Append(RenderLink(
                linkitem,
                x => x.NavigationItem.Url
                isEditable: false,
                contents: linkitem.NavigationTitle));

扩展方法不是类的"真正"扩展,它们在编译时解析。如果不看到代码的其余部分,指出如何重写代码以解决此问题并不容易。我建议像这样:

public static Link MakeLink(string urlvalue)
{
    Link itemLink = new Link();
    itemLink.Url = urlvalue;
    return itemLink;
}

然后在您的调用代码中

strMenuText.Append(RenderLink(mainlinkitem, 
        x => MakeLink( x.NavigationItem.Url ), 
        isEditable: true,            
        contents: mainlinkitem.NavigationTitle));