Пытаюсь создать VueJS SPA с ядром ASP.NET в бэкэнде
Поскольку dotnet SDK
версия 3.0.100
больше не поддерживает Vue, я создал приложение React
dotnet new react
и поменял ClientApp
с приложением Vue
rm -rf ClientApp
vue create frontend
Все отлично работает, кроме 1 вещи
Всякий раз, когда я запускаю приложение http://localhost:5000 и нажимаю на любой Vue Routerссылка, скажем, http://localhost:5000/about (это работает), но если я обновляю, я получаю ожидаемый 404
Невозможно получить / о
То же самое происходит, если я набрал URL-адрес в браузере и получил прямой доступ
Стоит отметить, что приложение React по умолчанию не сталкивается с этой проблемой, я сравнил все между файлами двух приложений ASP.NET, используя этот инструмент и не обнаружил различий
Теперь Vue Router обрабатывает маршруты с помощью Javascript, потому что он использует хэш #! за кулисами, поэтому маршрутизатор ASP.NET пытается сопоставить URL с индексом AboutController @, которыйне существует, следовательно, 404
Research reЯ заверил, что я должен установить резервный символ подстановки для маршрутизатора SPA в Startup.cs
, но все ответы, которые я нашел здесь , здесь , здесь , на этот вопрос , ответьте здесь , на этот вопрос и этот использует app.UseMvc()
, и у меня его нет, я использую app.UseEndpoints
вместо
Я также пытался искать в GitHub, но те же результаты
В этом ответе рекомендует придерживаться app.UseEndPoints
и миграции Microsoftруководство тоже
Документация Vue Router рассказывает об этой самой проблеме и предлагает решение для приложений .NET, использующее web.config
для IIS, например, ответ здесь но я запускаю сервер Kestrel на машине с Linux, так что это не дает никакого эффекта
Вот мой Startup.cs
файл
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.SpaServices.ReactDevelopmentServer;
namespace spa
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// In production, the Vue files will be served from this directory
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "frontend/dist";
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseSpaStaticFiles();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "frontend";
if (env.IsDevelopment())
{
spa.UseReactDevelopmentServer(npmScript: "serve:bs");
}
});
}
}
}
Я переместил это приложение в GitHub здесь , чтобы сделатьего легко воспроизвести на тот случай, если я что-то забыл
Как я могу добиться того же эффекта от этого
app.UseMvc(routes =>
{
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
routes.MapRoute("spa-fallback", "{*anything}", new { controller = "Home", action = "Index" });
});
, используя app.UseEndpoints
?
На всякий случай, это уместно, вот мой маршрутизатор Vue
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
import NotFound from './views/NotFound.vue'
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [{
path: '/',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import( /* webpackChunkName: "about" */ './views/About.vue')
},
{
path: '/forecast',
name: 'forecast',
component: () => import( /* webpackChunkName: "forecast" */ './views/Forecast.vue')
},
{
path: '*',
component: NotFound
}
]
})