Ядро ASP.net MVC ловит весь маршрут обслуживает статический файл
Есть ли способ сделать перехват всех маршрутов статическим файлом?
Глядя на это http://blog.nbellocam.me/2016/03/21/routing-angular-2-asp-net-core/
Я в основном хочу что-то вроде этого:
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller}/{action=Index}");
routes.MapRoute("spa", "{*url}"); // This should serve SPA index.html
});
Таким образом, любой маршрут, который не соответствует контроллеру MVC, будет обслуживаться wwwroot/index.html
8 ответов
Если вы уже находитесь в стадии маршрутизации, вы прошли точку, когда статические файлы подаются в конвейер. Ваш стартап будет выглядеть примерно так:
app.UseStaticFiles();
...
app.UseMvc(...);
Порядок здесь важен. Таким образом, ваше приложение будет сначала искать статические файлы, что имеет смысл с точки зрения производительности - не нужно запускать конвейер MVC, если вы просто хотите выбросить статический файл.
Вы можете создать универсальное действие контроллера, которое будет возвращать содержимое файла. Например (кража кода в вашем комментарии):
public IActionResult Spa()
{
return File("~/index.html", "text/html");
}
Я должен был сделать некоторые дополнения к ответу @DavidG. Вот что я закончил
Startup.cs
app.UseStaticFiles();
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller}/{action}");
routes.MapRoute("Spa", "{*url}", defaults: new { controller = "Home", action = "Spa" });
});
HomeController.cs
public class HomeController : Controller
{
public IActionResult Spa()
{
return File("~/index.html", "text/html");
}
}
ASP.NET Core перехватывает все маршруты, для Web API и MVC настроены по-разному
С веб-API (if you're using prefix "api" for all server-side controllers eg. Route("api/[controller"]
):
app.Use(async (context, next) =>
{
await next();
var path = context.Request.Path.Value;
if (!path.StartsWith("/api") && !Path.HasExtension(path))
{
context.Request.Path = "/index.html";
await next();
}
});
app.UseStaticFiles();
app.UseDefaultFiles();
app.UseMvc();
С MVC (dotnet add package Microsoft.AspNetCore.SpaServices -Version x.y.z
):
app.UseStaticFiles();
app.UseDefaultFiles();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}");
routes.MapSpaFallbackRoute("spa", new { controller = "Home", action = "Index" });
});
Если вы не хотите вручную указывать, какие маршруты для API:
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseMvc()
//return index instead of 404
app.Use(async (context, next) => {
context.Request.Path = "/index.html";
await next();
});
app.UseStaticFiles();
То, что я использую это работает хорошо Microsoft.AspNetCore.Builder.SpaRouteExtensions.MapSpaFallbackRoute
:
app.UseMvc(routes =>
{
// Default route for SPA components, excluding paths which appear to be static files (have an extension)
routes.MapSpaFallbackRoute(
"spaFallback",
new { controller = "Home", action = "Index" });
});
HomeController.Index
имеет эквивалент вашего index.html
, Возможно, вы также можете перенаправить на статическую страницу.
Немного не по теме, но если у вас также есть API в том же проекте под api
В папке вы можете установить ответ 404 по умолчанию для любых маршрутов API, которые не совпадают:
routes.MapRoute(
"apiDefault",
"api/{*url}",
new { controller = "Home", action = "ApiNotFound" });
В результате вы получите следующее поведение:
/controller
=> Без расширения, так что обслуживайте страницу SPA по умолчанию сHomeController.Index
и пусть SPA управляет маршрутизацией/file.txt
=> Расширение обнаружено, подать статический файл/api/controller
=> правильный ответ API (используйте маршрутизацию атрибутов или настройте другую карту для контроллеров API)/api/non-existent-route
=> 404NotFound()
вернулся изHomeController.ApiNotFound
Во многих случаях вам понадобится API в отдельном проекте, но это жизнеспособная альтернатива.
Для того, чтобы служить index.html
от wwwroot
В папку должны быть добавлены следующие директивы (.Net Core 2).
Это позволяет обслуживать статические файлы:
app.UseStaticFiles();
Это позволяет получить файлы по умолчанию, например, index.html
:
app.UseDefaultFiles();
В ASP.NET Core 3.1 я использовал следующее:
Startup.cs
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseCors();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseDefaultFiles();
app.UseStaticFiles();
}
MyController.cs
[HttpGet("{anything}")]
public IActionResult GetSPA()
{
return File("~/index.html", "text/html");
}
В .NET Core 6 добавьтеapp.MapFallbackToFile("index.html");
в вашейProgram.cs
файл.
Вот пример кода из шаблона проекта ASP.NET Core с React:
app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
app.MapFallbackToFile("index.html");
app.Run();