Compartilhar via


Áreas no ASP.NET Core

Por Dhananjay Kumar e Rick Anderson

As áreas são um recurso do ASP.NET usado para organizar funcionalidades relacionadas em um grupo como os itens a seguir, em separado:

  • Namespace para roteamento.
  • Estrutura de pastas para exibições e Páginas do Razor.

O uso de áreas cria uma hierarquia para fins de roteamento, adicionando outro parâmetro de rota, area, a controller e action ou a uma RazorPáginapage.

As áreas proporcionam uma maneira de particionar um aplicativo Web do ASP.NET Core em grupos funcionais menores, cada um com seu próprio conjunto de Páginas Razor, controladores, exibições e modelos. Uma área é efetivamente uma estrutura MVC dentro de um aplicativo. Em um projeto Web do ASP.NET Core, os componentes lógicos como páginas, modelo, controlador e modo de exibição são mantidos em pastas diferentes. O runtime do ASP.NET Core usa as convenções de nomenclatura para criar a relação entre esses componentes. Para um aplicativo grande, pode ser vantajoso particionar o aplicativo em áreas de nível alto separadas de funcionalidade. Por exemplo, um aplicativo de comércio eletrônico com várias unidades de negócios, como check-out, cobrança e pesquisa. Cada uma dessas unidades tem sua própria área para conter exibições, controladores, Páginas Razor e modelos.

Considere o uso de Áreas em um projeto quando:

  • O aplicativo é composto por vários componentes funcionais de alto nível que podem ser separados logicamente.
  • Você deseja particionar o aplicativo para que cada área funcional possa ser trabalhada de forma independente.

Se você estiver usando o Páginas Razor, consulte Áreas com Páginas Razor nesse documento.

Áreas para os controladores com modos de exibição

Um aplicativo Web do ASP.NET Core típico usando áreas, controladores e exibições contém o seguinte:

  • Uma estrutura de pastas da área.

  • Controladores decorados com o atributo [Area] para associar o controlador à área:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • A rota de área adicionada à inicializaçãoProgram.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();
    

Estrutura de pastas da área

Considere um aplicativo que tem dois grupos lógicos, Produtos e Serviços. Usando áreas, a estrutura de pastas seria semelhante ao seguinte:

  • Nome do projeto
    • Áreas
      • Produtos
        • Controladores
          • HomeController.cs
          • ManageController.cs
        • Exibições
          • Home
            • Index.cshtml
          • Gerenciar
            • Index.cshtml
            • About.cshtml
      • Serviços
        • Controladores
          • HomeController.cs
        • Exibições
          • Home
            • Index.cshtml

Enquanto o layout anterior é típico ao usar áreas, somente os arquivos de exibição são necessários para usar essa estrutura de pastas. Pesquisas de descoberta de exibição para um arquivo de exibição de área correspondente, na seguinte ordem:

/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

Associar o controlador a uma área

Os controladores de área são designados com o 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();
    }
}

Adicionar rota de área

Rotas de área normalmente usam roteamento convencional, em vez de roteamento de atributo. O roteamento convencional é dependente da ordem. De modo geral, rotas com áreas devem ser colocadas mais no início na tabela de rotas, uma vez que são mais específicas que rotas sem uma área.

{area:...} pode ser usado como um token em modelos de rota, se o espaço de URL é uniforme entre todas as á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();

No código anterior, exists aplica uma restrição de que a rota deve corresponder a uma área. Usar {area:...} com MapControllerRoute:

  • Esse é o mecanismo menos complicado para a adição de roteamento para áreas.
  • Isso corresponde todos os controladores com o atributo [Area("Area name")].

O código a seguir usa MapAreaControllerRoute para criar duas rotas de área nomeadas:

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 obter mais informações, veja Roteamento de área.

O código a seguir do download do exemplo mostra geração de link com a á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>

O download de exemplo inclui uma exibição parcial que contém:

  • Os links anteriores.
  • Links semelhantes aos anteriores, exceto area, não são especificados.

