Áreas de ASP.NET Core

Por Dhananjay Kumar y Rick Anderson

Las áreas son una característica ASP.NET utilizadas para organizar las funcionalidades relacionadas en un grupo de forma separada:

  • Espacio de nombres para el enrutamiento.
  • Estructura de carpetas para vistas y páginas Razor.

El uso de áreas crea una jerarquía para el enrutamiento añadiendo de otro parámetro de ruta, area, a controller y action, o bien a Razor de la página page.

Las áreas ofrecen una manera de dividir una aplicación web ASP.NET Core en grupos funcionales más pequeños, cada uno con su propio conjunto de páginas Razor, controladores, vistas y modelos. Un área es en realidad una estructura dentro de una aplicación. En un proyecto web ASP.NET Core, los componentes lógicos como Páginas, Modelo, Vista y Controlador se mantienen en carpetas diferentes. El runtime de ASP.NET Core usa convenciones de nomenclatura para crear la relación entre estos componentes. Para una aplicación grande, puede ser conveniente dividir la aplicación en distintas áreas de funciones de alto nivel. Por ejemplo, una aplicación de comercio electrónico con varias unidades de negocio, como las de finalización de la compra, facturación y búsqueda. Cada una de estas unidades tiene un área propia para controlar vistas, controladores, páginas Razor y modelos.

Considere el uso de áreas en un proyecto en los casos siguientes:

  • La aplicación está formada por varios componentes funcionales generales que se pueden separar de forma lógica.
  • Le interesa dividir la aplicación para que se pueda trabajar en cada área funcional de forma independiente.

Si va a usar las páginas Razor, consulte Áreas con páginas Razor en este documento.

Áreas para controladores con vistas

