The first thing to mention is that areas in Razor Pages differ to the ones that you find in an MVC application. An MVC area is like a mini MVC application, including all of the folders that you associate with MVC - Model, Views and Controllers. MVC areas have tooling support within Visual Studio, enabling the quick scaffolding of all the required artefacts:
This kind of support is not available (at the time of writing, at least) to Razor Pages areas. To add areas to Razor Pages, you simply add a new folder to the application and name it Areas. The folder must be at the root of the application:
The name of the Areas folder is non-negotiable. You cannot configure it to be something other than "Areas".
Once you have done this, you add additional subfolders for each item that represents a distinct area of the application, in this example, Customers, Orders and Products. These form the names of the areas:
Razor Pages in areas must have their own root folder just as in the main application. Therefore you will need to add a Pages folder to each area:
Again, the name of the root folder for the pages is not configurable.
Having done that, you can begin to add Razor Pages to each area. One thing to mention is that the PageModel class will
be generated with a namespace matching the file path to the file e.g.
WebApplication1.Areas.Customers.Pages.IndexModel
. The @model
directive in the
content page will not pick this up by default, so you can either fully qualify
the @model
directive every time you add a new page to the area, or you can
add a _ViewImports.cshtml_ file to the Pages folder in the area,
specifying the namespace for all pages in the folder:
For demo purposes, the current Index.cshtml file in the Customers area is very brief:
You should be able to navigate to it by firing up the application and appending
/customers
to the URL, but the output is very bland and has no styling:
You can make use of the default layout file by copying the _ViewStart.cshtml file from the root Pages folder to the Areas folder:
Now the pages in all areas will automatically make use of the default layout page:
Alternatively, you can specify a different layout file altogether, and only affect one area. The following example makes use of a Layout page located in the Pages folder of the Customers area:
@{ Layout = "/Areas/Customers/Pages/_Layout.cshtml"; }
This ViewStart file can be placed in the Customers folder or the Customers/Pages folder to affect all pages in the Customers area only. Pages in other areas will still be governed by the ViewStart file placed in the Areas folder.
Links and Redirects To Areas
When you use the
anchor taghelper to generate your links to items in areas, you
must use the asp-area
attribute:
...unless you are generating links between pages within the same area. Here is the Customers area Index page again with a link to Create.cshtml, also located in the Customers area:
If using the RedirectToPage
method to transfer someone to a
location within an area, you should use the overload that takes
an object representing route values to specify the area:
The leading slash is not necessary when using RedirectToPage
from within a Razor page, but you must use it when redirecting from outside of a
Razor page, such as from an MVC controller.
Routing
Route templates for items in areas are generated by prepending the area name to the file path of the page rooted in the area's Pages folder. For example, the template generated for the item with a relative path of /Areas/Customers/Pages/Create.cshtml will be "Customers/Create". This will clash with an item located at /Pages/Customers/Create/Index.cshtml or /Pages/Customers/Create.cshtml, unless constraints are explicity added to the route templates to disambiguate them.
Configuration and customisation
Customisation of conventions around areas in Razor Pages is limited. As I mentioned earlier, the
location of areas is restricted to a folder named Areas. Razor page files must
be placed in a folder named Pages within each area. Areas are enabled through
one of two mechanisms. The first is by default if you to set the compatibility version to 2.1 in the
Startup ConfigureServices
method:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
The second method is to set the RazorPagesOptions.AllowAreas
property to true (also in
ConfigureServices
):
services.AddMvc().AddRazorPagesOptions(options => { options.AllowAreas = true; });
Note that your application still needs to be targeting .NET Core 2.1 for this to work. It is how you elect to opt in to specific 2.1 behaviours if you choose not to set the compatibility version.
Summary
Areas were added to Razor Pages primarily to assist with the introduction of Razor class libraries, specifically the introduction of Identity as a class library. As such, they offer a way of dividing a complex Razor Pages application up by feature, but in reality, the same can be achieved with a little less ceremony by adding feature folders to the Pages folder e.g. /Pages/Customers/, /Pages/Orders/ etc. Nevertheless, if you are used to working with areas in MVC, it's good to know that they are available in Razor Pages too.