A exibição parcial é referenciada no arquivo de layout, portanto, todas as páginas no aplicativo exibem os links gerados. Os links gerados sem especificar a área só são válidos quando referenciados de uma página na mesma área e no mesmo controlador.

Quando a área ou o controlador não for especificado, o roteamento dependerá dos valores do ambiente. Os valores de rota atuais da solicitação atual são considerados valores de ambiente para a geração de link. Em muitos casos para o aplicativo de exemplo, o uso dos valores de ambiente gera links incorretos com a marcação que não especifica a área.

Para obter mais informações, veja Roteamento para ações do controlador.

Layout compartilhado para áreas usando o arquivo _ViewStart.cshtml

Para compartilhar um layout comum para o aplicativo inteiro, mova o _ViewStart.cshtml para a pasta raiz do aplicativo. Saiba mais em Layout no ASP.NET Core.

Pasta raiz do aplicativo

A pasta raiz do aplicativo é a pasta que contém o arquivo Program.cs em um aplicativo Web criado com os modelos de ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, para MVC e /Pages/_ViewImports.cshtml para Páginas Razor não é importado para exibições em áreas. Use uma das seguintes abordagens para fornecer importações de exibição para todos os modos de exibição:

  • Adicione _ViewImports.cshtml à pasta raiz do aplicativo. Um _ViewImports.cshtml na pasta raiz do aplicativo será aplicado a todos os modos de exibição no aplicativo.
  • Copie o arquivo _ViewImports.cshtml para a pasta de exibição apropriada em áreas. Por exemplo, um aplicativo de Páginas Razor criado com contas de usuário individuais tem um arquivo _ViewImports.cshtml nas seguintes pastas:
    • /Areas/Identity/Pages/_ViewImports.cshtml
    • /Pages/_ViewImports.cshtml

O arquivo _ViewImports.cshtml normalmente contém importações de Auxiliares de Marca, @using e declarações @inject. Para obter mais informações, consulte Como Importar Diretivas Compartilhadas.

Alterar a pasta de área padrão em que as exibições são armazenadas

O código a seguir altera a pasta da área padrão de "Areas" para "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 com Páginas Razor

As áreas com Páginas Razor exigem uma pasta Areas/<area name>/Pages na raiz do aplicativo. A seguinte estrutura de pasta é usada com o aplicativo de exemplo:

  • Nome do projeto
    • Áreas
      • Produtos
        • Pages (Páginas)
          • _ViewImports
          • Sobre
          • Índice
      • Serviços
        • Pages (Páginas)
          • Gerenciar
            • Sobre
            • Índice

