【问题标题】:Exception in Glass mapper for Sitecore in PageEditor modePageEditor 模式下 Sitecore 的 Glass 映射器异常
【发布时间】:2013-09-09 12:51:55
【问题描述】:

代码:

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

这里mainlinkitem 是为数据模板创建的界面的导航对象。 在这种情况下,我正在使用接口,并且 Castle Windsor 为此创建了动态代理对象。

在我尝试使用页面编辑器模式并从 glass mapper api 显示以下错误之前一切正常。

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

注意:StringToLink 是将string 形式的外部url 转换为Glass mapper 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; }
}

【问题讨论】:

  • 如果您在调用 RenderLink() 时设置了 isEditable: false,页面编辑器是否工作?我们可以看看 RenderLink() 的代码吗?
  • RenderLink 方法来自 glass mapper 库,我的用户控件继承自 GlassUserControl&lt;T&gt; 类,其中 T 是我的模型表示数据模板
  • URL属性的配置是什么?
  • @MichaelEdwards 我已经更新了有关 URL 属性详细信息的问题。

标签: c# .net sitecore page-editor glass-mapper


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    扩展方法不是类的“真正”扩展,它们在编译时被解析。在没有看到其余代码的情况下,指出如何重写代码以解决此问题并不容易。我建议类似:

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

    【讨论】:

    • 你发布的代码是一样的,没有扩展方法..它不能解决任何问题..我会在几分钟内详细发布代码......我在页面编辑器模式下有问题,事情在正常模式下工作
    • 顺便说一句,我也尝试了非扩展方法,但存在相同的错误。我已经反编译了玻璃映射器程序集,代码抛出异常是if (!(field.Body is MemberExpression)) { throw new MapperException("Expression doesn't evaluate to a member {0}".Formatted(new object[] { field.Body })); }
    猜你喜欢
    • 2015-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多