Arquivos estáticos no ASP.NET Core

Note

Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão do .NET 10 deste artigo.

Warning

Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, consulte a Política de Suporte do .NET e do .NET Core. Para a versão atual, consulte a versão do .NET 10 deste artigo.

Arquivos estáticos, também chamados de ativos estáticos, são arquivos em um aplicativo ASP.NET Core que não são gerados dinamicamente. Em vez disso, o aplicativo os atende diretamente aos clientes sob solicitação. Exemplos de arquivos estáticos incluem arquivos HTML, CSS, imagem e JavaScript.

Para obter Blazor diretrizes de arquivos estáticos, que adiciona ou substitui as diretrizes neste artigo, consulte Arquivos estáticos do ASP.NET Core Blazor.

Para habilitar o tratamento de arquivos estáticos no ASP.NET Core, chame MapStaticAssets.

Por padrão, armazene arquivos estáticos no diretório raiz da Web do projeto. O diretório padrão é {CONTENT ROOT}/wwwroot, em que o {CONTENT ROOT} espaço reservado é a raiz de conteúdo do aplicativo. Somente os arquivos na wwwroot pasta são endereçáveis, portanto, você não precisa se preocupar com o restante do código.

Somente arquivos com extensões de arquivo específicas mapeadas para tipos de mídia com suporte são tratados como ativos da Web estáticos.

Os ativos estáticos da Web são descobertos em tempo de compilação e otimizados usando a impressão digital baseada em conteúdo para evitar a reutilização de arquivos antigos. Os ativos também são compactados para reduzir o tempo de entrega de ativos.

Em tempo de execução, os ativos estáticos da Web descobertos são expostos como pontos de extremidade com cabeçalhos HTTP aplicados, como cabeçalhos de cache e cabeçalhos de tipo de conteúdo. Um ativo é servido uma vez até que o arquivo seja alterado ou o navegador limpe seu cache. Os cabeçalhos ETag, Last-Modified e Content-Type estão definidos. O navegador é impedido de usar ativos obsoletos depois que um aplicativo é atualizado.

A entrega de ativos estáticos baseia-se no roteamento de ponto de extremidade, portanto, ele funciona com outros recursos com reconhecimento de ponto de extremidade, como autorização. Ele foi projetado para funcionar com todas as estruturas de interface do usuário, incluindo Blazor, Razor Pages e MVC.

O Mapa de Ativos Estáticos oferece os seguintes benefícios:

  • Compactação no tempo de compilação para todos os recursos no aplicativo, incluindo JavaScript (JS) e folhas de estilo, mas excluindo recursos de imagem e fonte que já estão compactados. A compactação Gzip (Content-Encoding: gz) é usada durante o desenvolvimento. A compressão Gzip e Brotli (Content-Encoding: br) é usada durante a publicação.
  • Impressão Digital para todos os ativos em tempo de compilação com uma cadeia de caracteres codificada em Base64do hash SHA-256 do conteúdo de cada arquivo. Isso impede a reutilização de uma versão antiga de um arquivo, mesmo que o arquivo antigo seja armazenado em cache. Os ativos com impressão digital são armazenados em cache usando a immutable diretiva, o que faz com que o navegador nunca mais solicite o ativo até que ele seja alterado. Para navegadores que não dão suporte à immutable diretiva, uma max-age diretiva é adicionada.
    • Mesmo que um ativo não seja fingerprintado, o conteúdo baseado em ETags é gerado para cada ativo estático usando o hash de impressão digital do arquivo como valor ETag. Isso garante que o navegador baixe apenas um arquivo se o conteúdo for alterado (ou se o arquivo estiver sendo baixado pela primeira vez).
    • Internamente, a estrutura mapeia ativos físicos para suas impressões digitais, o que permite ao aplicativo:
      • Encontre ativos gerados automaticamente, como CSS com escopo de componente Razor para o recurso de isolamento de CSS do Blazor e ativos JS descritos por mapas de importação JS.
      • Gere tags de link no conteúdo <head> da página para pré-carregar recursos.

O Mapa de Ativos Estáticos não fornece recursos para minificação ou outras transformações de arquivo. A minificação geralmente é feita com código personalizado ou ferramentas de terceiros.

Note

MapStaticAssets não serve documentos padrão sozinho. Para fornecer documentos padrão, chame UseDefaultFiles seguido por UseStaticFiles. Para obter mais informações, consulte a seção Documentos padrão do Serve .

Para habilitar o tratamento de arquivos estáticos no ASP.NET Core, chame UseStaticFiles.

Por padrão, armazene arquivos estáticos no diretório raiz da Web do projeto. O diretório padrão é {CONTENT ROOT}/wwwroot, em que o {CONTENT ROOT} espaço reservado é a raiz de conteúdo do aplicativo. Somente os arquivos na wwwroot pasta são endereçáveis, portanto, você não precisa se preocupar com o restante do código.

Em tempo de execução, os recursos web estáticos são retornados pelo middleware de arquivos estáticos quando solicitados com modificação de recursos e cabeçalhos de tipo de conteúdo aplicados. Os cabeçalhos ETag, Last-Modified e Content-Type estão definidos.

O middleware de arquivos estáticos habilita o fornecimento de arquivos estáticos e é usado por um aplicativo quando UseStaticFiles é chamado no pipeline de processamento de solicitações do aplicativo. Os arquivos são servidos do caminho especificado em IWebHostEnvironment.WebRootPath ou WebRootFileProvider, que usa como padrão a pasta raiz da Web, normalmente wwwroot.

Você também pode servir ativos da Web estáticos de projetos e pacotes referenciados.

Alterar o diretório raiz da Web

Para alterar o diretório raiz da web, use o método UseWebRoot. Para obter mais informações, consulte Visão geral dos conceitos básicos do ASP.NET Core.

Evite publicar arquivos em wwwroot usando o item <Content> de projeto no arquivo de projeto. O exemplo a seguir impede publicar conteúdo em wwwroot/local e em seus subdiretórios:

<ItemGroup>
  <Content Update="wwwroot\local\**\*.*" CopyToPublishDirectory="Never" />
