Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Url.RouteUrl is blank in ASP.NET Core 3.0

We are in the process of upgrading an ASP.NET Core 2.2 project to ASP.NET 3.0 that uses EndPoint routing.

We have a large list of urls constructed with Url.RouteUrl using named routes, e.g. :

string url = Url.RouteUrl("blog-details", new { title = item.Title, id = item.Id });
// returns correct link of https://example.org/us/blog/some-title-6 in 2.2 but is blank in 3.0

[Route("~/{lang}/blog/{title}-{id}", Name= "blog-details")]
public async Task<IActionResult> Details(string title, int id)
{
}

After upgrading to 3.0 those urls just produces a blank href. Our startup.cs is looking like this:

public void ConfigureServices(IServiceCollection services)
{
...
services.AddControllersWithViews(options =>
{
    options.Filters.Add(new MiddlewareFilterAttribute(typeof(LocalizationPipeline))); 
})
    .AddViewLocalization(LanguageViewLocationExpanderFormat.SubFolder)
    .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);

services.AddRazorPages();
... 
}

We have tried replacing with below but that creates the wrong link and does not allow us to reuse as a variable, e.g.:

<a asp-action="Details" asp-controller="Blog" asp-route-title="item.Title" asp-route-id="@item.Id">Link here</a>
url = Url.Action("Details", "Blog", new { id = item.Id, title = item.Title });
url = Url.RouteUrl(new { action = "Details", controller = "Blog", id = item.Id, title = item.Title });

// all returns https://example.org/us/blog/details/6?title=some-title 

<a asp-controller="Home" asp-action="Pricing">Pricing</a>
// returns https://example.org/us/home/pricing instead of correct https://example.org/us/pricing

[Route("~/{lang}/pricing")]
public async Task<IActionResult> Pricing()
{
    ...
}

This works, however:

<a asp-controller="Signup" asp-action="Customer">Sign up</a>
// returns correct https://example.org/us/signup/customer

[Route("~/{lang}/signup/customer")]
public IActionResult Customer()
{
   ...
}

What are we doing wrong if we want to use EndPoint routing (not the old 2.2.-way)?

like image 284
Sha Avatar asked Oct 01 '19 10:10

Sha


People also ask

What is URL RouteUrl?

RouteUrl(String, Object) Generates a fully qualified URL for the specified route values by using a route name. RouteUrl(String, RouteValueDictionary) Generates a fully qualified URL for the specified route values by using a route name.

What is new in core 3.0 in asp net?

IdentityServer4 supports authentication and authorization for web APIs and SPAs. ASP.NET Core 3.0 offers authentication in Single Page Apps (SPAs) using the support for web API authorization.

What is URL routing module in MVC?

The UrlRoutingModule class matches an HTTP request to a route in an ASP.NET application. The module iterates through all the routes in the RouteCollection property and searches for a route that has a URL pattern that matches the format of the HTTP request.


1 Answers

There are two items that are responsible for this behavior.

First, let's look at how the routes are generated:

[Route("~/{lang}/pricing")]

the {lang} token is the problematic one. One would expect that when browsing from page to page - as it was the case under ASP.Net Core 2.2 - this value would be retained and re-used. It is not the case anymore. The doc justifies it using the id example: book id 123 should not lead to login user id 123. Unfortunately, the same applies to the much more stable language code lang.

The URL generation must therefore include the lang code. Using the 1st URL in the question, it would become:

string url = Url.RouteUrl("blog-details", new {lang="en", title = item.Title, id = item.Id });

[Route("~/{lang}/blog/{title}-{id}", Name= "blog-details")]

The second item is the default route. Since the route you though was not matched because of the missing lang parameter, the default route is used. Since you have used parameters that are not part of the default route template, they are added to the end of the URL (?title=some-title). If there is no default route, no URL at all is generated.

There is an interesting post on the issue that is worth reading.

On a side note for all readers, one can extract the ambient value that should be recycled and plug it in links generations:

@{string lang = (string)ViewContext.RouteData.Values["lang"]; }
<a asp-area="" asp-controller="myController" asp-action="myAction" asp-route-lang=@lang >click here</a>
like image 126
JGH Avatar answered Oct 09 '22 20:10

JGH