在PageEditor模式下Sitecore的Glass映射器中的异常

时间:2013-09-09 12:51:56

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

代码:

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

此处mainlinkitem是为数据模板创建的界面的Navigation对象。 我在这种情况下使用接口,而windsor为此创建了动态代理对象。

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

  

表达式不会评估成员   x.NavigationItem.Url.StringToLink()at   Glass.Mapper.Sc.GlassHtml.MakeEditable [T](表达式1 field, Expression 1 standardOutput,T模型,字符串参数,上下文   context,Database database,TextWriter writer)

注意:StringToLink是将string表单中的外部网址转换为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();
    }
}

glass glassper的导航文件夹界面:

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

glass mapper的Navigation Link界面:

[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; }
}

2 个答案:

答案 0 :(得分:0)

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

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

答案 1 :(得分:0)

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

但是我没有对此进行测试,而是应该将属性更新为“链接”字段类型,它会自动映射它:

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

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

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