</ItemGroup>

O método CreateBuilder define a raiz do conteúdo como o diretório atual:

var builder = WebApplication.CreateBuilder(args);

O método CreateDefaultBuilder define a raiz do conteúdo como o diretório atual:

Host.CreateDefaultBuilder(args)

No pipeline de processamento de solicitações, após a chamada para UseHttpsRedirection, chame MapStaticAssets para habilitar o fornecimento de arquivos estáticos da raiz web do aplicativo:

app.MapStaticAssets();

No pipeline de processamento de solicitações, após a chamada para UseHttpsRedirection, chame UseStaticFiles para habilitar o fornecimento de arquivos estáticos da raiz web do aplicativo:

app.UseStaticFiles();

Os arquivos estáticos são acessíveis por meio de um caminho relativo à raiz Web.

Para acessar uma imagem em wwwroot/images/favicon.png:

  • Formato de URL: https://{HOST}/images/{FILE NAME}
    • O marcador {HOST} é o host.
    • O {FILE NAME} placeholder é o nome do arquivo.
  • Exemplos
    • URL absoluta: https://localhost:5001/images/favicon.png
    • URL relativa à raiz: images/favicon.png

Em um Blazor aplicativo, images/favicon.png carrega a imagem do ícone (favicon.png) da pasta wwwroot/images do aplicativo.

<link rel="icon" type="image/png" href="images/favicon.png" />

Em Páginas do Razor e aplicativos MVC, o caractere til ~ aponta para a raiz web. No exemplo a seguir, ~/images/favicon.png carrega a imagem do ícone (favicon.png) da pasta do wwwroot/images aplicativo:

<link rel="icon" type="image/png" href="~/images/favicon.png" />

Interromper o pipeline do middleware

Para evitar a execução de todo o pipeline do middleware após a correspondência de um recurso estático, que é o comportamento de UseStaticFiles, chame ShortCircuit em MapStaticAssets. A chamada ShortCircuit executa imediatamente o endpoint e retorna a resposta, impedindo que outros middlewares sejam executados para solicitações de recursos estáticos.

app.MapStaticAssets().ShortCircuit();

Controlar o cache de arquivos estáticos durante o desenvolvimento

Ao executar no ambiente Development, por exemplo, durante o teste de desenvolvimento com Recarregamento a Quente do Visual Studio, a estrutura substitui os cabeçalhos de cache para impedir que os navegadores armazenem arquivos estáticos em cache. Esse comportamento ajuda a garantir que a versão mais recente dos arquivos seja usada quando os arquivos forem alterados, evitando problemas com conteúdo obsoleto. Em produção, a estrutura define os cabeçalhos de cache corretos, para que os navegadores possam armazenar em cache ativos estáticos conforme o esperado.

Para desabilitar esse comportamento, defina EnableStaticAssetsDevelopmentCachingtrue no Development arquivo de configuração do aplicativo do ambiente (appsettings.Development.json).

Arquivos estáticos em ambientes não-Development

Ao executar um aplicativo localmente, o Development ambiente é o único ambiente que habilita ativos Web estáticos. Para habilitar arquivos estáticos para ambientes diferentes de Development durante o desenvolvimento e teste locais (por exemplo, no ambiente Staging), execute UseStaticWebAssets no WebApplicationBuilder.

Warning

Chame UseStaticWebAssets para o ambiente exato para evitar a ativação do recurso em produção, pois ele serve arquivos de locais separados no disco diferentes do projeto. Nesta seção, o exemplo verifica o ambiente Staging com IsStaging.

if (builder.Environment.IsStaging())
{
    builder.WebHost.UseStaticWebAssets();
}

Servir arquivos fora do diretório raiz da Web por meio de IWebHostEnvironment.WebRootPath

Quando você define IWebHostEnvironment.WebRootPath como uma pasta diferente wwwroot, o aplicativo exibe os seguintes comportamentos padrão:

  • No ambiente Development, os recursos estáticos são servidos de wwwroot se recursos com o mesmo nome estiverem em wwwroot e em uma pasta diferente atribuída a WebRootPath.
  • Em qualquer ambiente que não seja Development, ativos estáticos duplicados são servidos a partir da pasta WebRootPath.

Considere um aplicativo Web criado com base no modelo da Web vazio:

  • Contendo um arquivo Index.html em wwwroot e wwwroot-custom.
  • O Program arquivo é atualizado para definir WebRootPath = "wwwroot-custom".
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    WebRootPath = "wwwroot-custom"
});

Por padrão, para solicitações:/

  • No ambiente Development, wwwroot/Index.html é retornado.
  • Em qualquer ambiente diferente de Development, wwwroot-custom/Index.html é retornado.

Para garantir que os ativos de wwwroot-custom sejam sempre retornados, use uma das seguintes abordagens:

  • Excluir ativos nomeados duplicados em wwwroot.

  • Defina ASPNETCORE_ENVIRONMENT em Properties/launchSettings.json para qualquer valor diferente de Development.

  • Desative os ativos da Web estáticos definindo <StaticWebAssetsEnabled> como false no arquivo de projeto do aplicativo. AVISO: Desabilitar ativos da Web estáticos desabilita Razor bibliotecas de classes.

  • Adicione o seguinte XML ao arquivo de projeto:

    <ItemGroup>
      <Content Remove="wwwroot\**" />
    </ItemGroup>
    

O código a seguir atualiza WebRootPath para um valor não relacionado ao Desenvolvimento (Staging), assegurando que o conteúdo duplicado seja obtido do wwwroot-custom em vez de wwwroot.

var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
    Args = args,
    EnvironmentName = Environments.Staging,
    WebRootPath = "wwwroot-custom"
});

Middleware de arquivos estáticos

O middleware de arquivos estáticos permite o fornecimento de arquivos estáticos em cenários específicos de arquivos estáticos, geralmente em adição às convenções de roteamento de pontos de extremidade de Mapeamento de Recursos Estáticos (MapStaticAssets).

O middleware de arquivos estáticos é incluído no processamento de requisições quando UseStaticFiles é chamado no pipeline de processamento de requisições do aplicativo, normalmente após a adição das convenções de ponto de extremidade de Mapear Ativos Estáticos (MapStaticAssets).