O código a seguir do download do exemplo mostra a geração de links com a área especificada (por exemplo, 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>

O download de exemplo inclui uma exibição parcial que contém os links anteriores e os mesmos links sem especificar a área. A exibição parcial é referenciada no arquivo de layout, portanto, todas as páginas no aplicativo exibem os links gerados. Os links gerados sem especificar a área só são válidos quando referenciados de uma página na mesma área.

Quando a área não for especificada, o roteamento dependerá dos valores do ambiente. Os valores de rota atuais da solicitação atual são considerados valores de ambiente para a geração de link. Em muitos casos, para o aplicativo de exemplo, usar os valores de ambiente gera links incorretos. Por exemplo, considere os links gerados a partir do código a seguir:

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

Para o código anterior:

  • O link gerado de <a asp-page="/Manage/About"> só estará correto quando a última solicitação tiver sido para uma página na área Services. Por exemplo, /Services/Manage/, /Services/Manage/Index ou /Services/Manage/About.
  • O link gerado a partir <a asp-page="/About"> só estará correto quando a última solicitação tiver sido para uma página na área /Home.
  • O código vem do download de exemplo.

Importar o namespace e os Auxiliares de marca com o arquivo _ViewImports

Um arquivo _ViewImports.cshtml pode ser adicionado a cada pasta Páginas da área para importar o namespace e os Auxiliares de Marcação para cada Página Razor na pasta.

Considere a área Serviços do código de exemplo, que não contém um arquivo _ViewImports.cshtml. A marcação a seguir mostra a Página /Services/Manage/AboutRazor:

@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>

Na marcação anterior:

  • O nome de domínio totalmente qualificado deve ser usado para especificar o modelo (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Os Auxiliares de Marcação são habilitados por @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

No download de exemplo, a área Produtos contém o seguinte arquivo _ViewImports.cshtml:

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

A marcação a seguir mostra a Página /Products/AboutRazor:

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

No arquivo anterior, o namespace e a diretiva @addTagHelper são importados para o arquivo por meio do arquivo Areas/Products/Pages/_ViewImports.cshtml.

Para saber mais, confira Gerenciar o escopo do Auxiliar de Marcação e Importar diretivas compartilhadas.

Layout compartilhado para Áreas de Páginas Razor

Para compartilhar um layout comum para o aplicativo inteiro, mova o _ViewStart.cshtml para a pasta raiz do aplicativo.

Publicando áreas

Todos os arquivos *.cshtml e os arquivos do diretório wwwroot são publicados em uma saída quando <Project Sdk="Microsoft.NET.Sdk.Web"> são incluídos no arquivo *.csproj.

Adicionar área do MVC com o Visual Studio

Em Gerenciador de Soluções, clique com o botão direito do mouse no projeto e selecione ADICIONAR > Novo Item Scaffolded e selecione Área MVC.

Recursos adicionais

As áreas são um recurso do ASP.NET usado para organizar funcionalidades relacionadas em um grupo como os itens a seguir, em separado:

  • Namespace para roteamento.
  • Estrutura de pastas para exibições e Páginas do Razor.

O uso de áreas cria uma hierarquia para fins de roteamento, adicionando outro parâmetro de rota, area, a controller e action ou a uma RazorPáginapage.

As áreas proporcionam uma maneira de particionar um aplicativo Web do ASP.NET Core em grupos funcionais menores, cada um com seu próprio conjunto de Páginas Razor, controladores, exibições e modelos. Uma área é efetivamente uma estrutura MVC dentro de um aplicativo. Em um projeto Web do ASP.NET Core, os componentes lógicos como páginas, modelo, controlador e modo de exibição são mantidos em pastas diferentes. O runtime do ASP.NET Core usa as convenções de nomenclatura para criar a relação entre esses componentes. Para um aplicativo grande, pode ser vantajoso particionar o aplicativo em áreas de nível alto separadas de funcionalidade. Por exemplo, um aplicativo de comércio eletrônico com várias unidades de negócios, como check-out, cobrança e pesquisa. Cada uma dessas unidades tem sua própria área para conter exibições, controladores, Páginas Razor e modelos.

Considere o uso de Áreas em um projeto quando:

  • O aplicativo é composto por vários componentes funcionais de alto nível que podem ser separados logicamente.
  • Você deseja particionar o aplicativo para que cada área funcional possa ser trabalhada de forma independente.

Exibir ou baixar um código de exemplo (como baixar). O exemplo de download fornece um aplicativo básico para áreas de teste.

Se você estiver usando o Páginas Razor, consulte Áreas com Páginas Razor nesse documento.

Áreas para os controladores com modos de exibição

Um aplicativo Web do ASP.NET Core típico usando áreas, controladores e exibições contém o seguinte:

  • Uma estrutura de pastas da área.

  • Controladores decorados com o atributo [Area] para associar o controlador à área:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • A rota de área adicionada à inicialização:

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

Estrutura de pastas da área

Considere um aplicativo que tem dois grupos lógicos, Produtos e Serviços. Usando áreas, a estrutura de pastas seria semelhante ao seguinte:

  • Nome do projeto
    • Áreas
      • Produtos
        • Controladores
          • HomeController.cs
          • ManageController.cs
        • Exibições
          • Home
            • Index.cshtml
          • Gerenciar
            • Index.cshtml
            • About.cshtml
      • Serviços
        • Controladores
          • HomeController.cs
        • Exibições
          • Home
            • Index.cshtml

Enquanto o layout anterior é típico ao usar áreas, somente os arquivos de exibição são necessários para usar essa estrutura de pastas. Pesquisas de descoberta de exibição para um arquivo de exibição de área correspondente, na seguinte ordem:

/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

Associar o controlador a uma área

Controladores de área são designados com o 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();
        }
    }
}

