evento
19/11, 23 - 21/11, 23
Participe de sessões on-line no Microsoft Ignite criadas para expandir suas habilidades e ajudá-lo a lidar com os problemas complexos de hoje.
Registe-se agoraEste browser já não é suportado.
Atualize para o Microsoft Edge para tirar partido das mais recentes funcionalidades, atualizações de segurança e de suporte técnico.
Nota
Esta não é a versão mais recente deste artigo. Para a versão atual, consulte a versão .NET 9 deste artigo.
Aviso
Esta versão do ASP.NET Core não tem mais suporte. Para obter mais informações, confira .NET e a Política de Suporte do .NET Core. Para informações sobre a versão vigente, confira a Versão do .NET 8 deste artigo.
Importante
Essas informações relacionam-se ao produto de pré-lançamento, que poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.
Para a versão atual, consulte a versão .NET 9 deste artigo.
Por Rick Anderson
Arquivos estáticos, como HTML, CSS, imagens e JavaScript, são ativos que um aplicativo ASP.NET Core fornece diretamente para os clientes por padrão.
Para obter diretrizes sobre arquivos estáticos Blazor, que adicionam ou se sobrepõem às diretrizes deste artigo, consulte Arquivos estáticos do ASP.NET Core Blazor.
Os arquivos estáticos são armazenados no diretório raiz Web do projeto. O diretório padrão é {content root}/wwwroot
, mas pode ser alterado com o método UseWebRoot. Para obter mais informações, consulte Raiz de conteúdo e Raiz web.
O método CreateBuilder define a raiz do conteúdo como o diretório atual:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.MapStaticAssets();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
Os arquivos estáticos são acessíveis por meio de um caminho relativo à raiz Web. Por exemplo, os modelos de projeto do Aplicativo Web contêm várias pastas dentro da pasta wwwroot
:
wwwroot
css
js
lib
Considere um aplicativo com o arquivo wwwroot/images/MyImage.jpg
. O formato de URI para acessar um arquivo na pasta images
é https://<hostname>/images/<image_file_name>
. Por exemplo, https://localhost:5001/images/MyImage.jpg
A criação de aplicativos Web com bom desempenho requer a otimização do fornecimento de ativos ao navegador. As possíveis otimizações incluem:
MapStaticAssets são convenções de endpoint de roteamento que otimizam a entrega de ativos estáticos em um aplicativo. Ele foi projetado para funcionar com todas as estruturas de interface do usuário, incluindo Blazor, Razor Pages e MVC.
UseStaticFiles
também exibe arquivos estáticos, mas não fornece o mesmo nível de otimização que MapStaticAssets
. Para obter uma comparação de UseStaticFiles
e MapStaticAssets
, veja Otimização da entrega de ativos da Web estáticos .
Os modelos de aplicativo Web padrão chamam o método MapStaticAssets no Program.cs
, que permite que arquivos estáticos sejam fornecidos:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.MapStaticAssets();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
A sobrecarga do método UseStaticFiles
sem parâmetro marca os arquivos raiz Web como fornecíveis. As seguintes referências de marcação wwwroot/images/MyImage.jpg
:
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
Na marcação anterior, o caractere ~
de til aponta para a raiz Web.
Considere uma hierarquia de diretórios na qual os arquivos estáticos a serem fornecidos residam fora da raiz Web:
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
Uma solicitação pode acessar o arquivo red-rose.jpg
configurando o middleware de arquivo estático da seguinte maneira:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(); //Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
No código anterior, a hierarquia de diretórios MyStaticFiles é exposta publicamente por meio do segmento do URI StaticFiles. Uma solicitação para https://<hostname>/StaticFiles/images/red-rose.jpg
fornece ao arquivo red-rose.jpg
.
As seguintes referências de marcação MyStaticFiles/images/red-rose.jpg
:
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
Para fornecer arquivos de vários locais, consulte Fornecer arquivos de vários locais.
Um objeto StaticFileOptions pode ser usado para definir cabeçalhos de resposta HTTP. Além de configurar o fornecimento de arquivo estático da raiz Web, o seguinte código define o cabeçalho de controle por cache:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append(
"Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
}
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
O código anterior disponibiliza arquivos estáticos publicamente no cache local por uma semana.
Os modelos de ASP.NET Core chamam MapStaticAssets 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:
wwwroot
, são acessíveis publicamente.Para fornecer arquivos estáticos com base na autorização:
wwwroot
.UseStaticFiles
, especificando um caminho, depois de chamar UseAuthorization
.using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using StaticFileAuth.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.MapRazorPages();
app.Run();
No código anterior, a política de autorização de fallback exige que todos os usuários sejam autenticados. Pontos de extremidade, como controladores, Páginas do Razor etc., 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 em wwwroot
são acessíveis publicamente porque o middleware de arquivo estático padrão (app.UseStaticFiles();
) é chamado antes de UseAuthentication
. Os ativos estáticos na pasta MyStaticFiles exigem autenticação. O código de amostra demonstra isso.
Uma abordagem alternativa para fornecer arquivos com base na autorização é:
Armazene-os fora do wwwroot
e de qualquer diretório acessível ao middleware de arquivo estático.
Forneça-os por meio de um método de ação ao qual a autorização é aplicada e retorne um objeto FileResult:
[Authorize]
public class BannerImageModel : PageModel
{
private readonly IWebHostEnvironment _env;
public BannerImageModel(IWebHostEnvironment env) =>
_env = env;
public PhysicalFileResult OnGet()
{
var filePath = Path.Combine(
_env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
return PhysicalFile(filePath, "image/jpeg");
}
}
A abordagem anterior exige uma página ou um ponto de extremidade por arquivo. O seguinte código retorna ou carrega arquivos para os usuários autenticados:
app.MapGet("/files/{fileName}", IResult (string fileName) =>
{
var filePath = GetOrCreateFilePath(fileName);
if (File.Exists(filePath))
{
return TypedResults.PhysicalFile(filePath, fileDownloadName: $"{fileName}");
}
return TypedResults.NotFound("No file found with the supplied file name");
})
.WithName("GetFileByName")
.RequireAuthorization("AuthenticatedUsers");
app.MapPost("/files",
async (IFormFile file, LinkGenerator linker, HttpContext context) =>
{
// Don't rely on the file.FileName as it is only metadata that can be
// manipulated by the end-user. See 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");
app.Run();
IFormFile no exemplo anterior usa o buffer de memória para carregar. Para lidar com arquivos grandes, use streaming. Veja Carregar arquivos grandes com streaming.
Confira a pasta StaticFileAuth do GitHub para ver a amostra completa.
A navegação no diretório permite a listagem de diretórios nos diretórios especificados.
A navegação no diretório está desabilitada por padrão por motivos de segurança. Para obter mais informações, consulte Considerações sobre segurança relacionadas a arquivos estáticos.
Habilite a navegação no diretório com AddDirectoryBrowser e UseDirectoryBrowser:
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.MapStaticAssets();
var fileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.WebRootPath, "images"));
var requestPath = "/MyImages";
// Enable displaying browser links.
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = fileProvider,
RequestPath = requestPath
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = fileProvider,
RequestPath = requestPath
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
O código anterior permite a navegação no diretório da pasta wwwroot/images usando a URL https://<hostname>/MyImages
, com links para cada arquivo e pasta:
AddDirectoryBrowser
adiciona serviços exigidos pelo middleware de pesquisa no 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 em todos os aplicativos.
Definir uma página padrão fornece aos visitantes um ponto de partida em um site. Para fornecer um arquivo padrão de wwwroot
sem exigir que a URL de solicitação para incluir o nome do arquivo, chame o método UseDefaultFiles:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
UseDefaultFiles
deve ser chamado antes de UseStaticFiles
para fornecer o arquivo padrão. UseDefaultFiles
é um regenerador de URL que não fornece o arquivo.
Com UseDefaultFiles
, as solicitações para uma pasta em wwwroot
pesquisam:
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. Por exemplo, no aplicativo de amostra, uma solicitação para https://localhost:<port>/def/
exibe default.html
de wwwroot/def
.
O seguinte código altera o nome do arquivo padrão para mydefault.html
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
UseFileServer combina a funcionalidade de UseStaticFiles
, UseDefaultFiles
e opcionalmente UseDirectoryBrowser
.
Chame app.UseFileServer
para habilitar o fornecimento de arquivos estáticos e o arquivo padrão. A navegação no diretório não está habilitada:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
O código a seguir permite o fornecimento de arquivos estáticos, do arquivo padrão e da navegação no diretório:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer(enableDirectoryBrowsing: true);
app.UseRouting();
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
Considere a seguinte hierarquia de diretórios:
wwwroot
css
images
js
MyStaticFiles
defaultFiles
default.html
image3.png
images
MyImage.jpg
O código a seguir permite o fornecimento de arquivos estáticos, do arquivo padrão e da navegação no diretório de MyStaticFiles
:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
AddDirectoryBrowser precisa ser chamado quando o valor da propriedade EnableDirectoryBrowsing
é true
.
Com o uso da hierarquia de arquivos anterior e do código, as URLs são resolvidas da seguinte maneira:
URI | Resposta |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
listagem de diretório |
https://<hostname>/StaticFiles/defaultFiles |
MyStaticFiles/defaultFiles/default.html |
https://<hostname>/StaticFiles/defaultFiles/image3.png |
MyStaticFiles/defaultFiles//image3.png |
Se nenhum arquivo nomeado como padrão existir no diretório MyStaticFiles, https://<hostname>/StaticFiles
retornará a listagem de diretórios com links clicáveis:
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://<hostname>/StaticFiles
para https://<hostname>/StaticFiles/
. As URLs relativas dentro do diretório StaticFiles são inválidas sem uma barra à direita (/
), a menos que a opção RedirectToAppendTrailingSlash de DefaultFilesOptions seja usada.
A classe FileExtensionContentTypeProvider contém uma propriedade Mapeamentos que serve como um mapeamento de extensões de arquivo para tipos de conteúdo MIME. Na amostra a seguir, várias extensões de arquivo são mapeadas para tipos MIME conhecidos. A extensão .rtf é substituída e .mp4 é removida:
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
// 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
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
Consulte Tipos de conteúdo MIME.
O middleware de arquivo estático compreende 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 aprovará 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 seguinte código habilita o fornecimento de tipos desconhecidos e renderiza o arquivo desconhecido como uma imagem:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
app.UseAuthorization();
app.MapDefaultControllerRoute().WithStaticAssets();
app.MapRazorPages().WithStaticAssets();
app.Run();
Com o código anterior, uma solicitação para um arquivo com um tipo de conteúdo desconhecido é retornada como uma imagem.
Aviso
Habilitar ServeUnknownFileTypes é um risco à segurança. Ela está desabilitada por padrão, e seu uso não é recomendado. FileExtensionContentTypeProvider fornece uma alternativa mais segura para o fornecimento de arquivos com extensões não padrão.
Considere a seguinte página Razor que exibe o arquivo /MyStaticFiles/image3.png
:
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
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. O exemplo a seguir chama UseStaticFiles
duas vezes para fornecer arquivos de wwwroot
e MyStaticFiles
:
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
Usando o código anterior:
/MyStaticFiles/image3.png
é exibido.WebRootFileProvider
não foi atualizado para incluir a pasta MyStaticFiles
.O código a seguir atualiza o WebRootFileProvider
, que permite que o auxiliar de marcação de imagem forneça uma versão:
var webRootProvider = new PhysicalFileProvider(builder.Environment.WebRootPath);
var newPathProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"));
var compositeProvider = new CompositeFileProvider(webRootProvider,
newPathProvider);
// Update the default provider.
app.Environment.WebRootFileProvider = compositeProvider;
app.MapStaticAssets();
Nota
A abordagem anterior se aplica a Razor Pages e aplicativos MVC. Para obter diretrizes que se aplicam aos Blazor Web Apps, consulte Arquivos estáticos do ASP.NET Core Blazor.
Aviso
UseDirectoryBrowser
e UseStaticFiles
podem causar a perda de 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, Páginas do Razor, arquivos de configuração, etc.
As URLs para o conteúdo exposto com UseDirectoryBrowser
, UseStaticFiles
e MapStaticAssets
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:
Aviso
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 arquivo web.config não foi implantado.
.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.Quando IWebHostEnvironment.WebRootPath é definido como uma pasta diferente de wwwroot
:
wwwroot
e os atualizados IWebHostEnvironment.WebRootPath
são fornecidos do wwwroot
.IWebHostEnvironment.WebRootPath
.Considere um aplicativo Web criado com o modelo da Web vazio:
Contendo um arquivo Index.html
em wwwroot
e wwwroot-custom
.
Com o seguinte arquivo Program.cs
atualizado que define WebRootPath = "wwwroot-custom"
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in "wwwroot-custom"
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.UseDefaultFiles();
app.MapStaticAssets();
app.Run();
No código anterior, solicita /
:
wwwroot/Index.html
wwwroot-custom/Index.html
Para garantir que os ativos de wwwroot-custom
sejam retornados, use uma das seguintes abordagens:
Exclua ativos nomeados duplicados em wwwroot
.
Defina "ASPNETCORE_ENVIRONMENT"
em Properties/launchSettings.json
para qualquer valor diferente de "Development"
.
Desabilite completamente os ativos da Web estáticos definindo <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
no arquivo de projeto. AVISO, desabilitar ativos da Web estáticos desabilita Razor bibliotecas de classes.
Adicione o seguinte XML ao arquivo do projeto:
<ItemGroup>
<Content Remove="wwwroot\**" />
</ItemGroup>
O código a seguir atualiza IWebHostEnvironment.WebRootPath
para um valor que não é de desenvolvimento, garantindo que o conteúdo duplicado seja retornado de wwwroot-custom
ao invés de wwwroot
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Examine Hosting environment: logging value
EnvironmentName = Environments.Staging,
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
app.Environment.IsDevelopment().ToString());
app.UseDefaultFiles();
app.MapStaticAssets();
app.Run();
Por Rick Anderson
Arquivos estáticos, como HTML, CSS, imagens e JavaScript, são ativos que um aplicativo ASP.NET Core fornece diretamente para os clientes por padrão.
Os arquivos estáticos são armazenados no diretório raiz Web do projeto. O diretório padrão é {content root}/wwwroot
, mas pode ser alterado com o método UseWebRoot. Para obter mais informações, consulte Raiz de conteúdo e Raiz web.
O método CreateBuilder define a raiz do conteúdo como o diretório atual:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Os arquivos estáticos são acessíveis por meio de um caminho relativo à raiz Web. Por exemplo, os modelos de projeto do Aplicativo Web contêm várias pastas dentro da pasta wwwroot
:
wwwroot
css
js
lib
Considere criar a pasta wwwroot/images e adicionar o arquivo wwwroot/images/MyImage.jpg
. O formato de URI para acessar um arquivo na pasta images
é https://<hostname>/images/<image_file_name>
. Por exemplo, https://localhost:5001/images/MyImage.jpg
Os modelos de aplicativo Web padrão chamam o método UseStaticFiles no Program.cs
, que permite que arquivos estáticos sejam fornecidos:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
A sobrecarga do método UseStaticFiles
sem parâmetro marca os arquivos raiz Web como fornecíveis. As seguintes referências de marcação wwwroot/images/MyImage.jpg
:
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
Na marcação anterior, o caractere ~
de til aponta para a raiz Web.
Considere uma hierarquia de diretórios na qual os arquivos estáticos a serem fornecidos residam fora da raiz Web:
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
Uma solicitação pode acessar o arquivo red-rose.jpg
configurando o middleware de arquivo estático da seguinte maneira:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
No código anterior, a hierarquia de diretórios MyStaticFiles é exposta publicamente por meio do segmento do URI StaticFiles. Uma solicitação para https://<hostname>/StaticFiles/images/red-rose.jpg
fornece ao arquivo red-rose.jpg
.
As seguintes referências de marcação MyStaticFiles/images/red-rose.jpg
:
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
Para fornecer arquivos de vários locais, consulte Fornecer arquivos de vários locais.
Um objeto StaticFileOptions pode ser usado para definir cabeçalhos de resposta HTTP. Além de configurar o fornecimento de arquivo estático da raiz Web, o seguinte código define o cabeçalho de controle por cache:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append(
"Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
}
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
O código anterior disponibiliza arquivos estáticos publicamente no cache local por uma semana (604800 segundos).
Os modelos de ASP.NET Core chamam 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:
wwwroot
, são acessíveis publicamente.Para fornecer arquivos estáticos com base na autorização:
wwwroot
.UseStaticFiles
, especificando um caminho, depois de chamar UseAuthorization
.using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using StaticFileAuth.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.MapRazorPages();
app.Run();
No código anterior, a política de autorização de fallback exige que todos os usuários sejam autenticados. Pontos de extremidade, como controladores, Páginas do Razor etc., 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 em wwwroot
são acessíveis publicamente porque o middleware de arquivo estático padrão (app.UseStaticFiles();
) é chamado antes de UseAuthentication
. Os ativos estáticos na pasta MyStaticFiles exigem autenticação. O código de amostra demonstra isso.
Uma abordagem alternativa para fornecer arquivos com base na autorização é:
Armazene-os fora do wwwroot
e de qualquer diretório acessível ao middleware de arquivo estático.
Forneça-os por meio de um método de ação ao qual a autorização é aplicada e retorne um objeto FileResult:
[Authorize]
public class BannerImageModel : PageModel
{
private readonly IWebHostEnvironment _env;
public BannerImageModel(IWebHostEnvironment env) =>
_env = env;
public PhysicalFileResult OnGet()
{
var filePath = Path.Combine(
_env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
return PhysicalFile(filePath, "image/jpeg");
}
}
A abordagem anterior exige uma página ou um ponto de extremidade por arquivo. O seguinte código retorna ou carrega arquivos para os usuários autenticados:
app.MapGet("/files/{fileName}", IResult (string fileName) =>
{
var filePath = GetOrCreateFilePath(fileName);
if (File.Exists(filePath))
{
return TypedResults.PhysicalFile(filePath, fileDownloadName: $"{fileName}");
}
return TypedResults.NotFound("No file found with the supplied file name");
})
.WithName("GetFileByName")
.RequireAuthorization("AuthenticatedUsers");
// IFormFile uses memory buffer for uploading. For handling large file use streaming instead.
// https://video2.skills-academy.com/aspnet/core/mvc/models/file-uploads#upload-large-files-with-streaming
app.MapPost("/files", async (IFormFile file, LinkGenerator linker, HttpContext context) =>
{
// Don't rely on the file.FileName as it is only metadata that can be manipulated by the end-user
// Take a look at 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");
app.Run();
Confira a pasta StaticFileAuth do GitHub para ver a amostra completa.
A navegação no diretório permite a listagem de diretórios nos diretórios especificados.
A navegação no diretório está desabilitada por padrão por motivos de segurança. Para obter mais informações, consulte Considerações sobre segurança relacionadas a arquivos estáticos.
Habilite a navegação no diretório com AddDirectoryBrowser e UseDirectoryBrowser:
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
var fileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.WebRootPath, "images"));
var requestPath = "/MyImages";
// Enable displaying browser links.
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = fileProvider,
RequestPath = requestPath
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = fileProvider,
RequestPath = requestPath
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
O código anterior permite a navegação no diretório da pasta wwwroot/images usando a URL https://<hostname>/MyImages
, com links para cada arquivo e pasta:
AddDirectoryBrowser
adiciona serviços exigidos pelo middleware de pesquisa no 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 em todos os aplicativos.
Definir uma página padrão fornece aos visitantes um ponto de partida em um site. Para fornecer um arquivo padrão de wwwroot
sem exigir que a URL de solicitação para incluir o nome do arquivo, chame o método UseDefaultFiles:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
UseDefaultFiles
deve ser chamado antes de UseStaticFiles
para fornecer o arquivo padrão. UseDefaultFiles
é um regenerador de URL que não fornece o arquivo.
Com UseDefaultFiles
, as solicitações para uma pasta em wwwroot
pesquisam:
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 mydefault.html
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
UseFileServer combina a funcionalidade de UseStaticFiles
, UseDefaultFiles
e opcionalmente UseDirectoryBrowser
.
Chame app.UseFileServer
para habilitar o fornecimento de arquivos estáticos e o arquivo padrão. A navegação no diretório não está habilitada:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
O código a seguir permite o fornecimento de arquivos estáticos, do arquivo padrão e da navegação no diretório:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer(enableDirectoryBrowsing: true);
app.UseRouting();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Considere a seguinte hierarquia de diretórios:
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
O código a seguir permite o fornecimento de arquivos estáticos, do arquivo padrão e da navegação no diretório de MyStaticFiles
:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
AddDirectoryBrowser precisa ser chamado quando o valor da propriedade EnableDirectoryBrowsing
é true
.
Com o uso da hierarquia de arquivos anterior e do código, as URLs são resolvidas da seguinte maneira:
URI | Resposta |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
Se nenhum arquivo nomeado como padrão existir no diretório MyStaticFiles, https://<hostname>/StaticFiles
retornará a listagem de diretórios com links clicáveis:
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://<hostname>/StaticFiles
para https://<hostname>/StaticFiles/
. As URLs relativas dentro do diretório StaticFiles são inválidas sem uma barra à direita (/
), a menos que a opção RedirectToAppendTrailingSlash de DefaultFilesOptions seja usada.
A classe FileExtensionContentTypeProvider contém uma propriedade Mappings
que fornece como um mapeamento de extensões de arquivo para tipos de conteúdo MIME. Na amostra a seguir, várias extensões de arquivo são mapeadas para tipos MIME conhecidos. A extensão .rtf é substituída e .mp4 é removida:
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
// 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
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Consulte Tipos de conteúdo MIME.
O middleware de arquivo estático compreende 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 aprovará 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 seguinte código habilita o fornecimento de tipos desconhecidos e renderiza o arquivo desconhecido como uma imagem:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Com o código anterior, uma solicitação para um arquivo com um tipo de conteúdo desconhecido é retornada como uma imagem.
Aviso
Habilitar ServeUnknownFileTypes é um risco à segurança. Ela está desabilitada por padrão, e seu uso não é recomendado. FileExtensionContentTypeProvider fornece uma alternativa mais segura para o fornecimento de arquivos com extensões não padrão.
Considere a seguinte página Razor que exibe o arquivo /MyStaticFiles/image3.png
:
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
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. O exemplo a seguir chama UseStaticFiles
duas vezes para fornecer arquivos de wwwroot
e MyStaticFiles
:
app.UseStaticFiles(); // Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
Usando o código anterior:
/MyStaticFiles/image3.png
é exibido.WebRootFileProvider
não foi atualizado para incluir a pasta MyStaticFiles
.O código a seguir atualiza o WebRootFileProvider
, que permite que o auxiliar de marcação de imagem forneça uma versão:
var webRootProvider = new PhysicalFileProvider(builder.Environment.WebRootPath);
var newPathProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"));
var compositeProvider = new CompositeFileProvider(webRootProvider,
newPathProvider);
// Update the default provider.
app.Environment.WebRootFileProvider = compositeProvider;
app.UseStaticFiles();
Nota
A abordagem anterior se aplica a Razor Pages e aplicativos MVC. Para obter diretrizes que se aplicam aos Blazor Web Apps, consulte Arquivos estáticos do ASP.NET Core Blazor.
Aviso
UseDirectoryBrowser
e UseStaticFiles
podem causar a perda de 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, Páginas do Razor, 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:
Aviso
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 arquivo web.config não foi implantado.
.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.Quando IWebHostEnvironment.WebRootPath é definido como uma pasta diferente de wwwroot
:
wwwroot
e os atualizados IWebHostEnvironment.WebRootPath
são fornecidos do wwwroot
.IWebHostEnvironment.WebRootPath
.Considere um aplicativo Web criado com o modelo da Web vazio:
Contendo um arquivo Index.html
em wwwroot
e wwwroot-custom
.
Com o seguinte arquivo Program.cs
atualizado que define WebRootPath = "wwwroot-custom"
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in "wwwroot-custom"
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
app.Run();
No código anterior, solicita /
:
wwwroot/Index.html
wwwroot-custom/Index.html
Para garantir que os ativos de wwwroot-custom
sejam retornados, use uma das seguintes abordagens:
Exclua ativos nomeados duplicados em wwwroot
.
Defina "ASPNETCORE_ENVIRONMENT"
em Properties/launchSettings.json
para qualquer valor diferente de "Development"
.
Desabilite completamente os ativos da Web estáticos definindo <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
no arquivo de projeto. AVISO, desabilitar ativos da Web estáticos desabilita Razor bibliotecas de classes.
Adicione o seguinte JSON ao arquivo de projeto:
<ItemGroup>
<Content Remove="wwwroot\**" />
</ItemGroup>
O código a seguir atualiza IWebHostEnvironment.WebRootPath
para um valor que não é de desenvolvimento, garantindo que o conteúdo duplicado seja retornado de wwwroot-custom
ao invés de wwwroot
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Examine Hosting environment: logging value
EnvironmentName = Environments.Staging,
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
app.Environment.IsDevelopment().ToString());
app.UseDefaultFiles();
app.UseStaticFiles();
app.Run();
Por Rick Anderson e Kirk Larkin
Arquivos estáticos, como HTML, CSS, imagens e JavaScript, são ativos que um aplicativo ASP.NET Core fornece diretamente para os clientes por padrão.
Os arquivos estáticos são armazenados no diretório raiz Web do projeto. O diretório padrão é {content root}/wwwroot
, mas pode ser alterado com o método UseWebRoot. Para obter mais informações, consulte Raiz de conteúdo e Raiz web.
O método CreateBuilder define a raiz do conteúdo como o diretório atual:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Os arquivos estáticos são acessíveis por meio de um caminho relativo à raiz Web. Por exemplo, os modelos de projeto do Aplicativo Web contêm várias pastas dentro da pasta wwwroot
:
wwwroot
css
js
lib
Considere criar a pasta wwwroot/images e adicionar o arquivo wwwroot/images/MyImage.jpg
. O formato de URI para acessar um arquivo na pasta images
é https://<hostname>/images/<image_file_name>
. Por exemplo, https://localhost:5001/images/MyImage.jpg
Os modelos de aplicativo Web padrão chamam o método UseStaticFiles no Program.cs
, que permite que arquivos estáticos sejam fornecidos:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
A sobrecarga do método UseStaticFiles
sem parâmetro marca os arquivos raiz Web como fornecíveis. As seguintes referências de marcação wwwroot/images/MyImage.jpg
:
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
Na marcação anterior, o caractere ~
de til aponta para a raiz Web.
Considere uma hierarquia de diretórios na qual os arquivos estáticos a serem fornecidos residam fora da raiz Web:
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
Uma solicitação pode acessar o arquivo red-rose.jpg
configurando o middleware de arquivo estático da seguinte maneira:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
No código anterior, a hierarquia de diretórios MyStaticFiles é exposta publicamente por meio do segmento do URI StaticFiles. Uma solicitação para https://<hostname>/StaticFiles/images/red-rose.jpg
fornece ao arquivo red-rose.jpg
.
As seguintes referências de marcação MyStaticFiles/images/red-rose.jpg
:
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
Para fornecer arquivos de vários locais, consulte Fornecer arquivos de vários locais.
Um objeto StaticFileOptions pode ser usado para definir cabeçalhos de resposta HTTP. Além de configurar o fornecimento de arquivo estático da raiz Web, o seguinte código define o cabeçalho de controle por cache:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var cacheMaxAgeOneWeek = (60 * 60 * 24 * 7).ToString();
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
ctx.Context.Response.Headers.Append(
"Cache-Control", $"public, max-age={cacheMaxAgeOneWeek}");
}
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
O código anterior disponibiliza arquivos estáticos publicamente no cache local por uma semana (604800 segundos).
Os modelos de ASP.NET Core chamam 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:
wwwroot
, são acessíveis publicamente.Para fornecer arquivos estáticos com base na autorização:
wwwroot
.UseStaticFiles
, especificando um caminho, depois de chamar UseAuthorization
.using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.FileProviders;
using StaticFileAuth.Data;
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();
builder.Services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseMigrationsEndPoint();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.MapRazorPages();
app.Run();
No código anterior, a política de autorização de fallback exige que todos os usuários sejam autenticados. Pontos de extremidade, como controladores, Páginas do Razor etc., 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 em wwwroot
são acessíveis publicamente porque o middleware de arquivo estático padrão (app.UseStaticFiles();
) é chamado antes de UseAuthentication
. Os ativos estáticos na pasta MyStaticFiles exigem autenticação. O código de amostra demonstra isso.
Uma abordagem alternativa para fornecer arquivos com base na autorização é:
wwwroot
e de qualquer diretório acessível ao middleware de arquivo estático.[Authorize]
public class BannerImageModel : PageModel
{
private readonly IWebHostEnvironment _env;
public BannerImageModel(IWebHostEnvironment env) =>
_env = env;
public PhysicalFileResult OnGet()
{
var filePath = Path.Combine(
_env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
return PhysicalFile(filePath, "image/jpeg");
}
}
A navegação no diretório permite a listagem de diretórios nos diretórios especificados.
A navegação no diretório está desabilitada por padrão por motivos de segurança. Para obter mais informações, consulte Considerações sobre segurança relacionadas a arquivos estáticos.
Habilite a navegação no diretório com AddDirectoryBrowser e UseDirectoryBrowser:
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
var fileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.WebRootPath, "images"));
var requestPath = "/MyImages";
// Enable displaying browser links.
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = fileProvider,
RequestPath = requestPath
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = fileProvider,
RequestPath = requestPath
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
O código anterior permite a navegação no diretório da pasta wwwroot/images usando a URL https://<hostname>/MyImages
, com links para cada arquivo e pasta:
AddDirectoryBrowser
adiciona serviços exigidos pelo middleware de pesquisa no 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 em todos os aplicativos.
Definir uma página padrão fornece aos visitantes um ponto de partida em um site. Para fornecer um arquivo padrão de wwwroot
sem exigir que a URL de solicitação para incluir o nome do arquivo, chame o método UseDefaultFiles:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
UseDefaultFiles
deve ser chamado antes de UseStaticFiles
para fornecer o arquivo padrão. UseDefaultFiles
é um regenerador de URL que não fornece o arquivo.
Com UseDefaultFiles
, as solicitações para uma pasta em wwwroot
pesquisam:
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 mydefault.html
:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
UseFileServer combina a funcionalidade de UseStaticFiles
, UseDefaultFiles
e opcionalmente UseDirectoryBrowser
.
Chame app.UseFileServer
para habilitar o fornecimento de arquivos estáticos e o arquivo padrão. A navegação no diretório não está habilitada:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
O código a seguir permite o fornecimento de arquivos estáticos, do arquivo padrão e da navegação no diretório:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer(enableDirectoryBrowsing: true);
app.UseRouting();
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Considere a seguinte hierarquia de diretórios:
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
O código a seguir permite o fornecimento de arquivos estáticos, do arquivo padrão e da navegação no diretório de MyStaticFiles
:
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
builder.Services.AddDirectoryBrowser();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
AddDirectoryBrowser precisa ser chamado quando o valor da propriedade EnableDirectoryBrowsing
é true
.
Com o uso da hierarquia de arquivos anterior e do código, as URLs são resolvidas da seguinte maneira:
URI | Resposta |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
Se nenhum arquivo nomeado como padrão existir no diretório MyStaticFiles, https://<hostname>/StaticFiles
retornará a listagem de diretórios com links clicáveis:
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://<hostname>/StaticFiles
para https://<hostname>/StaticFiles/
. As URLs relativas dentro do diretório StaticFiles são inválidas sem uma barra à direita (/
), a menos que a opção RedirectToAppendTrailingSlash de DefaultFilesOptions seja usada.
A classe FileExtensionContentTypeProvider contém uma propriedade Mappings
que fornece como um mapeamento de extensões de arquivo para tipos de conteúdo MIME. Na amostra a seguir, várias extensões de arquivo são mapeadas para tipos MIME conhecidos. A extensão .rtf é substituída e .mp4 é removida:
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
// 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
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Consulte Tipos de conteúdo MIME.
O middleware de arquivo estático compreende 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 aprovará 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 seguinte código habilita o fornecimento de tipos desconhecidos e renderiza o arquivo desconhecido como uma imagem:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
app.UseAuthorization();
app.MapDefaultControllerRoute();
app.MapRazorPages();
app.Run();
Com o código anterior, uma solicitação para um arquivo com um tipo de conteúdo desconhecido é retornada como uma imagem.
Aviso
Habilitar ServeUnknownFileTypes é um risco à segurança. Ela está desabilitada por padrão, e seu uso não é recomendado. FileExtensionContentTypeProvider fornece uma alternativa mais segura para o fornecimento de arquivos com extensões não padrão.
Considere a seguinte página Razor que exibe o arquivo /MyStaticFiles/image3.png
:
@page
<p> Test /MyStaticFiles/image3.png</p>
<img src="~/image3.png" class="img" asp-append-version="true" alt="Test">
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. O exemplo a seguir chama UseStaticFiles
duas vezes para fornecer arquivos de wwwroot
e MyStaticFiles
:
app.UseStaticFiles(); // Serve files from wwwroot
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"))
});
Usando o código anterior:
/MyStaticFiles/image3.png
é exibido.WebRootFileProvider
não foi atualizado para incluir a pasta MyStaticFiles
.O código a seguir atualiza o WebRootFileProvider
, que permite que o auxiliar de marcação de imagem forneça uma versão:
var webRootProvider = new PhysicalFileProvider(builder.Environment.WebRootPath);
var newPathProvider = new PhysicalFileProvider(
Path.Combine(builder.Environment.ContentRootPath, "MyStaticFiles"));
var compositeProvider = new CompositeFileProvider(webRootProvider,
newPathProvider);
// Update the default provider.
app.Environment.WebRootFileProvider = compositeProvider;
app.UseStaticFiles();
Aviso
UseDirectoryBrowser
e UseStaticFiles
podem causar a perda de 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, Páginas do Razor, 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:
Aviso
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 arquivo web.config não foi implantado.
.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.Quando IWebHostEnvironment.WebRootPath é definido como uma pasta diferente de wwwroot
:
wwwroot
e os atualizados IWebHostEnvironment.WebRootPath
são fornecidos do wwwroot
.IWebHostEnvironment.WebRootPath
.Considere um aplicativo Web criado com o modelo da Web vazio:
Contendo um arquivo Index.html
em wwwroot
e wwwroot-custom
.
Com o seguinte arquivo Program.cs
atualizado que define WebRootPath = "wwwroot-custom"
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Look for static files in "wwwroot-custom"
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.UseDefaultFiles();
app.UseStaticFiles();
app.Run();
No código anterior, solicita /
:
wwwroot/Index.html
wwwroot-custom/Index.html
Para garantir que os ativos de wwwroot-custom
sejam retornados, use uma das seguintes abordagens:
Exclua ativos nomeados duplicados em wwwroot
.
Defina "ASPNETCORE_ENVIRONMENT"
em Properties/launchSettings.json
para qualquer valor diferente de "Development"
.
Desabilite completamente os ativos da Web estáticos definindo <StaticWebAssetsEnabled>false</StaticWebAssetsEnabled>
no arquivo de projeto. AVISO, desabilitar ativos da Web estáticos desabilita Razor bibliotecas de classes.
Adicione o seguinte JSON ao arquivo de projeto:
<ItemGroup>
<Content Remove="wwwroot\**" />
</ItemGroup>
O código a seguir atualiza IWebHostEnvironment.WebRootPath
para um valor que não é de desenvolvimento, garantindo que o conteúdo duplicado seja retornado de wwwroot-custom
ao invés de wwwroot
:
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
Args = args,
// Examine Hosting environment: logging value
EnvironmentName = Environments.Staging,
WebRootPath = "wwwroot-custom"
});
var app = builder.Build();
app.Logger.LogInformation("ASPNETCORE_ENVIRONMENT: {env}",
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"));
app.Logger.LogInformation("app.Environment.IsDevelopment(): {env}",
app.Environment.IsDevelopment().ToString());
app.UseDefaultFiles();
app.UseStaticFiles();
app.Run();
Por Rick Anderson e Kirk Larkin
Arquivos estáticos, como HTML, CSS, imagens e JavaScript, são ativos que um aplicativo ASP.NET Core fornece diretamente para os clientes por padrão.
Exibir ou baixar código de exemplo (como baixar)
Os arquivos estáticos são armazenados no diretório raiz Web do projeto. O diretório padrão é {content root}/wwwroot
, mas pode ser alterado com o método UseWebRoot. Para obter mais informações, consulte Raiz de conteúdo e Raiz web.
O método CreateDefaultBuilder define a raiz do conteúdo como o diretório atual:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
O código anterior foi criado com o modelo de aplicativo Web.
Os arquivos estáticos são acessíveis por meio de um caminho relativo à raiz Web. Por exemplo, os modelos de projeto do Aplicativo Web contêm várias pastas dentro da pasta wwwroot
:
wwwroot
css
js
lib
Considere criar a pasta wwwroot/images e adicionar o arquivo wwwroot/images/MyImage.jpg
. O formato de URI para acessar um arquivo na pasta images
é https://<hostname>/images/<image_file_name>
. Por exemplo, https://localhost:5001/images/MyImage.jpg
Os modelos de aplicativo Web padrão chamam o método UseStaticFiles no Startup.Configure
, que permite que arquivos estáticos sejam fornecidos:
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.MapDefaultControllerRoute();
});
}
A sobrecarga do método UseStaticFiles
sem parâmetro marca os arquivos raiz Web como fornecíveis. As seguintes referências de marcação wwwroot/images/MyImage.jpg
:
<img src="~/images/MyImage.jpg" class="img" alt="My image" />
No código anterior, o caractere til ~/
aponta para a raiz Web.
Considere uma hierarquia de diretórios na qual os arquivos estáticos a serem fornecidos residam fora da raiz Web:
wwwroot
css
images
js
MyStaticFiles
images
red-rose.jpg
Uma solicitação pode acessar o arquivo red-rose.jpg
configurando o middleware de arquivo estático da seguinte maneira:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
// using Microsoft.Extensions.FileProviders;
// using System.IO;
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
No código anterior, a hierarquia de diretórios MyStaticFiles é exposta publicamente por meio do segmento do URI StaticFiles. Uma solicitação para https://<hostname>/StaticFiles/images/red-rose.jpg
fornece ao arquivo red-rose.jpg
.
As seguintes referências de marcação MyStaticFiles/images/red-rose.jpg
:
<img src="~/StaticFiles/images/red-rose.jpg" class="img" alt="A red rose" />
Um objeto StaticFileOptions pode ser usado para definir cabeçalhos de resposta HTTP. Além de configurar o fornecimento de arquivo estático da raiz Web, o seguinte código define o cabeçalho Cache-Control
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
const string cacheMaxAge = "604800";
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
{
// using Microsoft.AspNetCore.Http;
ctx.Context.Response.Headers.Append(
"Cache-Control", $"public, max-age={cacheMaxAge}");
}
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
O código anterior define a idade máxima como 604800 segundos (7 dias).
Os modelos de ASP.NET Core chamam 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:
wwwroot
, são acessíveis publicamente.Para fornecer arquivos estáticos com base na autorização:
wwwroot
.UseStaticFiles
, especificando um caminho, depois de chamar UseAuthorization
.public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
// wwwroot css, JavaScript, and images don't require authentication.
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles"
});
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
});
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddRazorPages();
services.AddAuthorization(options =>
{
options.FallbackPolicy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
});
}
// Remaining code ommitted for brevity.
No código anterior, a política de autorização de fallback exige que todos os usuários sejam autenticados. Pontos de extremidade, como controladores, Páginas do Razor etc., 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 em wwwroot
são acessíveis publicamente porque o middleware de arquivo estático padrão (app.UseStaticFiles();
) é chamado antes de UseAuthentication
. Os ativos estáticos na pasta MyStaticFiles exigem autenticação. O código de amostra demonstra isso.
Uma abordagem alternativa para fornecer arquivos com base na autorização é:
wwwroot
e de qualquer diretório acessível ao middleware de arquivo estático.[Authorize]
public IActionResult BannerImage()
{
var filePath = Path.Combine(
_env.ContentRootPath, "MyStaticFiles", "images", "red-rose.jpg");
return PhysicalFile(filePath, "image/jpeg");
}
A navegação no diretório permite a listagem de diretórios nos diretórios especificados.
A navegação no diretório está desabilitada por padrão por motivos de segurança. Para obter mais informações, consulte Considerações sobre segurança relacionadas a arquivos estáticos.
Habilite a navegação no diretório com:
Startup.ConfigureServices
.Startup.Configure
.public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDirectoryBrowser();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
// using Microsoft.Extensions.FileProviders;
// using System.IO;
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.WebRootPath, "images")),
RequestPath = "/MyImages"
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.WebRootPath, "images")),
RequestPath = "/MyImages"
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
O código anterior permite a navegação no diretório da pasta wwwroot/images usando a URL https://<hostname>/MyImages
, com links para cada arquivo e pasta:
Definir uma página padrão fornece aos visitantes um ponto de partida em um site. Para fornecer um arquivo padrão de wwwroot
sem exigir que a URL de solicitação para incluir o nome do arquivo, chame o método UseDefaultFiles:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
UseDefaultFiles
deve ser chamado antes de UseStaticFiles
para fornecer o arquivo padrão. UseDefaultFiles
é um regenerador de URL que não fornece o arquivo.
Com UseDefaultFiles
, as solicitações para uma pasta em wwwroot
pesquisam:
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 mydefault.html
:
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
O código a seguir mostra Startup.Configure
com o código anterior:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
var options = new DefaultFilesOptions();
options.DefaultFileNames.Clear();
options.DefaultFileNames.Add("mydefault.html");
app.UseDefaultFiles(options);
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
UseFileServer combina a funcionalidade de UseStaticFiles
, UseDefaultFiles
e opcionalmente UseDirectoryBrowser
.
Chame app.UseFileServer
para habilitar o fornecimento de arquivos estáticos e o arquivo padrão. A navegação no diretório não está habilitada. O código a seguir mostra Startup.Configure
com UseFileServer
:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
O código a seguir permite o fornecimento de arquivos estáticos, do arquivo padrão e da navegação no diretório:
app.UseFileServer(enableDirectoryBrowsing: true);
O código a seguir mostra Startup.Configure
com o código anterior:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseFileServer(enableDirectoryBrowsing: true);
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
Considere a seguinte hierarquia de diretórios:
wwwroot
css
images
js
MyStaticFiles
images
MyImage.jpg
default.html
O código a seguir permite o fornecimento de arquivos estáticos, do arquivo padrão e da navegação no diretório de MyStaticFiles
:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddDirectoryBrowser();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(); // For the wwwroot folder.
// using Microsoft.Extensions.FileProviders;
// using System.IO;
app.UseFileServer(new FileServerOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.ContentRootPath, "MyStaticFiles")),
RequestPath = "/StaticFiles",
EnableDirectoryBrowsing = true
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
AddDirectoryBrowser precisa ser chamado quando o valor da propriedade EnableDirectoryBrowsing
é true
.
Com o uso da hierarquia de arquivos e do código anterior, as URLs são resolvidas da seguinte maneira:
URI | Resposta |
---|---|
https://<hostname>/StaticFiles/images/MyImage.jpg |
MyStaticFiles/images/MyImage.jpg |
https://<hostname>/StaticFiles |
MyStaticFiles/default.html |
Se nenhum arquivo nomeado como padrão existir no diretório MyStaticFiles, https://<hostname>/StaticFiles
retornará a listagem de diretórios com links clicáveis:
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://<hostname>/StaticFiles
para https://<hostname>/StaticFiles/
. As URLs relativas dentro do diretório StaticFiles são inválidas sem uma barra à direita (/
).
A classe FileExtensionContentTypeProvider contém uma propriedade Mappings
que fornece como um mapeamento de extensões de arquivo para tipos de conteúdo MIME. Na amostra a seguir, várias extensões de arquivo são mapeadas para tipos MIME conhecidos. A extensão .rtf é substituída e .mp4 é removida:
// 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 = "/MyImages",
ContentTypeProvider = provider
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.WebRootPath, "images")),
RequestPath = "/MyImages"
});
O código a seguir mostra Startup.Configure
com o código anterior:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
// 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 = "/MyImages",
ContentTypeProvider = provider
});
app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(env.WebRootPath, "images")),
RequestPath = "/MyImages"
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
Consulte Tipos de conteúdo MIME.
O middleware de arquivo estático compreende 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 aprovará 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 seguinte código habilita o fornecimento de tipos desconhecidos e renderiza o arquivo desconhecido como uma imagem:
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
O código a seguir mostra Startup.Configure
com o código anterior:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true,
DefaultContentType = "image/png"
});
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
Com o código anterior, uma solicitação para um arquivo com um tipo de conteúdo desconhecido é retornada como uma imagem.
Aviso
Habilitar ServeUnknownFileTypes é um risco à segurança. Ela está desabilitada por padrão, e seu uso não é recomendado. FileExtensionContentTypeProvider fornece uma alternativa mais segura para o fornecimento de arquivos com extensões não padrão.
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. Saiba mais neste tópico do GitHub.
Aviso
UseDirectoryBrowser
e UseStaticFiles
podem causar a perda de 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, Páginas do Razor, 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:
Aviso
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 arquivo web.config não foi implantado.
.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.Comentários do ASP.NET Core
O ASP.NET Core é um projeto código aberto. Selecione um link para fornecer comentários:
evento
19/11, 23 - 21/11, 23
Participe de sessões on-line no Microsoft Ignite criadas para expandir suas habilidades e ajudá-lo a lidar com os problemas complexos de hoje.
Registe-se agora