0
votes

I have an Area named Projects I am trying to navigate to. This area has two Controllers named Project and Dashboard, each with an Index action.

[Authorize]
[Area("Projects")]
public class ProjectController : Controller
{
    ...
}

[Authorize]
[Area("Projects")]
public class DashboardController : Controller
{
    ...
}

I have the following routes defined in Startup.cs.

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

    routes.MapRoute(
        name: "Projects",
        template: "{area}/{controller}/{action}/{id?}");

    ...
});

When I type the url "http://localhost:1234:Projects/Dashboard" to the Dashboard it works - the view is displayed. However, having the following tag helper defined in this view to the Project controller, I get the url http://localhost:1234/Project?area=Projects with a 404 not found:

<a asp-area="Projects" asp-controller="Project" asp-action="Index">
    <span>Goto Project</span>
</a>

The url needs to be http://localhost:1234/Projects/Project. If I enter that in the browser address bar then it shows the Projects Index View. I am assuming my routes are configured correctly.

I've tried asp-area="Projects" and omitting asp-area tags also. I've trawled through the area docs and routing docs multiple times to no avail.

I am targeting .NET Framework 4.6.2. Here is the csproj areas of interest:

<PropertyGroup>
    <TargetFramework>net462</TargetFramework>
    <RuntimeIdentifier>win7-x86</RuntimeIdentifier>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <PlatformTarget>x86</PlatformTarget>
</PropertyGroup>

<ItemGroup>
    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Authentication.Cookies" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Identity" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="1.1.1" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
    <PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="1.1.0" />
    <PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="1.1.1" />
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
    <PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="1.1.0" PrivateAssets="All" />
    <PackageReference Include="SimpleInjector.Integration.AspNetCore.Mvc" Version="3.3.2" />
    <PackageReference Include="Telerik.UI.for.AspNet.Core" Version="2017.1.223" />
</ItemGroup>
<ItemGroup>
    <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
    <DotNetCliToolReference Include="Microsoft.Extensions.SecretManager.Tools" Version="1.0.0" />
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="1.0.0" />
</ItemGroup>

I've created a folder named Areas at the root level of the project. Ie:

ACMEMVCWebApp\Areas\Projects
ACMEMVCWebApp\Areas\Projects\Controllers
ACMEMVCWebApp\Areas\Projects\Views

How can I navigate from Dashboard to Project using the Anchor Tag Helper?

3

3 Answers

2
votes

I just tried in a new application and it works fine.

Which version of .Net Core are you using?

I just check the implementation and it should be fine. Maybe some package mismatch?

So here is my example configuration. I put area route to the top like this:

Route

Controller

View

Generated URL

1
votes

I too have this problem with generating the correct url to a controller action within an area. I have found the fix that may be of interest to some with the same issue.

The order of the routes was the issue with creating the correct url to the action. In my case I was generating the action for a form and was moving some code from MVC 5 to MVC Core 2.0. The original code used a html helper like this:

@using (Html.BeginForm())

And produced the following correct markup:

<form action="/Admin/Role/Create?_=1505204033132" method="post">

I then updated the code to use the tag helper as I quite like the syntax. I changed the above to:

<form asp-area="Admin" asp-controller="Role" asp-action="Create" method="post">

This did not create the correct url. The code it produced looks like this:

<form method="post" action="/Role/Create?area=Admin">

Using this url gives the expected 404 response.

Changing the order of the routes around, in startup.cs, so that the area route was first fixed the issue and the url is now correct.

I have no idea why this is so and was very surprised to find that the routing had any control over the generation of the url. This certainly has the ability to catch me out again as i would have thought that the two were separate entities and that the routing was only used when a request was made - seems that is not a correct assumption.

Gordon

0
votes

To quote the documentation:

Routes in the route collection are ordered, and will be processed in the order they are added. So in this example, the blog route will be tried before the default route.

So this needs to be areas first before default route:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "Projects",
        template: "{area}/{controller}/{action}/{id?}");

    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");

}

Given that, I still find it odd that typing the url in directly worked. The problem was in the Tag Helpers.