#asp.net-core #.net-core #routes #asp.net-core-mvc
#asp.net-ядро #.net-ядро #маршруты #asp.net-core-mvc
Вопрос:
У меня есть CMS, работающая как ASP.NET Основное приложение MVC, и я хочу, чтобы:
- Для
/api/
(или/api/*
) и / или/admin/
(или/admin/*
) он перехватывает ссылку и правильно маршрутизирует, используя свой контроллер MVC - В противном случае используйте статический файл (которым я
index.html
управляюvue.js
приложением и его внутренним маршрутом).
Основное использование: если я наберу /admin
, запустите ASP.NET Основное приложение MVC, если я наберу /
(или что-то еще, например /pages/text
), вызовет, index.html
где vuejs
будет действовать маршрутизация.
Как я могу это сделать?
Пробовал это:
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseDefaultFiles(); // load index.html as default page
app.UseStaticFiles();
app.UseOrchardCore();
}
Но это работает только с /
, /api/*
и /admin/*
. Если я наберу /pages/text
, это вызовет ASP.NET Основной контроллер MVC и, очевидно, возвращает ошибку (не vuejs app
маршрутизацию).
Ответ №1:
Я сделал нечто подобное в размещенном на Blazor WebAssembly приложении с включенной аутентификацией. В моей ситуации, когда я звонил /api/{controller}
в Postman, я получал html вместо json.
Я исправил это, добавив:
app.UseEndpoints(endpoints =>
{
...
endpoints.Map("api/{**slug}", HandleApiFallback);
endpoints.MapFallbackToFile("{**slug}", "index.html");
});
private Task HandleApiFallback(HttpContext context)
{
context.Response.StatusCode = StatusCodes.Status404NotFound;
return Task.FromResult(0);
}
Я думаю, что это также может быть адаптировано для вашей ситуации.
Другой способ, который может сработать, это:
// In production, the Vue files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "ClientApp/dist";
});
app.UseSpaStaticFiles();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
if (env.IsDevelopment())
{
endpoints.MapToVueCliProxy(
"{*path}",
new SpaOptions { SourcePath = "ClientApp" },
npmScript: "serve",
regex: "Compiled successfully");
}
// Add MapRazorPages if the app uses Razor Pages. Since Endpoint Routing includes support for many frameworks, adding Razor Pages is now opt -in.
endpoints.MapRazorPages();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "ClientApp";
});
Ваше приложение Vue должно находиться внутри каталога с именем «ClientApp». Пожалуйста, взгляните на этот пример.
Ответ №2:
Вы могли бы написать промежуточное программное обеспечение, которое будет обрабатывать все 404 ответа, а затем переопределяет путь вашего запроса:
public class ReturnDefaultMiddleware
{
private readonly RequestDelegate _next;
public ReturnDefaultMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
await _next(context);
// If controller was found, return the actual response
if(context.Response.HasStarted || context.Response.StatusCode != (int) HttpStatusCode.NotFound)
return;
// Rewrite the request to request index.html
context.Request.Path = "/index.html";
// Rerun the rest of the request pipeline
await _next(context);
}
}
Это выполнит ваш конвейер запросов как обычно. Если конвейер отвечает 404, потому что не был найден контроллер, который может обрабатывать маршрут, запрос будет переопределен.
Запустив await _next(context)
снова весь процесс будут обработаны снова, но на новый index.html
маршрут.
Просто добавьте новое промежуточное программное обеспечение перед запуском чего-либо еще:
public void Configure(IApplicationBuilder app, IHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// Add custom middleware here
app.UseMiddleware<ReturnDefaultMiddleware>();
app.UseDefaultFiles(); // load index.html as default page
app.UseStaticFiles();
app.UseOrchardCore();
}
Редактировать
Я не узнал, что существуют конкретные маршруты, на которые API должен отвечать. Если вы хотите запустить конвейер запросов MVC только на некоторых определенных маршрутах, вы можете переопределить путь для всех других маршрутов:
app.UseWhen(ctx => !ctx.Request.Path.StartsWithSegments("/api") amp;amp; !ctx.Request.Path.StartsWithSegments("/admin"), builder =>
{
builder.UseMiddleware<ReturnDefaultMiddleware>();
});
Это добавит промежуточное программное обеспечение ко всем запросам, которые не начинаются с path /admin или / api.
Промежуточное программное обеспечение будет таким же простым, как это:
public class ReturnDefaultMiddleware
{
private readonly RequestDelegate _next;
public ReturnDefaultMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// Rewrite the request to request index.html
context.Request.Path = "/index.html";
// Rerun the request pipeline
await _next(context);
}
}
Обратите внимание, что относительные ссылки в вашем index.html не будет работать с этим решением. Вы могли бы рассмотреть возможность переопределения пути для определенных окончаний файлов или путей внутри промежуточного программного обеспечения.
Комментарии:
1. и что, когда происходит настоящий 404? Я потеряю его, перенаправив на «статические» файлы (что не так хорошо).
2. Если был найден соответствующий маршрут,
context.Response.HasStarted
будет true, поэтому запасной вариант использоваться не будет. Проверка была неправильной, и я исправил ее в своей правке.3. Размышления об этом заставляют меня прийти к выводу, что проверки
context.Response.HasStarted
достаточно, чтобы увидеть, был ли соответствующий маршрут.4. Пробовал ваш код, но не работает. Он просто возвращает 404
5. Смотрите мою правку в ответе. Если вы работаете с фиксированными маршрутами внутри вашего mvc, вы можете использовать
UseWhen
для переопределения пути на основе фактического префикса пути.
Ответ №3:
У меня была такая же проблема в ASP. NET 6 со сборкой моего приложения react, но я просто добавляю эту функцию, и это решило мою проблему (использует контроллеры, если их не найдено, использует навигацию моего приложения react, даже маршруты, которые не существуют, попадают на мою пользовательскую страницу 404 в react).
app.Use(async (context, next) =>
{
await next();
if (context.Response.StatusCode == 404 amp;amp; !Path.HasExtension(context.Request.Path.Value))
{
context.Request.Path = "/index.html";
context.Response.StatusCode = 200;
await next();
}
});
Я думаю, что вы уже использовали эти методы, если нет, то я использовал их ПОСЛЕ функции для маршрутизации
app.UseDefaultFiles();
app.UseStaticFiles();