Una aplicación web ASP.NET Core típica en la que se usen áreas, controladores y vistas contiene lo siguiente:

  • Una estructura de carpetas de área.

  • Controladores con el atributo [Area] para asociar el controlador con el área:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • La ruta de área agregada a Program.cs:

    var builder = WebApplication.CreateBuilder(args);
    
    builder.Services.AddControllersWithViews();
    
    var app = builder.Build();
    
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    
    app.UseRouting();
    
    app.UseAuthorization();
    
    app.MapControllerRoute(
        name: "MyArea",
        pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
    
    app.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    
    app.Run();
    

Estructura de carpetas de área

Considere una aplicación que tiene dos grupos lógicos, Productos y Servicios. Mediante las áreas, la estructura de carpetas sería similar a la siguiente:

  • Nombre del proyecto
    • Áreas
      • Productos
        • Controladores
          • HomeController.cs
          • ManageController.cs
        • Vistas
          • Home
            • Index.cshtml
          • Administrar
            • Index.cshtml
            • About.cshtml
      • Servicios
        • Controladores
          • HomeController.cs
        • Vistas
          • Home
            • Index.cshtml

Aunque el diseño anterior es típico cuando se usan áreas, solo los archivos de vista tienen que usar esta estructura de carpetas. La detección de vista busca un archivo de vista de área coincidente en el orden siguiente:

/Areas/<Area-Name>/Views/<Controller-Name>/<Action-Name>.cshtml
/Areas/<Area-Name>/Views/Shared/<Action-Name>.cshtml
/Views/Shared/<Action-Name>.cshtml
/Pages/Shared/<Action-Name>.cshtml

Asociación del controlador a un área

Los controladores de área se designan con el atributo [Area]:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Docs.Samples;

namespace MVCareas.Areas.Products.Controllers;

[Area("Products")]
public class ManageController : Controller
{
    public IActionResult Index()
    {
        ViewData["routeInfo"] = ControllerContext.MyDisplayRouteInfo();
        return View();
    }

    public IActionResult About()
    {
        ViewData["routeInfo"] = ControllerContext.MyDisplayRouteInfo();
        return View();
    }
}

Adición de la ruta de área

Las rutas de área normalmente usan el enrutamiento convencional en lugar del enrutamiento mediante atributos. El enrutamiento convencional depende del orden. En general, las rutas con áreas deben colocarse antes en la tabla de rutas, ya que son más específicas que las rutas sin un área.

Se puede {area:...} usar como un token en las plantillas de ruta, si el espacio de direcciones URL es uniforme en todas las áreas:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "MyArea",
    pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

En el código anterior, exists aplica la restricción de que la ruta debe coincidir con un área. Uso de {area:...} con MapControllerRoute:

  • Es el mecanismo menos complicado para agregar enrutamiento a las áreas.
  • Une todos los controladores con el atributo [Area("Area name")].

En el código siguiente se usa MapAreaControllerRoute para crear dos rutas de área con nombre:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapAreaControllerRoute(
    name: "MyAreaProducts",
    areaName: "Products",
    pattern: "Products/{controller=Home}/{action=Index}/{id?}");

app.MapAreaControllerRoute(
    name: "MyAreaServices",
    areaName: "Services",
    pattern: "Services/{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Para más información, vea Enrutamiento de áreas.

En el código siguiente de la descarga de ejemplo se muestra la generación de vínculos con el área especificada:

<li>Anchor Tag Helper links</li>
<ul>
    <li>
        <a asp-area="Products" asp-controller="Home" asp-action="About">
            Products/Home/About
        </a>
    </li>
    <li>
        <a asp-area="Services" asp-controller="Home" asp-action="About">
            Services About
        </a>
    </li>
    <li>
        <a asp-area="" asp-controller="Home" asp-action="About">
            /Home/About
        </a>
    </li>
</ul>
<li>Html.ActionLink generated links</li>
<ul>
    <li>
        @Html.ActionLink("Product/Manage/About", "About", "Manage",
                                                new { area = "Products" })
    </li>
</ul>
<li>Url.Action generated links</li>
<ul>
    <li>
        <a href='@Url.Action("About", "Manage", new { area = "Products" })'>
            Products/Manage/About
        </a>
    </li>
</ul>

La descarga de ejemplo incluye una vista parcial que contiene:

  • Los vínculos anteriores.
  • Vínculos similares a los anteriores, excepto area que no se especifican.

En el archivo de diseño se hace referencia a la vista parcial, por lo que en todas las páginas de la aplicación se muestran los vínculos generados. Los vínculos generados sin especificar el área solo son válidos cuando se les hace referencia desde una página en el mismo área y controlador.

Cuando no se especifica el área o el controlador, el enrutamiento depende de los valores de ambiente. Los valores de ruta actuales de la solicitud actual se consideran valores de ambiente para la generación de vínculos. En muchos casos de la aplicación de ejemplo, el uso de los valores ambientales genera vínculos incorrectos con el marcado que no especifica el área.

Para más información, vea Enrutar a acciones de controlador.

Diseño Compartido para áreas con el archivo _ViewStart.cshtml

Para compartir un diseño común para toda la aplicación, mueva el archivo _ViewStart.cshtml a la carpeta raíz de la aplicación. Para obtener más información, consulte Diseño en ASP.NET Core

Carpeta raíz de la aplicación

La carpeta raíz de la aplicación es la carpeta que contiene el archivo Program.cs en una aplicación web creada con las plantillas de ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, para MVC y /Pages/_ViewImports.cshtml para las páginas Razor, no se importan a las vistas en las áreas. Use uno de los métodos siguientes para proporcionar importaciones de vistas a todas las vistas:

  • Agregue _ViewImports.cshtml a la carpeta raíz de la aplicación. Un _ViewImports.cshtml en la carpeta raíz de la aplicación se aplicará a todas las vistas de la aplicación.
  • Copie el archivo _ViewImports.cshtml en la carpeta de vista adecuada en áreas. Por ejemplo, una aplicación de páginas Razorcreada con cuentas de usuario individuales tiene un archivo _ViewImports.cshtml en las siguientes carpetas:
    • /Areas/Identity/Pages/_ViewImports.cshtml
    • /Pages/_ViewImports.cshtml

El archivo _ViewImports.cshtml normalmente contiene etiquetas auxiliares importadas, @using, e instrucciones de @inject. Para obtener más información, consulte Importar directivas compartidas.

Cambio de la carpeta de área predeterminada donde se almacenan las vistas

En el código siguiente se cambia la carpeta de área predeterminada de "Areas" a "MyAreas":

using Microsoft.AspNetCore.Mvc.Razor;

var builder = WebApplication.CreateBuilder(args);

builder.Services.Configure<RazorViewEngineOptions>(options =>
{
    options.AreaViewLocationFormats.Clear();
    options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/{1}/{0}.cshtml");
    options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/Shared/{0}.cshtml");
    options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
});

builder.Services.AddControllersWithViews();

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthorization();

app.MapControllerRoute(
    name: "MyArea",
    pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

Áreas con páginas Razor

Las áreas con páginas Razor requieren una carpeta Areas/<area name>/Pages en la raíz de la aplicación. La siguiente estructura de carpetas se usa con la aplicación de ejemplo:

  • Nombre del proyecto
    • Áreas
      • Productos
        • Páginas
          • _ViewImports
          • Acerca de
          • Índice
      • Servicios
        • Páginas
          • Administrar
            • Acerca de
            • Índice

El código siguiente de la descarga de ejemplo muestra la generación de vínculos con el área especificada (por ejemplo, asp-area="Products"):

<li>Anchor Tag Helper links</li>
<ul>
    <li>
        <a asp-area="Products" asp-page="/About">
            Products/About
        </a>
    </li>
    <li>
        <a asp-area="Services" asp-page="/Manage/About">
            Services/Manage/About
        </a>
    </li>
    <li>
        <a asp-area="" asp-page="/About">
            /About
        </a>
    </li>
</ul>
<li>Url.Page generated links</li>
<ul>
    <li>
        <a href='@Url.Page("/Manage/About", new { area = "Services" })'>
            Services/Manage/About
        </a>
    </li>
    <li>
        <a href='@Url.Page("/About", new { area = "Products" })'>
            Products/About
        </a>
    </li>
</ul>

En la descarga de ejemplo se incluye una vista parcial que contiene los vínculos anteriores y los mismos vínculos sin especificar el área. En el archivo de diseño se hace referencia a la vista parcial, por lo que en todas las páginas de la aplicación se muestran los vínculos generados. Los vínculos generados sin especificar el área solo son válidos cuando se les hace referencia desde una página de la misma área.

Cuando no se especifica el área, el enrutamiento depende de los valores ambient. Los valores de ruta actuales de la solicitud actual se consideran valores de ambiente para la generación de vínculos. En muchos casos de la aplicación de ejemplo, el uso de valores de ambiente genera vínculos incorrectos. Por ejemplo, tenga en cuenta los vínculos generados desde el código siguiente:

<li>
    <a asp-page="/Manage/About">
        Services/Manage/About
    </a>
</li>
<li>
    <a asp-page="/About">
        /About
    </a>
</li>

En el código anterior:

  • El vínculo generado a partir de <a asp-page="/Manage/About"> es correcto solo cuando la última solicitud fue de una página del área Services. Por ejemplo, /Services/Manage/, /Services/Manage/Index o /Services/Manage/About.
  • El vínculo generado a partir de <a asp-page="/About"> es correcto solo cuando la última solicitud fue de una página de /Home.
  • El código está tomado de la descarga de ejemplo.

Importación del espacio de nombres y los asistentes de etiquetas con el archivo _ViewImports

Se puede agregar un archivo _ViewImports.cshtml a la carpeta Pages de cada área para importar el espacio de nombres y las etiquetas auxiliares en cada página Razor de la carpeta.

Tenga en cuenta el área Services del código de ejemplo, que no contiene un archivo _ViewImports.cshtml. El marcado siguiente muestra la página Razor/Services/Manage/About:

@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model RPareas.Areas.Services.Pages.Manage.AboutModel
@{
    ViewData["Title"] = "Srv Mng About";
}

<div>
  ViewData["routeInfo"]:  @ViewData["routeInfo"]
</div>

<a asp-area="Products" asp-page="/Index">
    Products/Index
</a>

En el marcado anterior:

  • El nombre de clase completo debe usarse para especificar el modelo (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Los asistentes de etiquetas se habilitan mediante @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

En la descarga de ejemplo, el área Products contiene el siguiente archivo _ViewImports.cshtml:

@namespace RPareas.Areas.Products.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

El siguiente marcado muestra la página Razor/Products/About:

@page
@model AboutModel
@{
    ViewData["Title"] = "Prod About";
}

En el archivo anterior, el espacio de nombres y la directiva @addTagHelper se importan en el archivo mediante el archivo Areas/Products/Pages/_ViewImports.cshtml.

Para más información, consulte Administración del ámbito de los asistentes de etiquetas y Importar directivas compartidas.

Diseño compartido para áreas de lás páginas Razor

Para compartir un diseño común para toda la aplicación, mueva el archivo _ViewStart.cshtml a la carpeta raíz de la aplicación.

Publicación de áreas

Todos los archivos *.cshtml y los archivos que formen parte del directorio wwwroot se publicarán como resultados si <Project Sdk="Microsoft.NET.Sdk.Web"> está incluido en el archivo *.csproj.

Agregar área de MVC con Visual Studio

En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione AGREGAR nuevo elemento con scaffolding > y, a continuación, seleccione Área MVC.

Recursos adicionales

Las áreas son una característica ASP.NET utilizadas para organizar las funcionalidades relacionadas en un grupo de forma separada:

  • Espacio de nombres para el enrutamiento.
  • Estructura de carpetas para vistas y páginas Razor.

El uso de áreas crea una jerarquía para el enrutamiento añadiendo de otro parámetro de ruta, area, a controller y action, o bien a Razor de la página page.

Las áreas ofrecen una manera de dividir una aplicación web ASP.NET Core en grupos funcionales más pequeños, cada uno con su propio conjunto de páginas Razor, controladores, vistas y modelos. Un área es en realidad una estructura dentro de una aplicación. En un proyecto web ASP.NET Core, los componentes lógicos como Páginas, Modelo, Vista y Controlador se mantienen en carpetas diferentes. El runtime de ASP.NET Core usa convenciones de nomenclatura para crear la relación entre estos componentes. Para una aplicación grande, puede ser conveniente dividir la aplicación en distintas áreas de funciones de alto nivel. Por ejemplo, una aplicación de comercio electrónico con varias unidades de negocio, como las de finalización de la compra, facturación y búsqueda. Cada una de estas unidades tiene un área propia para controlar vistas, controladores, páginas Razor y modelos.

Considere el uso de áreas en un proyecto en los casos siguientes:

  • La aplicación está formada por varios componentes funcionales generales que se pueden separar de forma lógica.
  • Le interesa dividir la aplicación para que se pueda trabajar en cada área funcional de forma independiente.

Vea o descargue el código de ejemplo (cómo descargarlo). En el ejemplo de descarga se proporciona una aplicación básica para probar las áreas.

Si va a usar las páginas Razor, consulte Áreas con páginas Razor en este documento.

Áreas para controladores con vistas

Una aplicación web ASP.NET Core típica en la que se usen áreas, controladores y vistas contiene lo siguiente:

  • Una estructura de carpetas de área.

  • Controladores con el atributo [Area] para asociar el controlador con el área:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • La ruta de área agregada al inicio:

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

Estructura de carpetas de área

Considere una aplicación que tiene dos grupos lógicos, Productos y Servicios. Mediante las áreas, la estructura de carpetas sería similar a la siguiente:

  • Nombre del proyecto
    • Áreas
      • Productos
        • Controladores
          • HomeController.cs
          • ManageController.cs
        • Vistas
          • Home
            • Index.cshtml
          • Administrar
            • Index.cshtml
            • About.cshtml
      • Servicios
        • Controladores
          • HomeController.cs
        • Vistas
          • Home
            • Index.cshtml

Aunque el diseño anterior es típico cuando se usan áreas, solo los archivos de vista tienen que usar esta estructura de carpetas. La detección de vista busca un archivo de vista de área coincidente en el orden siguiente:

/Areas/<Area-Name>/Views/<Controller-Name>/<Action-Name>.cshtml
/Areas/<Area-Name>/Views/Shared/<Action-Name>.cshtml
/Views/Shared/<Action-Name>.cshtml
/Pages/Shared/<Action-Name>.cshtml

Asociación del controlador a un área

Los controladores de área se designan con el atributo [Área]:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Docs.Samples;

namespace MVCareas.Areas.Products.Controllers
{
    [Area("Products")]
    public class ManageController : Controller
    {
        public IActionResult Index()
        {
            ViewData["routeInfo"] = ControllerContext.MyDisplayRouteInfo();
            return View();
        }

        public IActionResult About()
        {
            ViewData["routeInfo"] = ControllerContext.MyDisplayRouteInfo();
            return View();
        }
    }
}

Adición de la ruta de área

Las rutas de área normalmente usan el enrutamiento convencional en lugar del enrutamiento mediante atributos. El enrutamiento convencional depende del orden. En general, las rutas con áreas deben colocarse antes en la tabla de rutas, ya que son más específicas que las rutas sin un área.

Se puede {area:...} usar como un token en las plantillas de ruta, si el espacio de direcciones URL es uniforme en todas las áreas:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

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

        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

En el código anterior, exists aplica la restricción de que la ruta debe coincidir con un área. Uso de {area:...} con MapControllerRoute:

  • Es el mecanismo menos complicado para agregar enrutamiento a las áreas.
  • Une todos los controladores con el atributo [Area("Area name")].

En el código siguiente se usa MapAreaControllerRoute para crear dos rutas de área con nombre:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }
    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapAreaControllerRoute(
            name: "MyAreaProducts",
            areaName: "Products",
            pattern: "Products/{controller=Home}/{action=Index}/{id?}");

        endpoints.MapAreaControllerRoute(
            name: "MyAreaServices",
            areaName: "Services",
            pattern: "Services/{controller=Home}/{action=Index}/{id?}");

        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

Para más información, vea Enrutamiento de áreas.

En el código siguiente de la descarga de ejemplo se muestra la generación de vínculos con el área especificada:

<li>Anchor Tag Helper links</li>
<ul>
    <li>
        <a asp-area="Products" asp-controller="Home" asp-action="About">
            Products/Home/About
        </a>
    </li>
    <li>
        <a asp-area="Services" asp-controller="Home" asp-action="About">
            Services About
        </a>
    </li>
    <li>
        <a asp-area="" asp-controller="Home" asp-action="About">
            /Home/About
        </a>
    </li>
</ul>
<li>Html.ActionLink generated links</li>
<ul>
    <li>
        @Html.ActionLink("Product/Manage/About", "About", "Manage",
                                                new { area = "Products" })
    </li>
</ul>
<li>Url.Action generated links</li>
<ul>
    <li>
        <a href='@Url.Action("About", "Manage", new { area = "Products" })'>
            Products/Manage/About
        </a>
    </li>
</ul>

La descarga de ejemplo incluye una vista parcial que contiene:

  • Los vínculos anteriores.
  • Vínculos similares a los anteriores, excepto area que no se especifican.

En el archivo de diseño se hace referencia a la vista parcial, por lo que en todas las páginas de la aplicación se muestran los vínculos generados. Los vínculos generados sin especificar el área solo son válidos cuando se les hace referencia desde una página en el mismo área y controlador.

Cuando no se especifica el área o el controlador, el enrutamiento depende de los valores de ambiente. Los valores de ruta actuales de la solicitud actual se consideran valores de ambiente para la generación de vínculos. En muchos casos de la aplicación de ejemplo, el uso de los valores ambientales genera vínculos incorrectos con el marcado que no especifica el área.

Para más información, vea Enrutar a acciones de controlador.

Diseño Compartido para áreas con el archivo _ViewStart.cshtml

Para compartir un diseño común para toda la aplicación, mantenga el_ViewStart.cshtml en la carpeta raíz de la aplicación. Para obtener más información, consulte Diseño en ASP.NET Core

Carpeta raíz de la aplicación

La carpeta raíz de la aplicación es la carpeta que contiene Startup.cs en una aplicación web creada con las plantillas de ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, para MVC y /Pages/_ViewImports.cshtml para las páginas Razor, no se importa a las vistas en áreas. Use uno de los métodos siguientes para proporcionar importaciones de vistas a todas las vistas:

  • Agregue _ViewImports.cshtml a la carpeta raíz de la aplicación. Un _ViewImports.cshtml en la carpeta raíz de la aplicación se aplicará a todas las vistas de la aplicación.
  • Copie el archivo _ViewImports.cshtml en la carpeta de vista adecuada en áreas.

El archivo _ViewImports.cshtml normalmente contiene etiquetas auxiliares importadas, @using, e instrucciones de @inject. Para obtener más información, consulte Importar directivas compartidas.

Cambio de la carpeta de área predeterminada donde se almacenan las vistas

En el código siguiente se cambia la carpeta de área predeterminada de "Areas" a "MyAreas":

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.AreaViewLocationFormats.Clear();
        options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/{1}/{0}.cshtml");
        options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/Shared/{0}.cshtml");
        options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
    });

    services.AddControllersWithViews();
}