Adicionar rota de área

Rotas de área normalmente usam roteamento convencional, em vez de roteamento de atributo. O roteamento convencional é dependente da ordem. De modo geral, rotas com áreas devem ser colocadas mais no início na tabela de rotas, uma vez que são mais específicas que rotas sem uma área.

{area:...} pode ser usado como um token em modelos de rota, se o espaço de URL é uniforme entre todas as á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?}");
    });
}

No código anterior, exists aplica uma restrição de que a rota deve corresponder a uma área. Usar {area:...} com MapControllerRoute:

  • Esse é o mecanismo menos complicado para a adição de roteamento para áreas.
  • Isso corresponde todos os controladores com o atributo [Area("Area name")].

O código a seguir usa MapAreaControllerRoute para criar duas rotas de área nomeadas:

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 obter mais informações, veja Roteamento de área.

O código a seguir do download do exemplo mostra geração de link com a á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>

O download de exemplo inclui uma exibição parcial que contém:

  • Os links anteriores.
  • Links semelhantes aos anteriores, exceto area, não são especificados.

A exibição parcial é referenciada no arquivo de layout, portanto, todas as páginas no aplicativo exibem os links gerados. Os links gerados sem especificar a área só são válidos quando referenciados de uma página na mesma área e no mesmo controlador.

Quando a área ou o controlador não for especificado, o roteamento dependerá dos valores do ambiente. Os valores de rota atuais da solicitação atual são considerados valores de ambiente para a geração de link. Em muitos casos para o aplicativo de exemplo, o uso dos valores de ambiente gera links incorretos com a marcação que não especifica a área.

Para obter mais informações, veja Roteamento para ações do controlador.

Layout compartilhado para áreas usando o arquivo _ViewStart.cshtml

Para compartilhar um layout comum para o aplicativo inteiro, mantenha o _ViewStart.cshtml na pasta raiz do aplicativo. Saiba mais em Layout no ASP.NET Core.

Pasta raiz do aplicativo

A pasta raiz do aplicativo é a pasta que contém o Startup.cs em um aplicativo Web criado com os modelos do ASP.NET Core.

_ViewImports.cshtml

/Views/_ViewImports.cshtml, para MVC e /Pages/_ViewImports.cshtml para Páginas Razor, não é importado para exibições em áreas. Use uma das seguintes abordagens para fornecer importações de exibição para todos os modos de exibição:

  • Adicione _ViewImports.cshtml à pasta raiz do aplicativo. Um _ViewImports.cshtml na pasta raiz do aplicativo será aplicado a todos os modos de exibição no aplicativo.
  • Copie o arquivo _ViewImports.cshtml para a pasta de exibição apropriada em áreas.

O arquivo _ViewImports.cshtml_ViewImports.cshtml normalmente contém importações de Auxiliares de Marca@using, e declarações@inject. Para obter mais informações, consulte Como Importar Diretivas Compartilhadas.

Alterar a pasta de área padrão em que as exibições são armazenadas

O código a seguir altera a pasta da área padrão de "Areas" para "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 com Páginas Razor

As áreas com Páginas Razor exigem uma pasta Areas/<area name>/Pages na raiz do aplicativo. A seguinte estrutura de pasta é usada com o aplicativo de exemplo:

  • Nome do projeto
    • Áreas
      • Produtos
        • Pages (Páginas)
          • _ViewImports
          • Sobre
          • Índice
      • Serviços
        • Pages (Páginas)
          • Gerenciar
            • Sobre
            • Índice