As convenções de endpoint do Map Static Assets são usadas em aplicativos direcionados ao .NET 9 ou posterior. O middleware de arquivo estático deve ser usado em aplicativos destinados a versões de .NET antes do .NET 9.

O middleware de arquivos estáticos serve arquivos estáticos, mas não oferece o mesmo nível de otimização que as convenções de ponto de extremidade de Mapear Ativos Estáticos. Os recursos de compressão em tempo de compilação e de identificação de arquivos das convenções de ponto de extremidade de Mapear Ativos Estáticos não estão disponíveis quando se utiliza apenas o middleware de arquivos estáticos.

As convenções de ponto de extremidade são otimizadas para servir ativos que o aplicativo conhece em tempo de execução. Se o aplicativo servir arquivos de outros locais, como disco ou recursos incorporados, use o middleware de arquivos estáticos.

Os seguintes recursos abordados neste artigo são compatíveis com o middleware de arquivos estáticos, mas não com as convenções do ponto de extremidade Map Static Assets:

Servir arquivos fora do diretório raiz da Web por meio de UseStaticFiles

Considere a seguinte hierarquia de diretório com arquivos estáticos que residem fora da raiz da Web do aplicativo em uma pasta chamada ExtraStaticFiles:

  • wwwroot
    • css
    • images
    • js
  • ExtraStaticFiles
    • images
      • red-rose.jpg

Uma requisição pode acessar red-rose.jpg configurando uma nova instância de middleware de arquivos estáticos:

Namespaces para a API a seguir:

using Microsoft.Extensions.FileProviders;

No pipeline de processamento de requisições, após a chamada existente para MapStaticAssets (.NET 9 ou posterior) ou UseStaticFiles (.NET 8 ou anterior):

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "ExtraStaticFiles")),
    RequestPath = "/static-files"
});

No código anterior, a hierarquia de ExtraStaticFiles diretório é exposta publicamente por meio do static-files segmento de URL. Uma solicitação para https://{HOST}/StaticFiles/images/red-rose.jpg, onde o espaço reservado {HOST} é o host, serve o arquivo red-rose.jpg.

As seguintes referências de marcação ExtraStaticFiles/images/red-rose.jpg:

<img src="static-files/images/red-rose.jpg" alt="A red rose" />

Para o exemplo anterior, a notação til-barra é compatível com Páginas do Razor e exibições MVC (src="~/StaticFiles/images/red-rose.jpg"), não com Razor componentes em Blazor aplicativos.

Fornecer arquivos de vários locais

As orientações nesta seção se aplicam a aplicativos Pages e MVC. Para obter diretrizes que se aplicam aos Blazor Web Apps, consulte Arquivos estáticos do ASP.NET Core Blazor.

Considere a seguinte marcação que exibe um logotipo da empresa:

<img src="~/logo.png" asp-append-version="true" alt="Company logo">

O desenvolvedor pretende usar o Image Tag Helper para acrescentar uma versão e servir o arquivo a partir de um local personalizado, uma pasta chamada ExtraStaticFiles.

O exemplo a seguir chama MapStaticAssets para fornecer arquivos de wwwroot e UseStaticFiles para fornecer arquivos de ExtraStaticFiles:

No pipeline de processamento de requisições, após a chamada existente para MapStaticAssets (.NET 9 ou posterior) ou UseStaticFiles (.NET 8 ou anterior):

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "ExtraStaticFiles"))
});

O exemplo a seguir chama UseStaticFiles duas vezes para atender arquivos de ambos wwwroot e ExtraStaticFiles.

No pipeline de processamento de requisições, após a chamada existente para UseStaticFiles:

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "ExtraStaticFiles"))
});

Usando o código anterior, o ExtraStaticFiles/logo.png arquivo é exibido. No entanto, o Image Tag Helper (AppendVersion) não é aplicado porque este depende de WebRootFileProvider, o qual não foi atualizado para incluir o diretório ExtraStaticFiles.

O código a seguir atualiza o WebRootFileProvider para incluir a pasta ExtraStaticFiles usando um CompositeFileProvider. Isso permite que o Auxiliar de Marca de Imagem aplique uma versão às imagens na ExtraStaticFiles pasta.

Namespace para a seguinte API:

using Microsoft.Extensions.FileProviders;

No pipeline de processamento de requisições, antes da chamada existente para MapStaticAssets (.NET 9 ou posterior) ou UseStaticFiles (.NET 8 ou anterior):

var webRootProvider = new PhysicalFileProvider(builder.Environment.WebRootPath);
var newPathProvider = new PhysicalFileProvider(
    Path.Combine(builder.Environment.ContentRootPath, "ExtraStaticFiles"));

var compositeProvider = new CompositeFileProvider(webRootProvider, newPathProvider);

app.Environment.WebRootFileProvider = compositeProvider;

UseStaticFiles e UseFileServer padrão para o provedor de arquivos apontando para wwwroot. Instâncias adicionais de UseStaticFiles e UseFileServer podem ser fornecidas com outros provedores de arquivos para fornecer arquivos de outros locais. Para obter mais informações, consulte UseStaticFiles ainda necessário com UseFileServer para wwwroot (dotnet/AspNetCore.Docs nº 15578).

Definir cabeçalhos de resposta HTTP

Use StaticFileOptions para definir cabeçalhos de resposta HTTP. Além de configurar o middleware de arquivos estáticos para servir arquivos estáticos, o código a seguir define o cabeçalho Cache-Control para 604.800 segundos (uma semana).

Namespaces para a API a seguir:

using Microsoft.AspNetCore.Http;

No pipeline de processamento de requisições, após a chamada existente para MapStaticAssets (.NET 9 ou posterior) ou UseStaticFiles (.NET 8 ou anterior):

app.UseStaticFiles(new StaticFileOptions
{
    OnPrepareResponse = ctx =>
    {
        ctx.Context.Response.Headers.Append(
            "Cache-Control", "public, max-age=604800");
    }
});

Grande coleção de ativos

