如何处理ASP.NET Core中HTML5客户端路由回退的问题(2)

<rewrite> <rules> <!-- Make sure you have a <base href="https://www.jb51.net/" /> tag to fix the root path or all relative links will break on rewrite --><rule stopProcessing="true"> <match url=".*" /> <conditions logicalGrouping="MatchAll"> <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" /> <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" /> <add input="{REQUEST_URI}" pattern="api/" negate="true" /> </conditions> <action type="Rewrite" url="wwwroot/index.html" /> </rule> </rules></rewrite>

您可以从以下任何位置安装UrlRewrite模块:

Microsoft下载网站

choco install urlrewrite

Web平台安装程序

如果你在Linux上运行Docker和nginX或者Apache,那么类似的Rewrite选项就可以在那里使用。

让ASP.NET Core处理客户端路由

如前所述,我通常使用像IIS或nginX这样的前端Web服务器来处理重定向,但是通常在测试或内部应用程序时,只需要Kestrel直接为应用程序提供服务即可。如果您直接让Kestrel处理HTTP流量,那么您需要在ASP.NET Core代码中处理客户端路由。

捕获所有app.Run()处理程序

有很多方法可用,但是我发现了在Startup类的Configure()方法中使用一个非常简单的后备处理程序来处理客户端路由的最简单的方法:

// set up whatever routes you use with UseMvc()// you may not need to set up any routes here// if you only use attribute routes!app.UseMvc(routes =>{ routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}");});//handle client side routesapp.Run( async (context) =>{ context.Response.ContentType = "text/html"; await context.Response.SendFileAsync(Path.Combine(env.WebRootPath,"index.html"));});

关键是app.Run()位于路由后的管道末端的中间件处理程序。如果服务器端路由不能找到匹配的路由,这个通用处理程序就会启动。

上面的代码是你可以做的最简单的事情,只是把内容发送index.html到客户端。如果您有多个静态页面和SPA筒仓,您可以在其中添加额外的逻辑来尝试确定需要加载哪个页面。

请注意,内容不会重定向到,而是作为内嵌流发送到现有的URL请求,以便用户请求的URL保持不变。这确保了当用户请求:4200/albums你回到那个客户端页面而不是index.html。

捕获所有路由处理程序

另一种方法是在路由定义中使用最后定义的全部捕获的 MVC路由处理程序。这基本上拿起你的MVC路由配置无法处理的任何URL,然后路由到你指定的路线。

使用catch-all处理程序设置您的MVC路线,将此代码放在您的Startup类的Configure()方法中:

app.UseMvc(routes =>{ // default routes plus any other custom routesroutes.MapRoute(name: "default",template: "{controller=Home}/{action=Index}/{id?}"); // Catch all Route - catches anything not caught be other routesroutes.MapRoute(name: "catch-all",template: "{*url}",defaults: new {controller = "AlbumViewerApi", action = "RedirectIndex"});});

然后执行完全相同的事情中间件处理程序使用:index.html使用以下代码将内容流式传输到客户端:

// we need hosting environment for base pathpublic IHostingEnvironment HostingEnv { get; }public AlbumViewerApiController(IHostingEnvironment env){ HostingEnv = env;}[HttpGet]public IActionResult RedirectIndex(){ return new PhysicalFileResult( Path.Combine(HostingEnv.WebRootPath,"index.html"), new MediaTypeHeaderValue("text/html") );}

Catch-All Route不使用属性路由

确保您为回退路线指定的路线不具有分配给它的属性路线。当我昨天检查出来的时候,我无法得到一条全面的路线,直到我[Route("api/RedirectIndex")]从控制器的操作中移除 了这个全部工作。

SpaServices

SpaServices提供了另一个选项,routes.MapSpaFallbackRoute()尽管我自己也没有尝试过,但是如果您已经在ASP.NET Core应用程序中使用了Spa服务,那么这可能是一个简单的方法来实现这个功能,包括潜在的支持服务器预渲染。

概要

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdpyxs.html