O código a seguir do download do exemplo mostra a geração de links com a área especificada (por exemplo, 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>

O download de exemplo inclui uma exibição parcial que contém os links anteriores e os mesmos links sem especificar a área. A exibição parcial é referenciada no arquivo de layout, portanto, todas as páginas no aplicativo exibem os links gerados. Os links gerados sem especificar a área só são válidos quando referenciados de uma página na mesma área.

Quando a área não for especificada, o roteamento dependerá dos valores do ambiente. Os valores de rota atuais da solicitação atual são considerados valores de ambiente para a geração de link. Em muitos casos, para o aplicativo de exemplo, usar os valores de ambiente gera links incorretos. Por exemplo, considere os links gerados a partir do código a seguir:

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

Para o código anterior:

  • O link gerado de <a asp-page="/Manage/About"> só estará correto quando a última solicitação tiver sido para uma página na área Services. Por exemplo, /Services/Manage/, /Services/Manage/Index ou /Services/Manage/About.
  • O link gerado a partir <a asp-page="/About"> só estará correto quando a última solicitação tiver sido para uma página na área /Home.
  • O código vem do download de exemplo.

Importar o namespace e os Auxiliares de marca com o arquivo _ViewImports

Um arquivo _ViewImports.cshtml pode ser adicionado a cada pasta Páginas da área para importar o namespace e os Auxiliares de Marcação para cada Página Razor na pasta.

Considere a área Serviços do código de exemplo, que não contém um arquivo _ViewImports.cshtml. A marcação a seguir mostra a Página /Services/Manage/AboutRazor:

@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>

Na marcação anterior:

  • O nome de domínio totalmente qualificado deve ser usado para especificar o modelo (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Os Auxiliares de Marcação são habilitados por @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

No download de exemplo, a área Produtos contém o seguinte arquivo _ViewImports.cshtml:

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

A marcação a seguir mostra a Página /Products/AboutRazor:

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

No arquivo anterior, o namespace e a diretiva @addTagHelper são importados para o arquivo por meio do arquivo Areas/Products/Pages/_ViewImports.cshtml.

Para saber mais, confira Gerenciar o escopo do Auxiliar de Marcação e Importar diretivas compartilhadas.

Layout compartilhado para Áreas de Páginas Razor

Para compartilhar um layout comum para o aplicativo inteiro, mova o _ViewStart.cshtml para a pasta raiz do aplicativo.

Publicando áreas

Todos os arquivos *.cshtml e os arquivos do diretório wwwroot são publicados em uma saída quando <Project Sdk="Microsoft.NET.Sdk.Web"> são incluídos no arquivo *.csproj.

Adicionar área do MVC com o Visual Studio

Em Gerenciador de Soluções, clique com o botão direito do mouse no projeto e selecione ADICIONAR > Novo Item Scaffolded e selecione Área MVC.

Áreas são um recurso do ASP.NET usado para organizar funcionalidades relacionadas em um grupo como um namespace separado (para roteamento) e uma estrutura de pastas (para exibições). O uso de áreas cria uma hierarquia para fins de roteamento, adicionando outro parâmetro de rota, area, a controller e action ou a uma RazorPáginapage.

As áreas proporcionam uma maneira de particionar um aplicativo Web do ASP.NET Core em grupos funcionais menores, cada um com seu próprio conjunto de Páginas Razor, controladores, exibições e modelos. Uma área é efetivamente uma estrutura MVC dentro de um aplicativo. Em um projeto Web do ASP.NET Core, os componentes lógicos como páginas, modelo, controlador e modo de exibição são mantidos em pastas diferentes. O runtime do ASP.NET Core usa as convenções de nomenclatura para criar a relação entre esses componentes. Para um aplicativo grande, pode ser vantajoso particionar o aplicativo em áreas de nível alto separadas de funcionalidade. Por exemplo, um aplicativo de comércio eletrônico com várias unidades de negócios, como check-out, cobrança e pesquisa. Cada uma dessas unidades tem sua própria área para conter exibições, controladores, Páginas Razor e modelos.

Considere o uso de Áreas em um projeto quando:

  • O aplicativo é composto por vários componentes funcionais de alto nível que podem ser separados logicamente.
  • Você deseja particionar o aplicativo para que cada área funcional possa ser trabalhada de forma independente.

Exibir ou baixar um código de exemplo (como baixar). O exemplo de download fornece um aplicativo básico para áreas de teste.

Se você estiver usando o Páginas Razor, consulte Áreas com Páginas Razor nesse documento.

Áreas para os controladores com modos de exibição

Um aplicativo Web do ASP.NET Core típico usando áreas, controladores e exibições contém o seguinte:

  • Uma estrutura de pastas da área.

  • Controladores decorados com o atributo [Area] para associar o controlador à área:

    [Area("Products")]
    public class ManageController : Controller
    {
    
  • A rota de área adicionada à inicialização:

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

Estrutura de pastas da área

Considere um aplicativo que tem dois grupos lógicos, Produtos e Serviços. Usando áreas, a estrutura de pastas seria semelhante ao seguinte:

  • Nome do projeto
    • Áreas
      • Produtos
        • Controladores
          • HomeController.cs
          • ManageController.cs
        • Exibições
          • Home
            • Index.cshtml
          • Gerenciar
            • Index.cshtml
            • About.cshtml
      • Serviços
        • Controladores
          • HomeController.cs
        • Exibições
          • Home
            • Index.cshtml

Enquanto o layout anterior é típico ao usar áreas, somente os arquivos de exibição são necessários para usar essa estrutura de pastas. Pesquisas de descoberta de exibição para um arquivo de exibição de área correspondente, na seguinte ordem:

/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

Associar o controlador a uma área

Controladores de área são designados com o atributo [Area]:

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();
        }
    }
}