Ao lidar com grandes coleções de ativos, que são considerados cerca de 1.000 ou mais ativos, recomendamos usar um empacotador para reduzir o número final de ativos atendidos pelo aplicativo ou combinar MapStaticAssets com UseStaticFiles.

MapStaticAssets carrega antecipadamente os metadados pré-computados capturados durante o processo de build para os recursos, a fim de oferecer suporte à compactação, ao cache e à identificação. Esses recursos vêm ao custo de maior uso de memória pelo aplicativo. Para ativos que são acessados com frequência, geralmente vale os custos. Para ativos que não são acessados com frequência, a compensação pode não valer os custos.

Se você não usar o agrupamento, recomendamos que você combine MapStaticAssets com UseStaticFiles. O exemplo a seguir demonstra a abordagem.

No arquivo de projeto (.csproj), a propriedade MSBuild StaticWebAssetEndpointExclusionPattern é usada para filtrar endpoints do manifesto final para MapStaticAssets. Os arquivos excluídos são servidos por UseStaticFiles e não se beneficiam de compactação, cache e identificação por impressão digital.

Ao definir o valor de StaticWebAssetEndpointExclusionPattern, mantenha $(StaticWebAssetEndpointExclusionPattern) para manter o padrão de exclusão padrão da estrutura. Adicione padrões adicionais em uma lista separada por ponto-e-vírgula.

No exemplo a seguir, o padrão de exclusão adiciona os arquivos estáticos na pasta lib/icons, que representa um lote hipotético de ícones.