Áreas con páginas Razor

Las áreas con páginas Razor requieren una carpeta Areas/<area name>/Pages en la raíz de la aplicación. La siguiente estructura de carpetas se usa con la aplicación de ejemplo:

  • Nombre del proyecto
    • Áreas
      • Productos
        • Páginas
          • _ViewImports
          • Acerca de
          • Índice
      • Servicios
        • Páginas
          • Administrar
            • Acerca de
            • Índice

El código siguiente de la descarga de ejemplo muestra la generación de vínculos con el área especificada (por ejemplo, asp-area="Products"):

<li>Anchor Tag Helper links</li>
<ul>
    <li>
        <a asp-area="Products" asp-page="/About">
            Products/About
        </a>
    </li>
    <li>
        <a asp-area="Services" asp-page="/Manage/About">
            Services/Manage/About
        </a>
    </li>
    <li>
        <a asp-area="" asp-page="/About">
            /About
        </a>
    </li>
</ul>
<li>Url.Page generated links</li>
<ul>
    <li>
        <a href='@Url.Page("/Manage/About", new { area = "Services" })'>
            Services/Manage/About
        </a>
    </li>
    <li>
        <a href='@Url.Page("/About", new { area = "Products" })'>
            Products/About
        </a>
    </li>
</ul>

En la descarga de ejemplo se incluye una vista parcial que contiene los vínculos anteriores y los mismos vínculos sin especificar el área. En el archivo de diseño se hace referencia a la vista parcial, por lo que en todas las páginas de la aplicación se muestran los vínculos generados. Los vínculos generados sin especificar el área solo son válidos cuando se les hace referencia desde una página de la misma área.

Cuando no se especifica el área, el enrutamiento depende de los valores ambient. Los valores de ruta actuales de la solicitud actual se consideran valores de ambiente para la generación de vínculos. En muchos casos de la aplicación de ejemplo, el uso de valores de ambiente genera vínculos incorrectos. Por ejemplo, tenga en cuenta los vínculos generados desde el código siguiente:

<li>
    <a asp-page="/Manage/About">
        Services/Manage/About
    </a>
</li>
<li>
    <a asp-page="/About">
        /About
    </a>
</li>

En el código anterior:

  • El vínculo generado a partir de <a asp-page="/Manage/About"> es correcto solo cuando la última solicitud fue de una página del área Services. Por ejemplo, /Services/Manage/, /Services/Manage/Index o /Services/Manage/About.
  • El vínculo generado a partir de <a asp-page="/About"> es correcto solo cuando la última solicitud fue de una página de /Home.
  • El código está tomado de la descarga de ejemplo.

Importación del espacio de nombres y los asistentes de etiquetas con el archivo _ViewImports

Se puede agregar un archivo _ViewImports.cshtml a la carpeta Páginas de cada área para importar el espacio de nombres y los asistentes de etiquetas en cada página Razor de la carpeta.

Tenga en cuenta el área Servicios del código de ejemplo, que no contiene un archivo _ViewImports.cshtml. El marcado siguiente muestra la página Razor/Services/Manage/About:

@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model RPareas.Areas.Services.Pages.Manage.AboutModel
@{
    ViewData["Title"] = "Srv Mng About";
}

<a asp-area="Products" asp-page="/Index">
    Products/Index
</a>

En el marcado anterior:

  • El nombre de clase completo debe usarse para especificar el modelo (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Los asistentes de etiquetas se habilitan mediante @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

En la descarga de ejemplo, el área Productos contiene el siguiente archivo _ViewImports.cshtml:

@namespace RPareas.Areas.Products.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

El siguiente marcado muestra la página Razor/Products/About:

@page
@model AboutModel
@{
    ViewData["Title"] = "Prod About";
}

En el archivo anterior, el espacio de nombres y la directiva @addTagHelper se importan en el archivo mediante el archivo Areas/Products/Pages/_ViewImports.cshtml.

Para más información, consulte Administración del ámbito de los asistentes de etiquetas y Importar directivas compartidas.

Diseño compartido para áreas de lás páginas Razor

Para compartir un diseño común para toda la aplicación, mueva _ViewStart.cshtml a la carpeta raíz de la aplicación.

Publicación de áreas

Todos los archivos *.cshtml y los archivos que formen parte del directorio wwwroot se publicarán como resultados si <Project Sdk="Microsoft.NET.Sdk.Web"> está incluido en el archivo *.csproj.

Agregar área de MVC con Visual Studio

En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione AGREGAR nuevo elemento con scaffolding > y, a continuación, seleccione Área MVC.

Las áreas son una característica de ASP.NET que se usa para organizar funciones relacionadas en un grupo como un espacio de nombres independiente (para el enrutamiento) y una estructura de carpetas (para las vistas). El uso de áreas crea una jerarquía para el enrutamiento añadiendo de otro parámetro de ruta, area, a controller y action, o bien a Razor de la página page.

Las áreas ofrecen una manera de dividir una aplicación web ASP.NET Core en grupos funcionales más pequeños, cada uno con su propio conjunto de páginas Razor, controladores, vistas y modelos. Un área es en realidad una estructura dentro de una aplicación. En un proyecto web ASP.NET Core, los componentes lógicos como Páginas, Modelo, Vista y Controlador se mantienen en carpetas diferentes. El runtime de ASP.NET Core usa convenciones de nomenclatura para crear la relación entre estos componentes. Para una aplicación grande, puede ser conveniente dividir la aplicación en distintas áreas de funciones de alto nivel. Por ejemplo, una aplicación de comercio electrónico con varias unidades de negocio, como las de finalización de la compra, facturación y búsqueda. Cada una de estas unidades tiene un área propia para controlar vistas, controladores, páginas Razor y modelos.

Considere el uso de áreas en un proyecto en los casos siguientes:

  • La aplicación está formada por varios componentes funcionales generales que se pueden separar de forma lógica.
  • Le interesa dividir la aplicación para que se pueda trabajar en cada área funcional de forma independiente.

Vea o descargue el código de ejemplo (cómo descargarlo). En el ejemplo de descarga se proporciona una aplicación básica para probar las áreas.

Si va a usar las páginas Razor, consulte Áreas con páginas Razor en este documento.

Áreas para controladores con vistas

Una aplicación web ASP.NET Core típica en la que se usen áreas, controladores y vistas contiene lo siguiente:

  • Una estructura de carpetas de área.

  • Controladores con el atributo [Area] para asociar el controlador con el área:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • La ruta de área agregada al inicio:

    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?}");
    });
    

Estructura de carpetas de área

Considere una aplicación que tiene dos grupos lógicos, Productos y Servicios. Mediante las áreas, la estructura de carpetas sería similar a la siguiente:

  • Nombre del proyecto
    • Áreas
      • Productos
        • Controladores
          • HomeController.cs
          • ManageController.cs
        • Vistas
          • Home
            • Index.cshtml
          • Administrar
            • Index.cshtml
            • About.cshtml
      • Servicios
        • Controladores
          • HomeController.cs
        • Vistas
          • Home
            • Index.cshtml

Aunque el diseño anterior es típico cuando se usan áreas, solo los archivos de vista tienen que usar esta estructura de carpetas. La detección de vista busca un archivo de vista de área coincidente en el orden siguiente:

/Areas/<Area-Name>/Views/<Controller-Name>/<Action-Name>.cshtml
/Areas/<Area-Name>/Views/Shared/<Action-Name>.cshtml
/Views/Shared/<Action-Name>.cshtml
/Pages/Shared/<Action-Name>.cshtml

Asociación del controlador a un área

Los controladores de área se designan con el atributo [Área]:

using Microsoft.AspNetCore.Mvc;

namespace MVCareas.Areas.Products.Controllers
{
    [Area("Products")]
    public class ManageController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }

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