Adicionar rota de área

Rotas de área normalmente usam o roteamento convencional, em vez de roteamento de atributo. O roteamento convencional é dependente da ordem. De modo geral, rotas com áreas devem ser colocadas mais no início na tabela de rotas, uma vez que são mais específicas que rotas sem uma área.

{area:...} pode ser usado como um token em modelos de rota, se o espaço de URL é uniforme entre todas as á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?}");
    });
}

No código anterior, exists aplica uma restrição de que a rota deve corresponder a uma área. Usar {area:...} é o mecanismo menos complicado para a adição de roteamento para áreas.

O código a seguir usa MapAreaRoute para criar duas rotas de área nomeadas:

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

Ao usar MapAreaRoute com o ASP.NET Core 2.2, veja este problema do GitHub.

Para obter mais informações, veja Roteamento de área.

O código a seguir do download do exemplo mostra geração de link com a á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>

Os links gerados com o código anterior são válidos em qualquer lugar no aplicativo.

O download de exemplo inclui uma exibição parcial que contém os links anteriores e os mesmos links sem especificar a área. A exibição parcial é referenciada no arquivo de layout, portanto, todas as páginas no aplicativo exibem os links gerados. Os links gerados sem especificar a área só são válidos quando referenciados de uma página na mesma área e no mesmo controlador.

Quando a área ou o controlador não for especificado, o roteamento dependerá dos valores do ambiente. Os valores de rota atuais da solicitação atual são considerados valores de ambiente para a geração de link. Em muitos casos, para o aplicativo de exemplo, usar os valores de ambiente gera links incorretos.

Para obter mais informações, veja Roteamento para ações do controlador.

Layout compartilhado para áreas usando o arquivo _ViewStart.cshtml

Para compartilhar um layout comum para o aplicativo inteiro, mova o _ViewStart.cshtml para a pasta raiz do aplicativo.

