.Net Core MVC 路由:有条件地为每个控制器设置 MapSpaFallbackRoute
Posted
技术标签:
【中文标题】.Net Core MVC 路由:有条件地为每个控制器设置 MapSpaFallbackRoute【英文标题】:.Net Core MVC Routing: Setting MapSpaFallbackRoute Conditionally Per Controller 【发布时间】:2017-02-12 20:25:09 【问题描述】:我正在开发一个项目,该项目涉及托管在单个 .Net Core 1.0 Web 应用程序上的多个单页应用程序。
目标是对每个 SPA 进行分区,以便它们都独立存在,每个都有自己的视图和控制器。
在 Startup.cs 中,我使用 Microsoft.AspNetCore.SpaServices MapSpaFallbackRoute 传递指向 SPA 的深层链接(在本例中为 Angular 2),因此 MVC 不会混淆并在页面刷新时引发 404。
当我在 MapSpaFallbackRoute 中手动设置控制器时,我一次只为一个 SPA 工作,但我想不出一种方法为每个 SPA 控制器有条件地设置它。
我假设 Mapwhen() 和 Run() 的组合可以让我到达我需要的地方,但我似乎无法让语法正确。
假设 SPA 被命名为“Dash1”、“Dash2”等。以下后备路线非常适合 Dash1:
app.UseMvc(routes =>
routes.MapRoute(
name: "default",
template: "controller=Home/action=Index/id?");
routes.MapSpaFallbackRoute("spa-fallback", new controller = "Dash1", action = "Index" );
);
我试过了:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
app.UseMvc(routes =>
routes.MapRoute(
name: "default",
template: "controller=Home/action=Index/id?");
);
app.Map("/Dash1", HandleDash1);
private static void HandleDash1(IApplicationBuilder app)
app.UseMvc(routes =>
routes.MapSpaFallbackRoute("spa-fallback", new controller = "Dash1", action = "Index" );
);
...但是当我导航到 Dash1 并尝试刷新页面时,浏览器会在所有 http 请求之前添加“/Dash1/”并破坏所有内容。
【问题讨论】:
这里完全是在猜测,但您在第一种方法中尝试过routes.MapSpaFallbackRoute("controller/spa-fallback", new action = "Index" );
吗?
我试了一下,但页面刷新仍然出现 404。第一个字符串参数只是路线的名称,但似乎应该可以这样做;只需将当前控制器注册为后备。
【参考方案1】:
我让它与 MapWhen() 一起工作,但每个 SPA 都必须以这种方式注册。
app.MapWhen(context => context.Request.Path.Value.StartsWith("/Dash1"), builder =>
builder.UseMvc(routes =>
routes.MapSpaFallbackRoute("dash1-fallback", new controller = "Dash1", action = "Index" );
);
);
app.UseMvc(routes =>
routes.MapRoute(
name: "default",
template: "controller=Home/action=Index/id?");
);
我正在使用这种方法来托管 Angular(2+) 应用程序。我最初使用 SystemJS 并将所有应用程序保存在一个项目中,但是当版本 4 发布时我转移到了 Angular CLI。
我发现管理应用程序的最佳方法是在解决方案中为每个应用程序创建一个单独的项目,并使用 NPM 脚本将捆绑的文件复制到“主”项目的 wwwroot 内的文件夹中。
我只是提供由 CLI 创建的静态 html 文件,而不是返回视图,但视图也可以正常工作。
public IActionResult Index()
return PhysicalFile(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/dash1", "index.html"), "text/HTML");
棘手的部分是管理路由器。您必须通过设置 window['_app_base'] 对应于当前控制器的路由来设置基本 href 并将路由传递给 Angular 路由器。
在 index.html 中包含以下内容:
<head>
// Set base href.
// You need to include the path if serving the static file from wwwroot
// Use '/' if using a View (I think, I had to change this when I switched to static files).
<base href="/dash1/">
<script>
(function ()
// You could type the controller path here again but this will infer it.
window['_app_base'] = '/' + window.location.pathname.split('/')[1];
)();
</script>
</head>
然后,Angular 路由器必须从窗口['_app_base'] 获取它的方位。在 app.module.ts 中包含以下内容:
import NgModule, Provider from '@angular/core';
import APP_BASE_HREF, Location from '@angular/common';
const baseHref: Provider =
provide: APP_BASE_HREF,
useValue: window['_app_base'] || '/'
;
最后,在 @NgModule 的 providers 数组中包含 baseHref。
【讨论】:
David,我很难理解如何在单个 ASP.Net Core MVC 应用程序中创建单独的 Angular 2 应用程序。您愿意提供一些见解吗? 嗨,TDC。我用更多信息更新了帖子。我正在使用 SystemJS 而不是 Webpack,并且有很多新的构建功能我还没有学到。我看到了您关于 Nuget 上可用的新 Angular 模板的问题,但此方法与 Webpack 不兼容,因此我在此处更新了此答案。希望对您有所帮助。 感谢大卫的澄清,非常感谢。我需要花一些时间来了解这一切是如何结合在一起的。我无法确定在 ASP.Net Core 中集成 Angular 是有利还是完全分散注意力(礼貌用语)。 非常感谢。我想知道每个 Angular 应用程序是否需要多个项目。我认为可以通过拥有单个 Angular 项目和代码拆分功能来简化该过程。 每个 SPA 单独的.net 项目不是必需的。使用 SystemJS,我根本没有任何问题。我认为,Angular CLI 能够管理每个项目的多个应用程序,但我还没有尝试过。我发现在专用项目中使用模拟控制器在本地开发前端应用程序比在一个项目的源代码控制中管理模拟环境更容易。可以这样做,并且可能有一个令人信服的论据。以上是关于.Net Core MVC 路由:有条件地为每个控制器设置 MapSpaFallbackRoute的主要内容,如果未能解决你的问题,请参考以下文章