Adición de la ruta de área

Las rutas de área normalmente usan el enrutamiento convencional en lugar del enrutamiento mediante atributos. El enrutamiento convencional depende del orden. En general, las rutas con áreas deben colocarse antes en la tabla de rutas, ya que son más específicas que las rutas sin un área.

Se puede {area:...} usar como un token en las plantillas de ruta, si el espacio de direcciones URL es uniforme en todas las áreas:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    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?}");
    });
}

En el código anterior, exists aplica la restricción de que la ruta debe coincidir con un área. El uso de {area:...} es el mecanismo menos complicado para agregar enrutamiento a las áreas.

En el código siguiente se usa MapAreaRoute para crear dos rutas de área con nombre:

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseMvc(routes =>
    {
        routes.MapAreaRoute(
            name: "MyAreaProducts",
            areaName:"Products",
            template: "Products/{controller=Home}/{action=Index}/{id?}");

        routes.MapAreaRoute(
            name: "MyAreaServices",
            areaName: "Services",
            template: "Services/{controller=Home}/{action=Index}/{id?}");

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

Cuando use MapAreaRoute con ASP.NET Core 2.2, vea este problema de GitHub.

Para más información, vea Enrutamiento de áreas.

En el código siguiente de la descarga de ejemplo se muestra la generación de vínculos con el área especificada:

<li>Anchor Tag Helper links</li>
<ul>
    <li>
        <a asp-area="Products" asp-controller="Home" asp-action="About">
            Products/Home/About
        </a>
    </li>
    <li>
        <a asp-area="Services" asp-controller="Home" asp-action="About">
            Services About
        </a>
    </li>
    <li>
        <a asp-area="" asp-controller="Home" asp-action="About">
            /Home/About
        </a>
    </li>
</ul>
<li>Html.ActionLink generated links</li>
<ul>
    <li>
        @Html.ActionLink("Product/Manage/About", "About", "Manage", 
                                                new { area = "Products" })
    </li>
</ul>
<li>Url.Action generated links</li>
<ul>
    <li>
        <a href='@Url.Action("About", "Manage", new { area = "Products" })'>
            Products/Manage/About
        </a>
    </li>
</ul>

Los vínculos generados con el código anterior son válidos en cualquier parte de la aplicación.

En la descarga de ejemplo se incluye una vista parcial que contiene los vínculos anteriores y los mismos vínculos sin especificar el área. En el archivo de diseño se hace referencia a la vista parcial, por lo que en todas las páginas de la aplicación se muestran los vínculos generados. Los vínculos generados sin especificar el área solo son válidos cuando se les hace referencia desde una página en el mismo área y controlador.

Cuando no se especifica el área o el controlador, el enrutamiento depende de los valores de ambiente. Los valores de ruta actuales de la solicitud actual se consideran valores de ambiente para la generación de vínculos. En muchos casos de la aplicación de ejemplo, el uso de valores de ambiente genera vínculos incorrectos.

Para más información, vea Enrutar a acciones de controlador.

Diseño Compartido para áreas con el archivo _ViewStart.cshtml

Para compartir un diseño común para toda la aplicación, mueva _ViewStart.cshtml a la carpeta raíz de la aplicación.

_ViewImports.cshtml

En esta ubicación estándar, /Views/_ViewImports.cshtml no se aplica a las áreas. Para usar las etiquetas auxiliares comunes, @using o @inject en su zona, asegúrese de que un archivo _ViewImports.cshtml adecuado se aplica a las vistas del área. Si quiere el mismo comportamiento en todas las vistas, mueva /Views/_ViewImports.cshtml a la raíz de la aplicación.

Cambio de la carpeta de área predeterminada donde se almacenan las vistas

En el código siguiente se cambia la carpeta de área predeterminada de "Areas" a "MyAreas":

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.AreaViewLocationFormats.Clear();
        options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/{1}/{0}.cshtml");
        options.AreaViewLocationFormats.Add("/MyAreas/{2}/Views/Shared/{0}.cshtml");
        options.AreaViewLocationFormats.Add("/Views/Shared/{0}.cshtml");
    });

    services.AddMvc();
}

