U4-10596 - Umbraco.Url throws exception in UmbracoApiController

Created by Rune Antonsen 27 Oct 2017, 13:18:51 Updated by Claus Jensen 08 Jan 2018, 18:46:44

Tags: PR

Relates to: U4-10714

Subtask of: U4-9609

base.Umbraco.Url throws an: System.FormatException: 'Input string was not in a correct format.' when called from UmbracoApiController.

+However the order of testing is important to catch the error!+

Test scenario:

  • Call UmbracoApiTestController.Fails() -- Will throw: System.FormatException: 'Input string was not in a correct format.'
  • Call SurfaceTestController.Works() -- Will work as expected.
  • If you now call UmbracoApiTestController.Fails() again -- Will work as expected (cached or something)
public class UmbracoApiTestController : UmbracoApiController
{
    public void Fails()
    {
        var testUrl = Umbraco.Url(VALID_NODE_ID);
    }
}

public class SurfaceTestController : SurfaceController
{
    public void Works()
    {
        var testUrl = Umbraco.Url(VALID_NODE_ID);
    }
}

From Slack conversation: +mortenbock:+ The obvious difference is that one is an ApiController and the other is a surface controller. So the ApiController will not have a CurrentNode which might throw off the UrlProvider a bit?

+mortenbock:+ The code writing the url might want to check what the hostname is for the current node, to write the correct url etc.

Stacktrace from my application:

   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)\r\n
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)\r\n
   at Umbraco.Web.PublishedCache.XmlPublishedCache.PublishedContentCache.DetermineRouteById(UmbracoContext umbracoContext, Boolean preview, Int32 contentId)\r\n
   at Umbraco.Web.PublishedCache.XmlPublishedCache.PublishedContentCache.GetRouteById(UmbracoContext umbracoContext, Boolean preview, Int32 contentId)\r\n
   at Umbraco.Web.Routing.DefaultUrlProvider.GetUrl(UmbracoContext umbracoContext, Int32 id, Uri current, UrlProviderMode mode)\r\n
   at Umbraco.Web.Routing.UrlProvider.<>c__DisplayClass3.<GetUrl>b__0(IUrlProvider provider)\r\n
   at System.Linq.Enumerable.WhereSelectArrayIterator`2.MoveNext()\r\n   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)\r\n
   at Umbraco.Web.Routing.UrlProvider.GetUrl(Int32 id, Uri current, UrlProviderMode mode)\r\n
   at Umbraco.Web.Models.PublishedContentBase.get_Url()\r\n
   at Intranet.Features.Search.Helpers.SearchHelper.<>c.<GetFormSearchResults>b__5_3(IPublishedContent searchResult) in C:\\Projects\\Intranet\\Intranet\\Features\\Search\\Helpers\\SearchHelper.cs:line 153\r\n
   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()\r\n
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n
   at Intranet.Features.Search.Helpers.SearchHelper.GetFormSearchResults(IEnumerable`1 results) in C:\\Projects\\Intranet\\Intranet\\Features\\Search\\Helpers\\SearchHelper.cs:line 149\r\n
   at Intranet.Features.Search.Helpers.SearchHelper.Search(String searchString, String[] fieldsToSearch) in C:\\Projects\\Intranet\\Intranet\\Features\\Search\\Helpers\\SearchHelper.cs:line 42\r\n
   at Intranet.Features.Search.Controllers.QuickSearchController.Search(String s) in C:\\Projects\\Intranet\\Intranet\\Features\\Search\\Controllers\\QuickSearchController.cs:line 13\r\n
   at lambda_method(Closure , Object , Object[] )\r\n
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n
   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)"

Comments

Rune Antonsen 23 Nov 2017, 14:13:39

@mortenbock https://github.com/umbraco/Umbraco-CMS/pull/2332


Claus Jensen 08 Jan 2018, 13:14:41

I've not been able to make this actually fail on my machine using the instructions above. I've however tested that the (relatively simple) change doesn't seem to break anything either.

If it solves the issues you guys have been having - I'm okay with including this fix.


Rune Antonsen 08 Jan 2018, 15:47:06

@claus We managed to debug our way down to it being a fu**ed up Culture on my dev. computer. It was working fine in test environment and production.

However, I think the PR should be included anyways. No harm in it at all, just fixes a rare potential problem. There is probably more parses in the code that should also have an CultureInfo.InvariantCulture added to it.

Cheers


Claus Jensen 08 Jan 2018, 18:46:44

@ruant yep I couldn't really make it fail even though I tried with various hacks .. but yes the change should not really affect anything. And yes - in most cases you would always want to parse with invariantculture :) Thanks for the PR!


Priority: Normal

Type: Bug

State: Fixed

Assignee:

Difficulty: Normal

Category:

Backwards Compatible: True

Fix Submitted: Pull request

Affected versions: 7.5.10

Due in version: 7.7.9

Sprint: Sprint 76

Story Points: 1

Cycle: 7