Umbraco 动态 "Where" 过滤器 returns IQueryable 或 DynamicPublishedContentList 不一致

Umbraco dynamic "Where" filter returns either IQueryable or DynamicPublishedContentList inconsistently

我正在尝试使用递归助手在 Umbraco 中创建一个多级下拉菜单,但出于某种原因,我收到一个编译错误,提示我在传递根的 children 时传递了错误的参数帮助程序的元素。

我找到了一些解决方案,但他们没有使用助手,所以我不知道问题出在助手上还是我做错了什么。

我的代码是:

 @inherits Umbraco.Web.Mvc.UmbracoTemplatePage
 @{ var selection = CurrentPage.Site().Children.Where("Visible"); }
 <div class="fleft menu_area">
     <button class="btn btn-primary visible-xs" type="button" data-     toggle="collapse" data-target="#mainMenu" aria-expanded="false" aria-   controls="mainMenu"> <i class="glyphicon glyphicon-th-large"></i> Menu </button>
     <div class="collapse navbar-collapse" id="mainMenu">
         <ul class="nav navbar-nav">
             @CreateListItems(selection)
         </ul>
     </div>
 </div>

 @helper CreateListItems(Umbraco.Web.Models.DynamicPublishedContentList  collection)
 {
     foreach (var item in collection)
     {
         if (item.Children.Where("Visible").Count() > 0)
         {
             <li class="menuOption dropdown  @(item.IsAncestorOrSelf(CurrentPage) ? "current" : null)" data-menu- id="@item.GetPropertyValue("menuOptionIdentifier")">
                 <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" href="@item.Url">@item.Name</a>
                 <ul class="dropdown-menu">
                     @{            
                    CreateListItems(item.Children.Where("Visible")); // THE PROBLEM IS HERE
                     }
                 </ul>
           </li>
          }
         else
         {
             <li class="@(item.IsAncestorOrSelf(CurrentPage) ? "current" : null)"><a href="@item.Url">@item.Name</a></li>
         }
     }
 }

我看到 item.Children.Where("Visible") 正在返回一个 iQueryable,所以我尝试将它分配给一个变量,并且该变量是正确的 DynamicPublishedContentList 类型。我将该变量传递给了助手,但我得到了同样的错误。

我尝试了另一个版本,在助手之外使用 foreachs,而不是传递 DynamicPublishedContentList 我传递了 DynamicPublishedContent 项目,但我也无法使其工作,我遇到了同样的错误。

我尝试将 Where 结果转换为列表,但我也收到错误消息,指出无法从 IQueryable does not contain a definition for 'ToList'

传递那些 children 的正确方法是什么?

有什么想法吗?

你是对的。问题是您正试图将 IQueryable 传递给 DynamicPublishedContentList。我只是将其全部切换为动态,因此您不必特别担心传递的内容。如果你打算使用动态,你最好避免处理所有的类型转换。

您从对 Where("Visible") 的调用中收到混合消息的原因是 dynamic 不仅仅是常规类型。它基本上标记编译器跳过所有类型检查,所以它发生在运行时。这意味着在运行时,您的动态将编译为对象。

事实证明,当您从显式 DynamicPublishedContentList 调用 .Where("Visible") 时,会调用 Umbraco.Web.PublishedContentExtensions 中的 .Where("Visible") 方法。但是,扩展方法不适用于动态,因为 C# RuntimeBinder 不允许您访问扩展方法。当我们在 CurrentPage.Site().Children 上调用 .Where("Visible") 时,它看不到扩展方法,并且会调用 DynamicPublishedContentList class 上覆盖的 TryInvokeMember 方法。

这可能是您最简单的解决方案:

@helper CreateListItems(Umbraco.Web.Models.DynamicPublishedContentList  collection)

@helper CreateListItems(dynamic collection)

或者,您可以使用更强类型的 IPublishedContent。我喜欢这个,因为额外的智能感知有很大帮助。

@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
@{
    var root = Model.Content.AncestorOrSelf(1);
    var selection = root.Children.Where(n => !n.GetPropertyValue<bool>("umbracoNaviHide")).ToList();
}

<div class="fleft menu_area">
    <button class="btn btn-primary visible-xs" type="button" data-     toggle="collapse" data-target="#mainMenu" aria-expanded="false" aria-   controls="mainMenu"> <i class="glyphicon glyphicon-th-large"></i> Menu </button>
    <div class="collapse navbar-collapse" id="mainMenu">
        <ul class="nav navbar-nav">
            @CreateListItems(selection)
        </ul>
    </div>
</div>

@helper CreateListItems(List<IPublishedContent> collection)
{
    foreach (var item in collection)
    {
        if (item.Children.Any(n => !n.GetPropertyValue<bool>("umbracoNaviHide")))
        {
            <li class="menuOption dropdown  @(item.IsAncestorOrSelf(Model.Content) ? "current" : null)" data-menu- id="@item.GetPropertyValue("menuOptionIdentifier")">
                <a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false" href="@item.Url">@item.Name</a>
                <ul class="dropdown-menu">
                    @CreateListItems(item.Children.Where(n => !n.GetPropertyValue<bool>("umbracoNaviHide")).ToList())
                </ul>
            </li>
        }
        else
        {
            <li class="@(item.IsAncestorOrSelf(Model.Content) ? "current" : null)"><a href="@item.Url">@item.Name</a></li>
        }
    }
}

您可以使用 Model.Content.

获取当前页面作为 IPublishedContent