Áreas con páginas Razor

Las áreas con páginas Razor requieren una carpeta Areas/<area name>/Pages en la raíz de la aplicación. La siguiente estructura de carpetas se usa con la aplicación de ejemplo:

  • Nombre del proyecto
    • Áreas
      • Productos
        • Páginas
          • _ViewImports
          • Acerca de
          • Índice
      • Servicios
        • Páginas
          • Administrar
            • Acerca de
            • Índice

El código siguiente de la descarga de ejemplo muestra la generación de vínculos con el área especificada (por ejemplo, asp-area="Products"):

<li>Anchor Tag Helper links</li>
<ul>
    <li>
        <a asp-area="Products" asp-page="/About">
            Products/About
        </a>
    </li>
    <li>
        <a asp-area="Services" asp-page="/Manage/About">
            Services/Manage/About
        </a>
    </li>
    <li>
        <a asp-area="" asp-page="/About">
            /About
        </a>
    </li>
</ul>
<li>Url.Page generated links</li>
<ul>
    <li>
        <a href='@Url.Page("/Manage/About", new { area = "Services" })'>
            Services/Manage/About
        </a>
    </li>
    <li>
        <a href='@Url.Page("/About", new { area = "Products" })'>
            Products/About
        </a>
    </li>
</ul>

Los vínculos generados con el código anterior son válidos en cualquier parte de la aplicación.

En la descarga de ejemplo se incluye una vista parcial que contiene los vínculos anteriores y los mismos vínculos sin especificar el área. En el archivo de diseño se hace referencia a la vista parcial, por lo que en todas las páginas de la aplicación se muestran los vínculos generados. Los vínculos generados sin especificar el área solo son válidos cuando se les hace referencia desde una página de la misma área.

Cuando no se especifica el área, el enrutamiento depende de los valores ambient. Los valores de ruta actuales de la solicitud actual se consideran valores de ambiente para la generación de vínculos. En muchos casos de la aplicación de ejemplo, el uso de valores de ambiente genera vínculos incorrectos. Por ejemplo, tenga en cuenta los vínculos generados desde el código siguiente:

<li>
    <a asp-page="/Manage/About">
        Services/Manage/About
    </a>
</li>
<li>
    <a asp-page="/About">
        /About
    </a>
</li>

En el código anterior:

  • El vínculo generado a partir de <a asp-page="/Manage/About"> es correcto solo cuando la última solicitud fue de una página del área Services. Por ejemplo, /Services/Manage/, /Services/Manage/Index o /Services/Manage/About.
  • El vínculo generado a partir de <a asp-page="/About"> es correcto solo cuando la última solicitud fue de una página de /Home.
  • El código está tomado de la descarga de ejemplo.

Importación del espacio de nombres y los asistentes de etiquetas con el archivo _ViewImports

Se puede agregar un archivo _ViewImports.cshtml a la carpeta Páginas de cada área para importar el espacio de nombres y los asistentes de etiquetas en cada página Razor de la carpeta.

Tenga en cuenta el área Servicios del código de ejemplo, que no contiene un archivo _ViewImports.cshtml. El marcado siguiente muestra la página Razor/Services/Manage/About:

@page
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@model RPareas.Areas.Services.Pages.Manage.AboutModel
@{
    ViewData["Title"] = "Srv Mng About";
}

<h2>/Services/Manage/About</h2>

<a asp-area="Products" asp-page="/Index">
    Products/Index
</a>

En el marcado anterior:

  • El nombre de dominio completo debe usarse para especificar el modelo (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Los asistentes de etiquetas se habilitan mediante @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

En la descarga de ejemplo, el área Productos contiene el siguiente archivo _ViewImports.cshtml:

@namespace RPareas.Areas.Products.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

El siguiente marcado muestra la página Razor/Products/About:

@page
@model AboutModel
@{
    ViewData["Title"] = "Prod About";
}

<h2>Products/About</h2>

<a asp-area="Services" asp-page="/Manage/About">
    Services/Manage/About
</a>

En el archivo anterior, el espacio de nombres y la directiva @addTagHelper se importan en el archivo mediante el archivo Areas/Products/Pages/_ViewImports.cshtml.

Para más información, consulte Administración del ámbito de los asistentes de etiquetas y Importar directivas compartidas.

Diseño compartido para áreas de lás páginas Razor

Para compartir un diseño común para toda la aplicación, mueva _ViewStart.cshtml a la carpeta raíz de la aplicación.

Publicación de áreas

Todos los archivos *.cshtml y los archivos que formen parte del directorio wwwroot se publicarán como resultados si <Project Sdk="Microsoft.NET.Sdk.Web"> está incluido en el archivo *.csproj.