2017-02-23 91 views
4

Есть ли способ сделать уловку всего маршрута служить статическому файлу?ASP.net core 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

+2

Если вы уже находитесь в элементе маршрутизации, вы прошли мимо p где статические файлы подаются в конвейере. Вы можете создать действие контроллера catch-all, которое вместо этого вернет содержимое файла. – DavidG

+0

Есть ли рекомендуемый способ сделать это? – Mardoxx

+0

Не так далеко, насколько я знаю. – DavidG

ответ

8

Если вы уже на этапе маршрутизации вы прошли мимо точки, где статические файлы обслуживаются в конвейере. Ваш стартап будет выглядеть примерно так:

app.UseStaticFiles(); 

... 

app.UseMvc(...); 

Порядок здесь важен. Таким образом, ваше приложение будет сначала искать статические файлы, что имеет смысл с точки зрения производительности - нет необходимости запускаться через конвейер MVC, если вы просто хотите выбросить статический файл.

Вы можете создать действие контроллера catch-all, которое вместо этого вернет содержимое файла. Например (кражи кода в вашем комментарии):

public IActionResult Spa() 
{ 
    return File("~/index.html", "text/html"); 
} 
+0

Какой класс 'File' вы используете? Это не может быть 'System.IO.FileSystem.File'. Не удается найти хороший матч. – Marcus

+1

@Marcus Это не класс файлов, это метод ['File'] (https://docs.microsoft.com/en-us/aspnet/core/api/microsoft.aspnetcore.mvc.controllerbase#Microsoft_AspNetCore_Mvc_ControllerBase_File_System_String_System_String_) метода класс контроллера. – DavidG

+0

Я был осел, забыл унаследовать от «Контролера», поэтому я не мог этого видеть. Спасибо! – Marcus

17

Мне пришлось внести некоторые дополнения в ответ @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"); 
    } 
} 
1

Что я использую, что хорошо работает 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 => 404 NotFound() вернулся из HomeController.ApiNotFound

В во многих случаях вам понадобится API в отдельном проекте, но это жизнеспособная альтернатива.

0

Для того, чтобы подать index.html из wwwroot, необходимо добавить следующие директивы (.Net Core 2).

Это позволяет обслуживать статические файлы:

app.UseStaticFiles(); 

Это позволяет получить по умолчанию файлы, например, index.html:

app.UseDefaultFiles(); 
6

ASP.NET ядро ​​перехватывать все маршруты для Web API и MVC настроены по-разному

С помощью Web 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.UseDefaultFiles(); 
app.UseStaticFiles(); 

app.UseMvc(); 

С MVC (dotnet add package Microsoft.AspNetCore.SpaServices -Version x.y.z):

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

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

    routes.MapSpaFallbackRoute("spa", new { controller = "Home", action = "Index" }); 
}); 
+1

Замечательно! Я использовал ваше первое решение, хотя я поместил 'UseStaticFiles' перед вашей логикой, чтобы сначала были загружены статические файлы, и мне не нужны' UseDefaultFiles'. Что еще более важно, мне пришлось установить путь как 'context.Request.Path ="/";' и в моем указателе HomeController Index, подавать 'File (" ~/index.html "," text/html ");'. –

Смежные вопросы