在c#中通过路径获取Umbraco节点(语言切换)

发布于 2024-09-24 14:09:38 字数 514 浏览 0 评论 0原文

我有一个具有以下结构的多语言网站:

siteroot
- en
-- home
-- login
-- etc.
- de
-- home
-- login
-- etc. 

语言节点下的内容不一定相同。 当切换语言时,我想测试是否存在并行语言节点。

目前我正在执行以下操作:

  • 获取当前路径
  • 替换路径的语言部分 例如,将 /en/login 替换为 /de/login
  • 我发现最接近测试页面存在的方法是: XPathNodeIterator i = umbraco.library.GetXmlDocumentByUrl("http://localhost/de/login");

调试显示,umbraco 实际上访问了数据库。这不是测试页面是否存在的最佳方法。

有人有更好的方法吗?

I have a multi language site with the following structure:

siteroot
- en
-- home
-- login
-- etc.
- de
-- home
-- login
-- etc. 

The content beneath the language nodes is not necessarily the same.
When switching languages I want to test if a parallel language node exists.

Currently I'm doing the following:

  • get current path
  • replace the language part of path
    e.g. replace /en/login to /de/login
  • the closest I've found to test the existence of a page is:
    XPathNodeIterator i = umbraco.library.GetXmlDocumentByUrl("http://localhost/de/login");

Debugging this shows, that umbraco actually hits the database. This can't be the best way to test the existence of a page.

Anybody have a better method at hand?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

药祭#氼 2024-10-01 14:09:38

通过声音您可以使用 cms.businesslogic.web 命名空间中的文档类。此类用于修改/发布 umbraco 内部的节点。

尝试使用驻留在 umbraco.presentation.nodeFactory 中的节点类。这将仅与内存中的 XML 缓存交互。

Node.GetCurrent() //static method - will give you the current loaded page.
Node.Parent //class property - will give parent method

节点类的问题是它不能接受 XPath 查询(并且不会提供性能),

我编写了一个动态 Linq 提供程序,可用于使用编译的 xslt 表达式查询 Umbraco XML 结构。我将在下周左右发布。如果您有兴趣,请告诉我...

By the sounds your using the document class in cms.businesslogic.web namespace. This class is used for modifying/publishing nodes inside of umbraco.

Try using the node class that resides in umbraco.presentation.nodeFactory. This will interact with the in-memory XML cache only.

Node.GetCurrent() //static method - will give you the current loaded page.
Node.Parent //class property - will give parent method

The problem with the node class, that it can't take XPath queries (and will not give performance)

I've written a dynamic Linq provider that can be used to query the Umbraco XML structure using compiled xslt expressions. I going to be publishing in the next week or so. Let me know if your interested...

彩虹直至黑白 2024-10-01 14:09:38

我们有一个多语言网站,我们需要执行相同的操作来设置 hreflang 标签。可能有更好的方法,但我决定构建一些 Xpath 来查找其他语言中是否存在匹配的节点。我们正在使用 umbraco 7,如果可能的话,我会避免使用 NodeFactory。它已折旧。使用 umbraco 帮助程序不会访问数据库,并且是从 umbraco 7 查询已发布内容或媒体的最佳方法之一。

public static IPublishedContent GetLocalizedVersionOfPage(this IPublishedContent node, string regionName)
{
    var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
    var ancestorNames = node.AncestorsOrSelf()
                            .Where(n => n.Level > 1)
                            .OrderBy(n => n.Level)
                            .Select(n => n.Name).ToList();

    var xpath = new StringBuilder();
    xpath.AppendFormat("/root/HomePage[@nodeName='{0}']", regionName);
    foreach (var ancestorName in ancestorNames)
    {
        xpath.AppendFormat("/*[@nodeName='{0}']", ancestorName);
    }

    var matchingNode = umbracoHelper.TypedContentAtXPath(xpath.ToString()).FirstOrDefault();
    return matchingNode;
}

上述方法是 IPublishedContent 上的扩展方法。它允许您传入区域,并检查指定区域中是否存在具有由节点名称确定的相同路径的节点。我考虑过使用 urlname 而不是节点名称。您也可以这样做,甚至可以通过跳过执行 .AncestorsOrSelf() 的代码段来加快速度。这仅取决于您希望它如何工作。就我而言,即使 url 路径不同,我也希望它能够根据节点名称找到匹配项,因此我必须执行 .AncestorsOrSelf()。希望这有帮助。

另一件需要考虑的事情是如何调用这个方法。如果您使用这样的循环:

@foreach (var region in Umbraco.TypedContentAtRoot().Where(n => n.IsDocumentType("HomePage")))
{
    var localizedVersion = currentPage.GetLocalizedVersionOfPage(region.Name);
    if (localizedVersion != null)
    {
        <link rel="alternate" href="@localizedVersion.UrlAbsolute()" hreflang="@LocalizeUtils.GetCulture(region.Name)" />
    }
}

您最终将为每个区域一遍又一遍地获取当前节点的祖先,因为每次调用 GetLocalizedVersionOfPage() 时它都会调用 .AncestorsOrSelf()。重构 GetLocalizedVersionOfPage 方法可能是有意义的,这样您只需调用 .AncestorsOrSelf 一次。如果您多次执行此类操作,就会开始影响性能(尤其是当您的网站非常嵌套时)。

We have a multilingual site where we needed to do the same thing to set up our hreflang tags. There might be a better way, but I decided on building some Xpath to find out if a matching node exists in the other languages. We are using umbraco 7, and I would shy away from using NodeFactory if at all possible. It is depreciated. Using the umbraco helper won't hit the database, and is one of the best ways to query published content or media from umbraco for umbraco 7.

public static IPublishedContent GetLocalizedVersionOfPage(this IPublishedContent node, string regionName)
{
    var umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
    var ancestorNames = node.AncestorsOrSelf()
                            .Where(n => n.Level > 1)
                            .OrderBy(n => n.Level)
                            .Select(n => n.Name).ToList();

    var xpath = new StringBuilder();
    xpath.AppendFormat("/root/HomePage[@nodeName='{0}']", regionName);
    foreach (var ancestorName in ancestorNames)
    {
        xpath.AppendFormat("/*[@nodeName='{0}']", ancestorName);
    }

    var matchingNode = umbracoHelper.TypedContentAtXPath(xpath.ToString()).FirstOrDefault();
    return matchingNode;
}

The above method is an extension method on the IPublishedContent. It allows you to pass in the region and it checks to see if a node with the same path determined by node name exists in the specified region. I thought about using the urlname instead of the node name. You could do that as well and maybe even make this faster by skipping the piece of code that does the .AncestorsOrSelf(). It just depends on how you want it to work. In my case, I wanted it to find a match based on the node name even if the url path was different, so I had to do the .AncestorsOrSelf(). Hope this helps.

Another thing to consider is how you call this method. if you use a loop like this:

@foreach (var region in Umbraco.TypedContentAtRoot().Where(n => n.IsDocumentType("HomePage")))
{
    var localizedVersion = currentPage.GetLocalizedVersionOfPage(region.Name);
    if (localizedVersion != null)
    {
        <link rel="alternate" href="@localizedVersion.UrlAbsolute()" hreflang="@LocalizeUtils.GetCulture(region.Name)" />
    }
}

You will end up getting the ancestors of the current node over and over once for each region because it calls .AncestorsOrSelf() every time you call GetLocalizedVersionOfPage(). It probably makes sense to refactor the GetLocalizedVersionOfPage method so you only have to call .AncestorsOrSelf once. If you do this sort of thing too many times, it starts to affect performance (especially if your site is very nested).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文