U4-6479 - GetCulture Helper Bug

Created by christo 30 Mar 2015, 15:24:34 Updated by Murray Roke 23 Jun 2016, 00:37:42

Relates to: U4-7873

Relates to: U4-8647

I Pulled Down v 7.2.4.

I wanted to use the GetCulture Helper to get the culture of the given IContent item.

However, its inconsistent. It works sometimes and then doesnt other times. Im trying to use this against a published and unpublished node. Although im obviously using IContent each time. So im basically publishing and then unpublishing. If that makes any difference?

public static ICmsContentItem ToICmsContentItem(this IContent node) { var culture = node.GetCulture(); ...

This occasionally throws a object ref not found.

`` System.AggregateException was caught HResult=-2146233088 Message=One or more errors occurred. Source=mscorlib StackTrace: at System.Threading.Tasks.Task1.GetResultCore(Boolean waitCompletionNotification) at Admin.Web.App.StartupHandlers.ContentStartupHandler.Delete(IContent node, CancellableEventArgs args) in d:\projects\**\src\Admin.Web\App\StartupHandlers\ContentStartupHandler.cs:line 79 InnerException: System.NullReferenceException HResult=-2147467261 Message=Object reference not set to an instance of an object. Source=umbraco StackTrace: at Umbraco.Web.Models.ContentExtensions.GetCulture(UmbracoContext umbracoContext, ILocalizationService localizationService, Int32 contentId, String contentPath, Uri current) at Umbraco.Web.Models.ContentExtensions.GetCulture(IContent content, Uri current) at Admin.Web.App.Extensions.ContentExtensions.ToICmsContentItem(IContent node) in d:\projects\**\.Admin.Web\App\Extensions\ContentExtensions.cs:line 15 at Admin.Web.App.StartupHandlers.ContentStartupHandler.<>c__DisplayClass8.<Delete>b__6() in d:\projects\**admin\src\Admin.Web\App\StartupHandlers\ContentStartupHandler.cs:line 77 at System.Threading.Tasks.Task1.InnerInvoke() at System.Threading.Tasks.Task.Execute() InnerException: {"Object reference not set to an instance of an object."} TargetSite: {System.Globalization.CultureInfo GetCulture(Umbraco.Web.UmbracoContext, Umbraco.Core.Services.ILocalizationService, Int32, System.String, System.Uri)}

``

Comments

christo 30 Mar 2015, 15:27:12

please refer to http://issues.umbraco.org/issue/U4-3753

@zpqrtbnk im hoping you can help me with this issue.


christo 30 Mar 2015, 19:14:56

ok i think I figured it @zpqrtbnk . The GetCulture helper can only be called for published nodes, it will error if the given content item has no id. The following line throws a null reference exception.

https://github.com/umbraco/Umbraco-CMS/blob/3eb0dac48a37ead2483688bb1a14e56e32b645c2/src/Umbraco.Web/Models/ContentExtensions.cs#L42

Perhaps instead of using; var route = umbracoContext.ContentCache.GetRouteById(contentId); // cached

You could use this recursive helper below? `` public static string BuildUrl(this IContent node, StringBuilder uri) { var url = umbraco.library.NiceUrl(node.Id);

  if (url == "#")
  {
    if (node.Parent() != null)
    {
      BuildUrl(node.Parent(), uri);
    }
    uri.Append(string.Format("{0}/", node.Name.ToUrlSegment()));
  }
  else uri.Append(url);
  return uri.ToString();
}

``

fyi @dampee @jeffrey.schoemaker@perplex.nl


christo 30 Mar 2015, 20:50:28

ok ignore my previous suggestion @zpqrtbnk. My solution was to find the closest published node and retrieve the culture for that node. I assumed GetRouteById was doing something else entirely.

My solution is shown below.

`` public static CultureInfo GetClosestCulture(this IContent node) { while (true) { if (node.Published) return node.GetCulture();

    var parent = node.Parent();

    if (parent == null || node.ParentId == 0) return CultureInfo.CurrentUICulture;
    node = parent;
  }
}

``

Im sure theres a better way of doing it but with limited knowledge it will do for me. Im not suggesting it as a solution in this case but this still needs resolved. I still consider it a bug. This helper makes alot of assumptions and it has wasted alot of my time today. Of which could have been resolved by decent unit testing?

But regardless, thanks for the helper method. As you can see above. Im still using it.


Stephan 31 Mar 2015, 06:14:30

Hey - the issue with GetClosestCulture is that if there's a culture set on an unpublished node somewhere in the path between your node and the first published node, it will be ignored. I am using GetRouteById for perfs purposes (since it's all cached) but forgot to take care of unpublished nodes. Will fix.


Stephan 01 Apr 2015, 13:43:15

Have pushed fixes to both 7.2 (dev-v7 branch) and 7.3 (7.3.0 branch). With unit tests, that work for published and unpublished content.


Anja 24 Aug 2015, 09:17:02

try: var curNode = Umbraco.TypedContent(Model.Content.Id); string nodeLang = curNode.GetCulture().ToString(); see: http://www.sinfomania.com/en/tutorials/umbraco-7x/multi-language-site/#Add_and_assign_languages


Tim Geyssens 17 Sep 2015, 16:12:15

Just tried this with the 7.3 RC and still getting mixed results with the GetCulture extension method


Tim Geyssens 17 Sep 2015, 16:14:54

Being that GetCulture() returns the wrong culture in some cases


Stephan 17 Sep 2015, 16:43:42

... such as? Do you have a repro?


Tim Geyssens 18 Sep 2015, 08:04:08

Install RC with starter kit, add new language (I added nl-BE), copy node structure and assign languages (en-US to original, nl-BE to copy), if I then output Model.Content.GetCulture().ToString() on the original nodes it outputs nl-BE (as a side note dictionary items output the correct value)


Sam Sussman 17 Nov 2015, 18:03:21

Looking at the code for the helper, it appears a domain is required otherwise it simply grabs the first (Last) language. Which makes GetCulture unpredictable and unless without domains. For my solution I prefer not to have hard-coded domains as I am sharing a database with my local and dev environments, plus when I deploy to staging/prod I don't want to have to remember to change the domains. My quick fix was to add a language field to the root node Document Type and use that instead. It would be great if I could use the value that already is set(able) on each node.


Stephan 17 Nov 2015, 18:17:06

Interesting. There may be an issue indeed.


Stephan 01 Feb 2016, 11:12:28

Confirmed = issue U4-7873


Murray Roke 20 Jun 2016, 05:23:40

Still seems broken (or am I using it wrong) I have an IPC with Maori culture (no hostnames) but when I call node.GetCulture() I always get english (umbraco 7.4.3)

my case also relates to: http://issues.umbraco.org/issue/U4-8600 (where I want to use the culture I'm getting)


Priority: Normal

Type: Bug

State: Fixed

Assignee: Stephan

Difficulty: Normal

Category: Localization

Backwards Compatible: True

Fix Submitted:

Affected versions: 7.2.3, 7.2.4

Due in version: 7.3.0, 7.2.5

Sprint:

Story Points:

Cycle: