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)?
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.
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.
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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With