Search code examples
c#.netasp.net-coreasp.net-core-mvcasp.net-routing

Routing with Areas and Controller Name (asp.net core)


To stop my application from getting cluttered I started working with areas. But now I always have to call:
http://localhost:49358/Document/Document/
instead of:
http://localhost:49358/Document/
How can I change my route to access the Controllers by name of the Area? (no HomeController)

I have the following folder structure inside of my Project:

Folderstructure inside my Project
The code for my route to the Areas looks like this:

routes.MapRoute(name: "areaRoute",template: "{area:exists}/{controller=Home}/{action=Index}");

And I placed the [Area("Document")] Tag in my DocumentController.

Edit:
As suggested by Shyju and Jamie Taylor I went with the HomeControllers. (Thank you both for the quick answers and explanations)

My Structure now looks like this and the routing is working like expected:
enter image description here

For me it's still a bit dissapointing to have so many HomeControllers and Index Files. Navigating code isn't that easy anymore:
enter image description here

Edit2:
After getting too annoyed with all those Homecontrollers, I went with the solution suggested by Jamie Taylor and rearanged everything in a Features folder. It needs a bit more configuration but is much cleaner in my opinion.
It is also further explained in this Microsoft Article (Just skip the Area stuff):
https://msdn.microsoft.com/en-us/magazine/mt763233.aspx

My structure now looks like this and routing works like a charm and the controller names are still meaningful:
enter image description here


Solution

  • I'm not sure that's what areas are for. Perhaps you should rethink your architecture.

    In my ASP.NET MVC Core application template, I've leveraged Feature folders, which works a little like areas.

    To do this, I've added the following to the ConfigureServices method:

    serviceCollection.Configure<RazorViewEngineOptions>(options =>
    {
      options.ViewLocationExpanders.Add(new FeatureLocationExpander());
    });
    

    Where FeatureLocationExpander is:

    public class FeatureLocationExpander : IViewLocationExpander
    {
      public void PopulateValues(ViewLocationExpanderContext context)
      {
      // Don't need anything here, but required by the interface
      }
    
      public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
      {
        // The old locations are /Views/{1}/{0}.cshtml and /Views/Shared/{0}.cshtml
        // where {1} is the controller and {0} is the name of the View
    
        // Replace /Views with /Features
        return new string[]
        {
          "/Api/{1}/{0}.cshtml",
          "/Features/{1}/{0}.cshtml",
          "/Features/Shared/{0}.cshtml"
        };
      }
    }
    

    Replacing the contents of the new string[] which is returned by ExpandViewLocations for your areas will mean that you won't have to add the routing attributes.

    BUT, this does not fix your issue as that is not what areas are for.

    Unless you added a razor page (named Index.cshtml) under the Documents area which acts as an index page for the Documents area. This Index.cshtml could provide all of the functionality of the Index.cshtml in your /Documents/Documents/Index.cshtml with the added bonus of having a code-behind like file (remember ASP.NET webforms?) which acts like your controller.