_ViewImports.cshtml

Em sua localização padrão, /Views/_ViewImports.cshtml não se aplica a áreas. Para usar Auxiliares de Marca comuns, @using ou @inject em sua área, certifique-se que um arquivo _ViewImports.cshtml apropriado se aplica às suas exibições de área. Se você desejar o mesmo comportamento em todas as suas exibições, mova /Views/_ViewImports.cshtml para a raiz do aplicativo.

Alterar a pasta de área padrão em que as exibições são armazenadas

O código a seguir altera a pasta da área padrão de "Areas" para "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 com Páginas Razor

As áreas com Páginas Razor exigem uma pasta Areas/<area name>/Pages na raiz do aplicativo. A seguinte estrutura de pasta é usada com o aplicativo de exemplo:

  • Nome do projeto
    • Áreas
      • Produtos
        • Pages (Páginas)
          • _ViewImports
          • Sobre
          • Índice
      • Serviços
        • Pages (Páginas)
          • Gerenciar
            • Sobre
            • Índice

O código a seguir do download do exemplo mostra a geração de links com a área especificada (por exemplo, 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>

Os links gerados com o código anterior são válidos em qualquer lugar no aplicativo.

O download de exemplo inclui uma exibição parcial que contém os links anteriores e os mesmos links sem especificar a área. A exibição parcial é referenciada no arquivo de layout, portanto, todas as páginas no aplicativo exibem os links gerados. Os links gerados sem especificar a área só são válidos quando referenciados de uma página na mesma área.

Quando a área não for especificada, o roteamento dependerá dos valores do ambiente. Os valores de rota atuais da solicitação atual são considerados valores de ambiente para a geração de link. Em muitos casos, para o aplicativo de exemplo, usar os valores de ambiente gera links incorretos. Por exemplo, considere os links gerados a partir do código a seguir:

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

Para o código anterior:

  • O link gerado de <a asp-page="/Manage/About"> só estará correto quando a última solicitação tiver sido para uma página na área Services. Por exemplo, /Services/Manage/, /Services/Manage/Index ou /Services/Manage/About.
  • O link gerado a partir <a asp-page="/About"> só estará correto quando a última solicitação tiver sido para uma página na área /Home.
  • O código vem do download de exemplo.

Importar o namespace e os Auxiliares de marca com o arquivo _ViewImports

Um arquivo _ViewImports.cshtml pode ser adicionado a cada pasta Páginas da área para importar o namespace e os Auxiliares de Marcação para cada Página Razor na pasta.

Considere a área Serviços do código de exemplo, que não contém um arquivo _ViewImports.cshtml. A marcação a seguir mostra a Página /Services/Manage/AboutRazor:

@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>

Na marcação anterior:

  • O nome de domínio totalmente qualificado deve ser usado para especificar o modelo (@model RPareas.Areas.Services.Pages.Manage.AboutModel).
  • Os Auxiliares de Marcação são habilitados por @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers

No download de exemplo, a área Produtos contém o seguinte arquivo _ViewImports.cshtml:

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

A marcação a seguir mostra a Página /Products/AboutRazor:

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

<h2>Products/About</h2>

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

No arquivo anterior, o namespace e a diretiva @addTagHelper são importados para o arquivo por meio do arquivo Areas/Products/Pages/_ViewImports.cshtml.

Para saber mais, confira Gerenciar o escopo do Auxiliar de Marcação e Importar diretivas compartilhadas.

Layout compartilhado para Áreas de Páginas Razor

Para compartilhar um layout comum para o aplicativo inteiro, mova o _ViewStart.cshtml para a pasta raiz do aplicativo.

Publicando áreas

Todos os arquivos *.cshtml e os arquivos do diretório wwwroot são publicados em uma saída quando <Project Sdk="Microsoft.NET.Sdk.Web"> são incluídos no arquivo *.csproj.