question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ActionContext.RouteData.Routers empty causes ArgumentOutOfRangeException in UrlHelper (Regression from 2.1)

See original GitHub issue

Describe the bug

  1. ActionContext.RouteData.Routers is empty collection with CompabilityVersion.Version_2_2
  2. UrlHelper uses direct access to zero-element, instead calling .First() or .FirstOrDefault() with emergency return of ie. NullRouter protected IRouter Router => ActionContext.RouteData.Routers[0];
  3. This causes ArgumentOutOfRangeException while using UrlHelper

To Reproduce

Steps to reproduce the behavior:

  1. Using this version of ASP.NET Core ‘2.2’
  2. Run this code:

Generate new WebApi project In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
	services.AddRouting(opt => opt.LowercaseUrls = true);

	
	services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();
	services.AddScoped<IUrlHelper>(implementationFactory =>
	{
		var actionContext = implementationFactory.GetService<IActionContextAccessor>().ActionContext;
		return new UrlHelper(actionContext);
	});

	services.AddMvc()
		.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
}

TestController.cs

using Microsoft.AspNetCore.Mvc;

[Route("api/test")]
public class TestController : Controller
{

    protected IUrlHelper UrlHelper {get;set;}

	public TestController(IUrlHelper urlHelper)
	{
        UrlHelper = urlHelper;
	}

	[HttpGet]
	public IActionResult ListAsync() 
	{
		var res = UrlHelper.Action(nameof(ListAsync));
		return Ok(res);
	}
}
  1. Execute action GET /api/test
  2. See error:
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
 Parameter name: index
System.Collections.Generic.List<T>.get_Item(int index)
Microsoft.AspNetCore.Mvc.Routing.UrlHelper.get_Router()
Microsoft.AspNetCore.Mvc.Routing.UrlHelper.GetVirtualPathData(string routeName, RouteValueDictionary values)
Microsoft.AspNetCore.Mvc.Routing.UrlHelper.Action(UrlActionContext actionContext)
Microsoft.AspNetCore.Mvc.UrlHelperExtensions.Action(IUrlHelper helper, string action, string controller, object values, string protocol, string host, string fragment)
Microsoft.AspNetCore.Mvc.UrlHelperExtensions.Action(IUrlHelper helper, string action)
TestController.ListAsync() in TestController.cs
		var res = UrlHelper.Action(nameof(ListAsync));
  1. Switch CompabilityVersion to CompatibilityVersion.Version_2_1
  2. Watch action run as expected

Expected behavior

Action should return /api/test No ArgumentOutOfRangeException should be thrown

Additional context

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:17 (8 by maintainers)

github_iconTop GitHub Comments

2reactions
JamesNKcommented, Dec 17, 2018

UrlHelper relies on IRouter and will not work when endpoint routing is enabled. There is an EndpointRoutingUrlHelper that is used for backwards compatibility reasons but is internal.

Instead of injecting UrlHelper, you should change your code to use LinkGenerator. It is designed to be resolved from DI and is registered by default in 2.2

Use LinkGenerator.GetPathByAction: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-2.2#url-generation

@rynowak Do you think we should improve the exception UrlHelper throws when there is no router? Something like: “No router could be found. Use LinkGenerator instead.”

0reactions
brittonbeckhamcommented, Feb 7, 2019

Perfect! Thanks. I’ll take a look at how this works and see if it is a suitable replacement for what I was doing.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Trying to Test a Controller with a UrlHelper
The helper is trying to access actionContext.RouteData.Values which was not provided in the original example.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found