diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageApplicationModel.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageApplicationModel.cs
index dee4f299fd..bdf0654dc0 100644
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageApplicationModel.cs
+++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageApplicationModel.cs
@@ -72,9 +72,22 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
///
/// Gets the path relative to the base path for page discovery.
+ ///
+ /// This value is the path of the file without extension, relative to the pages root directory.
+ /// e.g. the for the file /Pages/Catalog/Antiques.cshtml is /Catalog/Antiques
+ ///
+ ///
+ /// In an area, this value is the path of the file without extension, relative to the pages root directory for the specified area.
+ /// e.g. the for the file Areas/Identity/Pages/Manage/Accounts.cshtml, is /Manage/Accounts.
+ ///
///
public string ViewEnginePath => ActionDescriptor.ViewEnginePath;
+ ///
+ /// Gets the area name.
+ ///
+ public string AreaName => ActionDescriptor.AreaName;
+
///
/// Gets the route template for the page.
///
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageConventionCollection.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageConventionCollection.cs
index d883dacccf..ba38593f10 100644
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageConventionCollection.cs
+++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageConventionCollection.cs
@@ -48,6 +48,40 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
return Add(new PageApplicationModelConvention(pageName, action));
}
+ ///
+ /// Creates and adds an that invokes an action on the
+ /// for the page with the specified name located in the specified area.
+ ///
+ /// The name of area.
+ ///
+ /// The page name e.g. /Users/List
+ ///
+ /// The page name is the path of the file without extension, relative to the pages root directory for the specified area.
+ /// e.g. the page name for the file Areas/Identity/Pages/Manage/Accounts.cshtml, is /Manage/Accounts.
+ ///
+ ///
+ /// The .
+ /// The added .
+ public IPageApplicationModelConvention AddAreaPageApplicationModelConvention(
+ string areaName,
+ string pageName,
+ Action action)
+ {
+ if (string.IsNullOrEmpty(areaName))
+ {
+ throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(areaName));
+ }
+
+ EnsureValidPageName(pageName);
+
+ if (action == null)
+ {
+ throw new ArgumentNullException(nameof(action));
+ }
+
+ return Add(new PageApplicationModelConvention(areaName, pageName, action));
+ }
+
///
/// Creates and adds an that invokes an action on
/// instances for all page under the specified folder.
@@ -67,6 +101,40 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
return Add(new FolderApplicationModelConvention(folderPath, action));
}
+ ///
+ /// Creates and adds an that invokes an action on
+ /// instances for all pages under the specified area folder.
+ ///
+ /// The name of area.
+ ///
+ /// The folder path e.g. /Manage/
+ ///
+ /// The folder path is the path of the folder, relative to the pages root directory for the specified area.
+ /// e.g. the folder path for the file Areas/Identity/Pages/Manage/Accounts.cshtml, is /Manage.
+ ///
+ ///
+ /// The .
+ /// The added .
+ public IPageApplicationModelConvention AddAreaFolderApplicationModelConvention(
+ string areaName,
+ string folderPath,
+ Action action)
+ {
+ if (string.IsNullOrEmpty(areaName))
+ {
+ throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(areaName));
+ }
+
+ EnsureValidFolderPath(folderPath);
+
+ if (action == null)
+ {
+ throw new ArgumentNullException(nameof(action));
+ }
+
+ return Add(new FolderApplicationModelConvention(areaName, folderPath, action));
+ }
+
///
/// Creates and adds an that invokes an action on the
/// for the page with the specified name.
@@ -86,6 +154,37 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
return Add(new PageRouteModelConvention(pageName, action));
}
+ ///
+ /// Creates and adds an that invokes an action on the
+ /// for the page with the specified name located in the specified area.
+ ///
+ /// The area name.
+ ///
+ /// The page name e.g. /Users/List
+ ///
+ /// The page name is the path of the file without extension, relative to the pages root directory for the specified area.
+ /// e.g. the page name for the file Areas/Identity/Pages/Manage/Accounts.cshtml, is /Manage/Accounts.
+ ///
+ ///
+ /// The .
+ /// The added .
+ public IPageRouteModelConvention AddAreaPageRouteModelConvention(string areaName, string pageName, Action action)
+ {
+ if (string.IsNullOrEmpty(areaName))
+ {
+ throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(areaName));
+ }
+
+ EnsureValidPageName(pageName);
+
+ if (action == null)
+ {
+ throw new ArgumentNullException(nameof(action));
+ }
+
+ return Add(new PageRouteModelConvention(areaName, pageName, action));
+ }
+
///
/// Creates and adds an that invokes an action on
/// instances for all page under the specified folder.
@@ -105,6 +204,37 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
return Add(new FolderRouteModelConvention(folderPath, action));
}
+ ///
+ /// Creates and adds an that invokes an action on
+ /// instances for all page under the specified area folder.
+ ///
+ /// The area name.
+ ///
+ /// The folder path e.g. /Manage/
+ ///
+ /// The folder path is the path of the folder, relative to the pages root directory for the specified area.
+ /// e.g. the folder path for the file Areas/Identity/Pages/Manage/Accounts.cshtml, is /Manage.
+ ///
+ ///
+ /// The .
+ /// The added .
+ public IPageRouteModelConvention AddAreaFolderRouteModelConvention(string areaName, string folderPath, Action action)
+ {
+ if (string.IsNullOrEmpty(areaName))
+ {
+ throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(areaName));
+ }
+
+ EnsureValidFolderPath(folderPath);
+
+ if (action == null)
+ {
+ throw new ArgumentNullException(nameof(action));
+ }
+
+ return Add(new FolderRouteModelConvention(areaName, folderPath, action));
+ }
+
///
/// Removes all instances of the specified type.
///
@@ -158,7 +288,7 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
}
}
- private TConvention Add(TConvention convention) where TConvention: IPageConvention
+ private TConvention Add(TConvention convention) where TConvention : IPageConvention
{
base.Add(convention);
return convention;
@@ -166,18 +296,26 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
private class PageRouteModelConvention : IPageRouteModelConvention
{
+ private readonly string _areaName;
private readonly string _path;
private readonly Action _action;
public PageRouteModelConvention(string path, Action action)
+ : this(null, path, action)
{
+ }
+
+ public PageRouteModelConvention(string areaName, string path, Action action)
+ {
+ _areaName = areaName;
_path = path;
_action = action;
}
public void Apply(PageRouteModel model)
{
- if (string.Equals(model.ViewEnginePath, _path, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(_areaName, model.AreaName, StringComparison.OrdinalIgnoreCase) &&
+ string.Equals(model.ViewEnginePath, _path, StringComparison.OrdinalIgnoreCase))
{
_action(model);
}
@@ -186,20 +324,26 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
private class FolderRouteModelConvention : IPageRouteModelConvention
{
+ private readonly string _areaName;
private readonly string _folderPath;
private readonly Action _action;
public FolderRouteModelConvention(string folderPath, Action action)
+ : this(null, folderPath, action)
{
+ }
+
+ public FolderRouteModelConvention(string areaName, string folderPath, Action action)
+ {
+ _areaName = areaName;
_folderPath = folderPath.TrimEnd('/');
_action = action;
}
public void Apply(PageRouteModel model)
{
- var viewEnginePath = model.ViewEnginePath;
-
- if (PathBelongsToFolder(_folderPath, viewEnginePath))
+ if (string.Equals(_areaName, model.AreaName, StringComparison.OrdinalIgnoreCase) &&
+ PathBelongsToFolder(_folderPath, model.ViewEnginePath))
{
_action(model);
}
@@ -208,18 +352,26 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
private class PageApplicationModelConvention : IPageApplicationModelConvention
{
+ private readonly string _areaName;
private readonly string _path;
private readonly Action _action;
public PageApplicationModelConvention(string path, Action action)
+ : this(null, path, action)
{
+ }
+
+ public PageApplicationModelConvention(string areaName, string path, Action action)
+ {
+ _areaName = areaName;
_path = path;
_action = action;
}
public void Apply(PageApplicationModel model)
{
- if (string.Equals(model.ViewEnginePath, _path, StringComparison.OrdinalIgnoreCase))
+ if (string.Equals(model.ViewEnginePath, _path, StringComparison.OrdinalIgnoreCase) &&
+ string.Equals(model.AreaName, _areaName, StringComparison.OrdinalIgnoreCase))
{
_action(model);
}
@@ -228,20 +380,26 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
private class FolderApplicationModelConvention : IPageApplicationModelConvention
{
+ private readonly string _areaName;
private readonly string _folderPath;
private readonly Action _action;
public FolderApplicationModelConvention(string folderPath, Action action)
+ : this(null, folderPath, action)
{
+ }
+
+ public FolderApplicationModelConvention(string areaName, string folderPath, Action action)
+ {
+ _areaName = areaName;
_folderPath = folderPath.TrimEnd('/');
_action = action;
}
public void Apply(PageApplicationModel model)
{
- var viewEnginePath = model.ViewEnginePath;
-
- if (PathBelongsToFolder(_folderPath, viewEnginePath))
+ if (string.Equals(_areaName, model.AreaName, StringComparison.OrdinalIgnoreCase) &&
+ PathBelongsToFolder(_folderPath, model.ViewEnginePath))
{
_action(model);
}
diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageRouteModel.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageRouteModel.cs
index 277fdad905..8c94ae18a7 100644
--- a/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageRouteModel.cs
+++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/ApplicationModels/PageRouteModel.cs
@@ -21,9 +21,21 @@ namespace Microsoft.AspNetCore.Mvc.ApplicationModels
/// The application relative path of the page.
/// The path relative to the base path for page discovery.
public PageRouteModel(string relativePath, string viewEnginePath)
+ : this(relativePath, viewEnginePath, areaName: null)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of .
+ ///
+ /// The application relative path of the page.
+ /// The path relative to the base path for page discovery.
+ /// The area name.
+ public PageRouteModel(string relativePath, string viewEnginePath, string areaName)
{
RelativePath = relativePath ?? throw new ArgumentNullException(nameof(relativePath));
ViewEnginePath = viewEnginePath ?? throw new ArgumentNullException(nameof(viewEnginePath));
+ AreaName = areaName;
Properties = new Dictionary