<StaticWebAssetEndpointExclusionPattern>
  $(StaticWebAssetEndpointExclusionPattern);lib/icons/**
</StaticWebAssetEndpointExclusionPattern>

Após o processamento do middleware de redirecionamento HTTPS (app.UseHttpsRedirection();) no arquivo Program:

app.UseStaticFiles();

app.UseAuthorization();

app.MapStaticAssets();

Manifesto de ativos estáticos

MapStaticAssets fornece ativos de um manifesto de ativos estáticos, em vez de verificar a raiz da web no tempo de execução. O arquivo de manifesto é gerado durante a compilação e a publicação e registra os ativos web estáticos detectados para o aplicativo, juntamente com metadados, como hashes de conteúdo, cabeçalhos Content-Type, cabeçalhos de cache e as representações comprimidas pré-calculadas (Gzip e Brotli). Em tempo de execução, MapStaticAssets lê o manifesto, registra um endpoint para cada recurso e fornece as respostas otimizadas.

O manifest é gerado no diretório de saída da compilação durante a compilação. Seu nome de arquivo é baseado no nome do assembly do projeto (por exemplo, {ASSEMBLY NAME}.staticwebassets.endpoints.json, em que o marcador {ASSEMBLY NAME} é o valor de AssemblyName do MSBuild do aplicativo). Para fornecer um manifesto de um local diferente, consulte a seção Fornecer um manifesto de arquivos estáticos personalizados .

Como MapStaticAssets só serve ativos listados no manifesto, os arquivos que não fazem parte do manifesto não são atendidos por MapStaticAssets. Os arquivos não fazem parte do manifesto quando são:

  • Localizado fora do diretório raiz web durante a compilação, como arquivos servidos a partir do disco, recursos inseridos ou um WebRootPath personalizado definido no tempo de execução.
  • Excluído do manifesto com a propriedade MSBuild StaticWebAssetEndpointExclusionPattern (consulte a seção Grande coleção de recursos).

Para servir arquivos que não estão no manifesto, chame UseStaticFiles, que serve arquivos diretamente da raiz da Web em tempo de execução. É também por isso que servir documentos padrão com MapStaticAssets requer uma chamada para UseStaticFiles.

Autorização de arquivo estático

Quando um aplicativo adota uma política de autorização de fallback, ele requer autorização para todas as solicitações que não especificam explicitamente uma política de autorização. Esse requisito inclui solicitações de arquivos estáticos depois que o middleware de autorização processa as solicitações. Para permitir o acesso anônimo a arquivos estáticos, aplique AllowAnonymousAttribute ao construtor de pontos de extremidade para arquivos estáticos:

app.MapStaticAssets().Add(endpointBuilder => 
    endpointBuilder.Metadata.Add(new AllowAnonymousAttribute()));

Quando um aplicativo adota uma política de autorização de contingência, a autorização passa a ser exigida para todas as solicitações que não especificam explicitamente uma política de autorização, incluindo solicitações de arquivos estáticos depois que o middleware de autorização processa as solicitações. Os modelos do ASP.NET Core permitem acesso anônimo a arquivos estáticos chamando UseStaticFiles antes de chamar UseAuthorization. A maioria dos aplicativos segue esse padrão. Quando o middleware de arquivo estático é chamado antes do middleware de autorização:

  • Nenhuma verificação de autorização é executada nos arquivos estáticos.
  • Os arquivos estáticos servidos pelo middleware de arquivos estáticos, como os que estão na raiz da Web (normalmente, wwwroot), são acessíveis publicamente.

Para fornecer arquivos estáticos com base na autorização:

Namespaces para a API a seguir:

using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.FileProviders;

Registro de serviço:

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

No pipeline de processamento de solicitação após a chamada para UseAuthorization:

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "SecureStaticFiles")),
    RequestPath = "/static-files"
});

Namespaces para a API a seguir:

using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.FileProviders;

Em Startup.ConfigureServices:

services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

Em Startup.Configure após a chamada para UseAuthorization:

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.ContentRootPath, "SecureStaticFiles")),
    RequestPath = "/static-files"
});

No código anterior, a política de autorização de fallback requer usuários autenticados. Pontos de extremidade, como controladores e Páginas do Razor, que especificam seus próprios requisitos de autorização não usam a política de autorização de fallback. Por exemplo, Páginas do Razor, controladores ou métodos de ação com [AllowAnonymous] ou [Authorize(PolicyName="MyPolicy")] usam o atributo de autorização aplicado em vez da política de autorização de fallback.

RequireAuthenticatedUser adiciona DenyAnonymousAuthorizationRequirement à instância atual, que impõe que o usuário atual seja autenticado.

Os ativos estáticos armazenados na raiz da web do aplicativo são acessíveis publicamente porque o middleware de arquivo estático padrão (UseStaticFiles) é chamado antes de UseAuthorization. Os ativos estáticos na SecureStaticFiles pasta exigem autenticação.

Uma abordagem alternativa para fornecer arquivos com base na autorização é:

  • Armazene os arquivos fora do diretório base e de qualquer diretório acessível ao middleware de arquivos estáticos.
  • Sirva os arquivos por meio de um método de ação ao qual a autorização é aplicada e retorne um FileResult objeto.

De uma Razor página (Pages/BannerImage.cshtml.cs):

public class BannerImageModel : PageModel
{
    private readonly IWebHostEnvironment _env;

    public BannerImageModel(IWebHostEnvironment env) => _env = env;

    public PhysicalFileResult OnGet()
    {
        var filePath = Path.Combine(
            _env.ContentRootPath, "SecureStaticFiles", "images", "red-rose.jpg");

        return PhysicalFile(filePath, "image/jpeg");
    }
}

De um controlador (Controllers/HomeController.cs):

[Authorize]
public IActionResult BannerImage()
{
    var filePath = Path.Combine(
        _env.ContentRootPath, "SecureStaticFiles", "images", "red-rose.jpg");

    return PhysicalFile(filePath, "image/jpeg");
}

A abordagem anterior exige uma página ou um ponto de extremidade por arquivo.

O exemplo de endpoint de rota a seguir retorna arquivos para usuários autenticados.

No arquivo Program:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AuthenticatedUsers", b => b.RequireAuthenticatedUser());
});

...

app.MapGet("/files/{fileName}", IResult (string fileName) => 
{
    var filePath = GetOrCreateFilePath(fileName);

    if (File.Exists(filePath))
    {
        return TypedResults.PhysicalFile(filePath, fileName);
    }

    return TypedResults.NotFound("No file found with the supplied file name");
})
.WithName("GetFileByName")
.RequireAuthorization("AuthenticatedUsers");

O exemplo de ponto de extremidade de rota a seguir carrega arquivos para usuários autenticados na função de administrador (admin).

No arquivo Program:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("AdminsOnly", b => b.RequireRole("admin"));
});

...

// IFormFile uses memory buffer for uploading. For handling large 
// files, use streaming instead. See the *File uploads* article
// in the ASP.NET Core documentation:
// https://learn.microsoft.com/aspnet/core/mvc/models/file-uploads
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, 
    HttpContext context) =>
{
    // Don't rely on the value in 'file.FileName', as it's only metadata that can 
    // be manipulated by the end-user. Consider the 'Utilities.IsFileValid' method 
    // that takes an 'IFormFile' and validates its signature within the 
    // 'AllowedFileSignatures'.

    var fileSaveName = Guid.NewGuid().ToString("N") + 
        Path.GetExtension(file.FileName);
    await SaveFileWithCustomFileName(file, fileSaveName);

    context.Response.Headers.Append("Location", linker.GetPathByName(context, 
        "GetFileByName", new { fileName = fileSaveName}));

    return TypedResults.Ok("File Uploaded Successfully!");
})
.RequireAuthorization("AdminsOnly");

Em Startup.ConfigureServices:

services.AddAuthorization(options =>
{
    options.AddPolicy("AuthenticatedUsers", b => b.RequireAuthenticatedUser());
});

Em Startup.Configure:

app.MapGet("/files/{fileName}", IResult (string fileName) => 
{
    var filePath = GetOrCreateFilePath(fileName);

    if (File.Exists(filePath))
    {
        return TypedResults.PhysicalFile(filePath, fileName);
    }

    return TypedResults.NotFound("No file found with the supplied file name");
})
.WithName("GetFileByName")
.RequireAuthorization("AuthenticatedUsers");

O código a seguir carrega arquivos para usuários autenticados na função de administrador (admin).

Em Startup.ConfigureServices:

services.AddAuthorization(options =>
{
    options.AddPolicy("AdminsOnly", b => b.RequireRole("admin"));
});

Em Startup.Configure:

// IFormFile uses memory buffer for uploading. For handling large 
// files, use streaming instead. See the *File uploads* article
// in the ASP.NET Core documentation:
// https://learn.microsoft.com/aspnet/core/mvc/models/file-uploads
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, 
    HttpContext context) =>
{
    // Don't rely on the value in 'file.FileName', as it's only metadata that can 
    // be manipulated by the end-user. Consider the 'Utilities.IsFileValid' method 
    // that takes an 'IFormFile' and validates its signature within the 
    // 'AllowedFileSignatures'.

    var fileSaveName = Guid.NewGuid().ToString("N") + 
        Path.GetExtension(file.FileName);
    await SaveFileWithCustomFileName(file, fileSaveName);

    context.Response.Headers.Append("Location", linker.GetPathByName(context, 
        "GetFileByName", new { fileName = fileSaveName}));

    return TypedResults.Ok("File Uploaded Successfully!");
})
.RequireAuthorization("AdminsOnly");

Navegação de diretório

A navegação no diretório permite a listagem de diretórios nos diretórios especificados.

Por motivos de segurança, a navegação de diretório está desabilitada por padrão. Para obter mais informações, consulte Considerações sobre segurança relacionadas a arquivos estáticos.

Habilite a navegação de diretório usando as seguintes APIs:

No exemplo a seguir:

  • Uma images pasta na raiz do aplicativo contém imagens para navegação de diretório.
  • O caminho da solicitação para procurar as imagens é /DirectoryImages.
  • Chamar UseStaticFiles e definir o FileProvider de StaticFileOptions permite exibir links do navegador para os arquivos individuais.

Namespaces para a API a seguir:

using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;

Registro de serviço:

builder.Services.AddDirectoryBrowser();

No pipeline de processamento de requisições, após a chamada existente para MapStaticAssets (.NET 9 ou posterior) ou UseStaticFiles (.NET 8 ou anterior):

var fileProvider = new PhysicalFileProvider(
    Path.Combine(builder.Environment.WebRootPath, "images"));
var requestPath = "/DirectoryImages";

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = fileProvider,
    RequestPath = requestPath
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
    FileProvider = fileProvider,
    RequestPath = requestPath
});

Namespaces para a API a seguir:

using Microsoft.Extensions.FileProviders;
using System.IO;

Em Startup.ConfigureServices:

services.AddDirectoryBrowser();

Em Startup.Configure após a chamada existente para UseStaticFiles:

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.WebRootPath, "images")),
    RequestPath = "/DirectoryImages"
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.WebRootPath, "images")),
    RequestPath = "/DirectoryImages"
});

O código anterior permite a navegação de diretórios da pasta wwwroot/images usando a URL https://{HOST}/DirectoryImages com links para cada arquivo e pasta, onde o marcador {HOST} é o host.

AddDirectoryBrowser adiciona serviços exigidos pelo middleware de navegação de diretório, incluindo HtmlEncoder. Esses serviços podem ser adicionados por outras chamadas, como AddRazorPages, mas recomendamos chamar AddDirectoryBrowser para garantir que os serviços sejam adicionados.

Fornecer documentos padrão

Definir uma página padrão fornece aos visitantes um ponto de partida em um site. Para servir um arquivo padrão a partir de wwwroot sem exigir que a URL de solicitação inclua o nome do arquivo, chame o método UseDefaultFiles.

UseDefaultFiles é um reescritor de URL que não serve o arquivo. Ele reescreve a URL da solicitação para o documento padrão (por exemplo, / para /index.html) e outro componente serve o arquivo.

Como MapStaticAssets fornece ativos descobertos durante a compilação por meio do roteamento de pontos de extremidade, ele não fornece documentos padrão por conta própria. Chame UseDefaultFiles para reescrever a solicitação, seguido de UseStaticFiles para processar a solicitação reescrita para o documento padrão:

app.UseDefaultFiles();
app.UseStaticFiles();
app.MapStaticAssets();

Importante

Configurar somente UseDefaultFiles e MapStaticAssets (sem UseStaticFiles) retorna uma resposta 404 – Não encontrada para uma solicitação para /. Isso ocorre porque a hospedagem mínima adiciona o middleware de roteamento no início do pipeline de processamento da solicitação, de modo que o roteamento de ponto de extremidade corresponda à solicitação antes que UseDefaultFiles a reescreva para o documento padrão. O problema é especialmente evidente quando a raiz web é alterada para um caminho personalizado com WebRootPath, porque os arquivos em uma raiz web personalizada não fazem parte do manifesto de ativos estáticos gerado em tempo de compilação que MapStaticAssets fornece. Adicione uma chamada a UseStaticFiles depois de UseDefaultFiles, conforme mostrado no exemplo anterior, para servir documentos padrão.

No pipeline de processamento de solicitação antes da chamada existente para UseStaticFiles:

app.UseDefaultFiles();

Com UseDefaultFiles, as solicitações para uma pasta em wwwroot visam procurar:

  • default.htm
  • default.html
  • index.htm
  • index.html

O primeiro arquivo encontrado na lista é fornecido como se a solicitação fosse incluída no nome do arquivo. A URL do navegador continua refletindo o URI solicitado.

O seguinte código altera o nome do arquivo padrão para default-document.html:

var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("default-document.html");
app.UseDefaultFiles(options);

Combinar arquivos estáticos, documentos padrão e navegação de diretório

UseFileServer combina a funcionalidade de UseStaticFiles, UseDefaultFiles e opcionalmente UseDirectoryBrowser.

No pipeline de processamento de solicitações, após a chamada existente para MapStaticAssets (.NET 9 ou posterior) ou UseStaticFiles (.NET 8 ou anterior), chame UseFileServer para permitir a disponibilização de arquivos estáticos e do arquivo padrão.

app.UseFileServer();

A navegação de diretório não está habilitada para o exemplo anterior.

O código a seguir habilita o fornecimento de arquivos estáticos, o arquivo padrão e a navegação de diretório.

Registro de serviço:

builder.Services.AddDirectoryBrowser();

No pipeline de processamento de requisições, após a chamada existente para UseStaticFiles:

app.UseFileServer(enableDirectoryBrowsing: true);

Em Startup.ConfigureServices:

services.AddDirectoryBrowser();

Em Startup.Configure após a chamada existente para UseStaticFiles:

app.UseFileServer(enableDirectoryBrowsing: true);

Para o endereço do host (/), UseFileServer retorna o documento HTML padrão antes da página padrão Razor (Pages/Index.cshtml) ou do modo de exibição MVC padrão (Home/Index.cshtml).

Considere a seguinte hierarquia de diretórios:

  • wwwroot
    • css
    • images
    • js
  • ExtraStaticFiles
    • images
      • logo.png
    • default.html

O código a seguir habilita o fornecimento de arquivos estáticos, o arquivo padrão e a navegação de diretório de ExtraStaticFiles.

Namespaces para a API a seguir:

using Microsoft.Extensions.FileProviders;

Registro de serviço:

builder.Services.AddDirectoryBrowser();

No pipeline de processamento de requisições, após a chamada existente para UseStaticFiles:

app.UseFileServer(new FileServerOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(builder.Environment.ContentRootPath, "ExtraStaticFiles")),
    RequestPath = "/static-files",
    EnableDirectoryBrowsing = true
});

Namespaces para a API a seguir:

using Microsoft.Extensions.FileProviders;
using System.IO;

Em Startup.ConfigureServices:

services.AddDirectoryBrowser();

Em Startup.Configure após a chamada existente para UseStaticFiles:

app.UseFileServer(new FileServerOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.ContentRootPath, "ExtraStaticFiles")),
    RequestPath = "/static-files",
    EnableDirectoryBrowsing = true
});

AddDirectoryBrowser precisa ser chamado quando o valor da propriedade EnableDirectoryBrowsing é true.

Usando a hierarquia de arquivos e o código anteriores, os URLs são resolvidos conforme mostrado na tabela a seguir (o marcador {HOST} representa o host).

URI Arquivo de resposta
https://{HOST}/static-files/images/logo.png ExtraStaticFiles/images/logo.png
https://{HOST}/static-files ExtraStaticFiles/default.html

Se nenhum arquivo com o nome padrão existir no diretório ExtraStaticFiles, https://{HOST}/static-files retornará a listagem do diretório com links clicáveis, em que o marcador {HOST} é o host.

UseDefaultFiles e UseDirectoryBrowser executam um redirecionamento do lado do cliente do URI de destino sem um / à direita para o URI de destino com um / à direita. Por exemplo, de https://{HOST}/static-files (sem sequência final /) para https://{HOST}/static-files/ (inclui uma sequência final /). As URLs relativas no diretório ExtraStaticFiles são inválidas sem uma barra final (/), a menos que a opção RedirectToAppendTrailingSlash de DefaultFilesOptions seja usada.

Mapear extensões de arquivo para tipos MIME

Note

Para obter diretrizes que se aplicam a Blazor aplicativos, consulte ASP.NET Arquivos estáticos principaisBlazor.

Use FileExtensionContentTypeProvider.Mappings para adicionar ou modificar a extensão de arquivo para mapeamentos de tipo de conteúdo MIME.

Note

FileExtensionContentTypeProvider não é thread-safe para gravações simultâneas. Seu dicionário de mapeamentos internos é um padrão Dictionary<string, string> sem sincronização. Os mapeamentos do provedor devem ser configurados uma vez na inicialização. Se apenas operações de leitura (consultas) forem realizadas posteriormente, o provedor pode ser registrado com segurança como um singleton. Não adicione, remova ou modifique mapeamentos depois que o provedor estiver em uso por solicitações simultâneas.

No exemplo a seguir, várias extensões de arquivo são mapeadas para tipos MIME conhecidos. A .rtf extensão é substituída e .mp4 removida:

using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;

...

// Set up custom content types - associating file extension to MIME type
var provider = new FileExtensionContentTypeProvider();
// Add new mappings
provider.Mappings[".myapp"] = "application/x-msdownload";
provider.Mappings[".htm3"] = "text/html";
provider.Mappings[".image"] = "image/png";
// Replace an existing mapping
provider.Mappings[".rtf"] = "application/x-msdownload";
// Remove MP4 videos
provider.Mappings.Remove(".mp4");

app.UseStaticFiles(new StaticFileOptions
{
    ContentTypeProvider = provider
});

Quando você tiver várias opções de arquivo estático para configurar, você poderá, como alternativa, definir o provedor usando StaticFileOptions:

var provider = new FileExtensionContentTypeProvider();

...

builder.Services.Configure<StaticFileOptions>(options =>
{
    options.ContentTypeProvider = provider;
});

app.UseStaticFiles();

Em Startup.Configure:

using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
using System.IO;

...

// Set up custom content types - associating file extension to MIME type
var provider = new FileExtensionContentTypeProvider();
// Add new mappings
provider.Mappings[".myapp"] = "application/x-msdownload";
provider.Mappings[".htm3"] = "text/html";
provider.Mappings[".image"] = "image/png";
// Replace an existing mapping
provider.Mappings[".rtf"] = "application/x-msdownload";
// Remove MP4 videos
provider.Mappings.Remove(".mp4");

app.UseStaticFiles(new StaticFileOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.WebRootPath, "images")),
    RequestPath = "/images",
    ContentTypeProvider = provider
});

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
    FileProvider = new PhysicalFileProvider(
        Path.Combine(env.WebRootPath, "images")),
    RequestPath = "/images"
});

Para obter mais informações, consulte tipos de conteúdo MIME.

Tipos de conteúdo não padrão

O middleware de arquivo estático entende quase 400 tipos de conteúdo de arquivo conhecidos. Se o usuário solicitar um arquivo com um tipo de arquivo desconhecido, o middleware de arquivo estático passará a solicitação para o próximo middleware no pipeline. Se nenhum middleware manipular a solicitação, uma resposta 404 Não Encontrado será retornada. Se a navegação no diretório estiver habilitada, um link para o arquivo será exibido na lista do diretório.

O código a seguir permite servir tipos de conteúdo desconhecidos e renderiza o arquivo desconhecido como uma imagem:

app.UseStaticFiles(new StaticFileOptions
{
    ServeUnknownFileTypes = true,
    DefaultContentType = "image/png"
});

Com o código anterior, uma solicitação para um arquivo com um tipo de conteúdo desconhecido é retornada como uma imagem.

Warning

Habilitar ServeUnknownFileTypes é um risco à segurança. Ela está desabilitada por padrão, e seu uso não é recomendado. As extensões de arquivo de mapa para tipos MIME fornecem uma alternativa mais segura para atender arquivos com extensões não padrão.

Fornecer um manifesto de arquivos estáticos personalizados

Se staticAssetsManifestPath for null, o IHostEnvironment.ApplicationName é usado para localizar o manifesto. Como alternativa, especifique um caminho completo para o arquivo de manifesto. Se um caminho relativo for usado, a estrutura procurará o arquivo no AppContext.BaseDirectory.

Considerações de segurança para arquivos estáticos

Warning

UseDirectoryBrowser e UseStaticFiles podem vazar segredos. A desabilitação da navegação no diretório em produção é altamente recomendada. Examine com atenção os diretórios que são habilitados por meio de UseStaticFiles ou UseDirectoryBrowser. Todo o diretório e seus subdiretórios se tornam publicamente acessíveis. Armazene arquivos adequados para fornecimento ao público em um diretório dedicado, como <content_root>/wwwroot. Separe esses arquivos das exibições MVC, Razor Páginas, arquivos de configuração, etc.

  • As URLs para o conteúdo exposto com UseDirectoryBrowser e UseStaticFiles estão sujeitas à diferenciação de maiúsculas e minúsculas e a restrições de caracteres do sistema de arquivos subjacente. Por exemplo, o Windows diferencia maiúsculas de minúsculas, mas o macOS e o Linux não.

  • Os aplicativos ASP.NET Core hospedados no IIS usam o Módulo do ASP.NET Core para encaminhar todas as solicitações ao aplicativo, inclusive as solicitações de arquivo estático. O manipulador de arquivo estático de IIS não é usado e não tem nenhuma chance de lidar com solicitações.

  • Conclua as etapas seguinte no Gerenciador do IIS para remover o manipulador de arquivos estáticos no IIS no nível do servidor ou do site:

    1. Navegue para o recurso Módulos.
    2. Selecione StaticFileModule na lista.
    3. Clique em Remover na barra lateral Ações.

Warning

Se o manipulador de arquivo estático do IIS estiver habilitado e o Módulo do ASP.NET Core não estiver configurado corretamente, os arquivos estáticos serão atendidos. Isso acontece, por exemplo, se o web.config arquivo não for implantado.

  • Coloque arquivos de código, incluindo .cs e .cshtml, fora da raiz Web do projeto de aplicativo. Portanto, uma separação lógica é criada entre o conteúdo do lado do cliente do aplicativo e o código baseado em servidor. Isso impede a perda de código do lado do servidor.

Propriedades do MSBuild

As tabelas a seguir mostram as propriedades e descrições de metadados do MSBuild dos arquivos estáticos.

Propriedade Description
EnableDefaultCompressedItems Habilita padrões padrão de inclusão/exclusão de compactação.
CompressionIncludePatterns Lista separada por ponto-e-vírgula de padrões de arquivo a serem incluídos para compactação.
CompressionExcludePatterns Lista separada por ponto-e-vírgula de padrões de arquivo a serem excluídos da compactação.
EnableDefaultCompressionFormats Habilita formatos de compactação padrão (Gzip e Brotli).
BuildCompressionFormats Formatos de compactação a serem usados durante o build.
PublishCompressionFormats Formatos de compactação a serem usados durante a publicação.
DisableBuildCompression Desabilita a compactação durante a compilação.
CompressDiscoveredAssetsDuringBuild Compacta ativos descobertos durante a compilação.
BrotliCompressionLevel Nível de compactação para o algoritmo Brotli.
StaticWebAssetBuildCompressAllAssets Compacta todos os ativos durante o build, não apenas ativos descobertos ou computados durante um build.
StaticWebAssetPublishCompressAllAssets Compacta todos os ativos durante a publicação, não apenas ativos descobertos ou computados durante um build.
Propriedade Description
StaticWebAssetBasePath Caminho de URL base para todos os recursos em uma biblioteca.
StaticWebAssetsFingerprintContent Habilita a identificação de conteúdo para invalidação de cache.
StaticWebAssetFingerprintingEnabled Habilita o recurso de impressão digital para ativos da Web estáticos.
StaticWebAssetsCacheDefineStaticWebAssetsEnabled Habilita o cache para configurações de recursos da web estáticos.
StaticWebAssetEndpointExclusionPattern Padrão para excluir pontos de extremidade.
Grupo de itens Description Metadados
StaticWebAssetContentTypeMapping Mapeia padrões de arquivo para tipos de conteúdo e cabeçalhos de cache para pontos de extremidade. Pattern Cache Priority
StaticWebAssetFingerprintPattern Define padrões para aplicar impressões digitais a ativos da Web estáticos para a quebra de cache. Pattern, Expression

Descrições de metadados:

  • Pattern: um padrão glob usado para corresponder a arquivos. Para StaticWebAssetContentTypeMapping, ele corresponde a arquivos para determinar seu tipo de conteúdo (por exemplo, *.js para arquivos JavaScript). Para StaticWebAssetFingerprintPattern, ele identifica arquivos de várias extensões que exigem tratamento especial de impressão digital (por exemplo, *.lib.module.js).

  • Cache: especifica o valor do Cache-Control cabeçalho para o tipo de conteúdo correspondente. Isso controla o comportamento de cache do navegador (por exemplo, max-age=3600, must-revalidate para arquivos de mídia).

  • Priority: controla a precedência quando vários StaticWebAssetContentTypeMapping itens correspondem ao mesmo arquivo. Valores numéricos mais altos têm precedência sobre os mais baixos. Priority é obrigatório.

  • Expression: define como a impressão digital é inserida no nome do arquivo. O padrão é #[.{FINGERPRINT}], que insere a impressão digital (espaço reservado {FINGERPRINT}) antes da extensão.

O exemplo a seguir mapeia o padrão de arquivo bitmap (.bmp) para o tipo de conteúdo image/bmp com o espaço reservado {CACHE HEADER} representando o cabeçalho Cache-Control a ser usado em endpoints sem identificação digital:

<ItemGroup>
  <StaticWebAssetContentTypeMapping Include="image/bmp" Cache="{CACHE HEADER}"
    Pattern="*.bmp" Priority="1" />
</ItemGroup>

Opções de configuração de runtime

A tabela a seguir descreve as opções de configuração de runtime.

Chave de configuração Description
ReloadStaticAssetsAtRuntime Habilita o recarregamento dinâmico de recursos estáticos em tempo de desenvolvimento: serve arquivos modificados da raiz da web (wwwroot) (recalcula ETag, recompila se necessário) em vez das versões do manifesto de tempo de compilação. Por padrão, é habilitado somente ao servir um manifesto de compilação, a menos que seja definido explicitamente.
DisableStaticAssetNotFoundRuntimeFallback Quando true, suprime o ponto de extremidade de fallback que serve arquivos recém-adicionados que não estão presentes no manifesto de compilação. Quando false está ausente, um fallback de verificação de existência do arquivo {**path} (GET/HEAD) registra um aviso e serve o arquivo com um valor computado ETag.
EnableStaticAssetsDevelopmentCaching Quando true, preserva os cabeçalhos Cache-Control originais nos descritores de recursos. Quando false está ausente, reescreve os cabeçalhos Cache-Control para no-cache para evitar o cache agressivo do cliente durante o desenvolvimento.
EnableStaticAssetsDevelopmentIntegrity Quando true, mantém propriedades de integridade em descritores de ativos. Quando false ou ausente, remove qualquer propriedade de integridade para evitar incompatibilidades quando os arquivos são alterados durante o desenvolvimento.

Recursos adicionais