How to use an Area in ASP.NET Core
Asked Answered
L

8

71

How do I use an Area in ASP.NET Core?

I have an app that needs an Admin section. This section requires its Views to be placed in that area. All requests that start with Admin/ will need to be redirected to that area.

Liturgical answered 10/4, 2016 at 21:2 Comment(0)
L
92

In order to include an Area in an ASP.NET Core app, first we need to include a conventional route in the Startup.cs file (It's best to place it before any non-area route):

In Startup.cs/Configure method:

app.UseMvc(routes =>
{
    routes.MapRoute("areaRoute", "{area:exists}/{controller=Admin}/{action=Index}/{id?}");

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

Then make a folder named Areas in the app root and make another named Admin inside the former, also make these folders inside Admin (ViewComponent is optional):

enter image description here

Now we create a controller inside the Controllers folder named AdminController, the content can be like:

[Area("Admin")]
[Route("admin")]
public class AdminController : Controller
{
    public AdminController()
    {
        // do stuff
    }

    public IActionResult Index()
    {
        return View();
    }

    [Route("[action]/{page:int?}")]
    public IActionResult Orders()
    {
        return View();
    }

    [Route("[action]")]
    public IActionResult Shop()
    {
        return View();
    }
    
    [Route("[action]/newest")]
    public IActionResult Payments()
    {
        return View();
    }
}

Now in order for that to work, you'll need to create Views for all actions that return one. The hierarchy for views is just like what you have in a non-area Views folder:

enter image description here

Now, you should be good to go!

Question: What if I want to have another controller inside my Area?

Answer:

Just add another controller beside AdminController and make sure the routes are like the following:

[Area("Admin")]
[Route("admin/[controller]")]
public class ProductsController : Controller
{
    public ProductsController()
    {
        //
    }

    [Route("{page:int?}")]
    public IActionResult Index()
    {
        return View();
    }
}

The important part is [Route("admin/[controller]")]. With that you can keep the style of routing to admin/controller/action/...

Liturgical answered 10/4, 2016 at 21:2 Comment(18)
This is tested on RC1, RC2, and 1.0. It totally works.Liturgical
I created a sample as you show above and add admin area, it works fine, but when I published my project, it doesn't published admin area and views and files, how can I handle it?Belford
@motevallizadeh, Another question of mine! #37326568Liturgical
thanks ,In your mind. is it .net core stable to start a real/final web application?Belford
@motevallizadeh, Hosting could be an issue because you'll absolutely need a VPS or Dedicated Server as no web based control panel supports ASP.NET Core yet (Plesk will eventually support it but still no ETA). Also Check out ASP.NET Core documentation (stackoverflow.com/documentation/asp.net-core/topics), I wrote some articles about localization and authorization.Liturgical
Thanks a lot for sharing your knowledgeBelford
I find that you still have to copy the contents css/js etc into wwwroot, is there a way around this for areas as you may have some scripts that may have some area related data that you do not wish to expose for some reason?James
@AliK, think to accomplish this you will need to store these scripts outside wwwroot and serve them over controller returning FileResult, as written here: docs.microsoft.com/en-us/aspnet/core/fundamentals/static-files: "The static file module provides no authorization checks. Any files served by it, including those under wwwroot are publicly available. To serve files based on authorization: Store them outside of wwwroot and any directory accessible to the static file middleware and Serve them through a controller action, returning a FileResult where authorization is applied"Diep
@Diep I did take a look at that option but seems a bit far fetched just to serve files required for an area that should be private in most cases, i am guessing at many people have a similar requirement so maybe someone has another solution.James
Is not the point of using Areas more to do about organization and structure, not security? Because I still don't see any other reason to use areas.Eldoree
@VSG24: what about if I want to create a view in the area zone that should use a shared layout in the non area zone? I have tried by creating a _ViewStart.cshtml in the area views folder with Layout = "~/Views/Shared/_LayoutAdmin.cshtml"; but unfortunately is not workingAsperity
is it possible to have different Identity auth options for a specific area? let's say, for only the "admin" area, set ApplicationCookie.AutomaticChallenge = true and ApplicationCookie.LoginPath = "admin/account/login"?Boar
This didn't work for me. I tried to code the same as you did. I am still redirected to the default view. Am i missing on something?Supernational
@SachinPakale Did you include the area route in UseMvc()?Liturgical
This is my UseMvc code routes.MapRoute("admin", "{area:exists}/{controller=Admin}/{action=Index}/{id?}"); // Default routing routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); });Supernational
this worked for me [Route("")] [Route("Admin")] [Route("Admin/Index")] public IActionResult Index()Supernational
@VSG24 Could you explain what the :exists modifier does?Lezlielg
So a registration file isn't the conventional way to do this anymore? I added the area, but it no longer creates one.Fradin
S
42

In ASP.NET Core 3.0. If you are working with Endpoint patterns, after adding the Area (Right click over project, Add, New Scaffolded Item, Area), you have to add manually routing pattern on startup.cs Configure method. (At this point the generated ScaffoldingReadMe.txt is out of date).

app.UseEndpoints(endpoints =>
{

    endpoints.MapAreaControllerRoute(
        "Admin",
        "Admin",
        "Admin/{controller=Home}/{action=Index}/{id?}");

    endpoints.MapControllerRoute(
         name: "default",
         pattern: "{controller=Home}/{action=Index}/{id?}");
});
Sponger answered 30/11, 2019 at 18:30 Comment(1)
This is what I was missing. This fixed the issue for me.Clothesline
S
10

In the Microsoft docs to migrate from ASP.NET CORE 2.2 to 3.0 the suggestion is to:

Replace UseMvc with UseEndpoints.

I encountered some challenges while trying to fix my Area's while simultaneously having Identity to keep working - but the solution below seems to be working for ASP.NET CORE 3.0 :

app.UseEndpoints(endpoints =>
{
    endpoints.MapRazorPages();
    endpoints.MapControllerRoute("areas", "{area:exists}/{controller=Home}/{action=Index}/{id?}");
    endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

Hopefully I could also help you out and reduce the research time :-)

Spiky answered 18/12, 2019 at 14:42 Comment(0)
P
5

Scaffolding has generated all the files and added the required dependencies.

However the Application's Startup code may required additional changes for things to work end to end. Add the following code to the Configure method in your Application's Startup class if not already done:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name : "areas",
        template : "{area:exists}/{controller=Home}/{action=Index}/{id?}");
});
Primogenitor answered 16/5, 2018 at 12:28 Comment(0)
D
4

Areas Implementation in Routing First Create Area(Admin) using VS and add the following code into Startup.cs First Way to Implement:- Add Controller Login and Index Action and add Following Code, [Area(“Admin”)] is compulsory to add on controller level to perform asp.net areas Routing. Startup.cs

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

Note: Area routing must be placed first with non area routing, area: exists is compulsory to add area routing.

Controller Code:

[Area("Admin")] 
    public class LoginController : Controller
    {
        public IActionResult Index()
        {
            return Content("Area Admin Login Controller and Index Action");
        }
    }

This route may be called using http://localhost:111/Admin

Second Way to Implement Area Routing:- Add Following code into startup.cs.

app.UseMvc(routes =>
            {
                routes.MapAreaRoute(
    name: "default",
    areaName: "Guest",
    template: "Guest/{controller}/{action}/{id?}",
    defaults: new { controller = "GuestLogin", action = "Index" });
            });

Create an Area “Guest”, Add “GuestLogin” Controller and “Index” Action and add the following code into the newly created controller.

[Area("Guest")]
    public class GuestLoginController : Controller
    {
        public IActionResult Index()
        {
            return Content("Area Guest Login Controller and Index Action");
        }
    }

This route may be called using http://localhost:111/Guest

Dunkin answered 27/5, 2019 at 0:34 Comment(0)
S
1
With .net core, following is needed to be added in the startup file if you are adding an area:

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

After that you can just simply mark your area and route in the controller, i.e
     [Area("Order")]
     [Route("order")]

it works for me.

Stephanus answered 13/2, 2019 at 9:26 Comment(0)
C
1

Use this pattern in Configure method in Startup.Cs, as its full routing manner:

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

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

In Core 3.1 you should use below code in ConfigureServices method:

services.AddMvc(option => option.EnableEndpointRouting = false);
Clinch answered 19/1, 2020 at 6:57 Comment(0)
C
0

Use this pattern in Configure method in Startup.Cs, as its full routing manner:

app.UseMvc(routes =>{

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

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

In Core 3.1 you should use below code in ConfigureServices method:

services.AddMvc(option => option.EnableEndpointRouting = false);
Clinch answered 19/1, 2020 at 6:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.