这篇文章将为大家详细讲解有关怎么处理ASP.NET Core中HTML5客户端路由回退的问题,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
Html 5客户端路由?
如果您不知道HTML5客户端路由是什么,请快速回顾一下。
客户端框架实现他们自己的客户端路由机制,以便他们可以 - 就像服务器应用程序 - 在页面或组件之间进行导航。
Angular支持几种路由类型:
哈希路线(http:// localhost:4200 /#!/ albums或http:// localhost:4200 /#/ albums)
HTML 5路线(http:// localhost:4200 / albums)
#!/ 哈希邦德路线
前者是一种较早的方法,它直接与HTTP语义一起工作,指定任何具有a的URL #在客户端被触发并跳转到页面内的“本地”URL。框架可以拦截导航并检查跟随的URL内容#以确定路线。散列爆炸#!用于区分应用程序URL和普通#锚链接。
散列爆炸路线的好处是,他们只是工作。没有服务器端出血的路线,如果您书签或刷新客户端页面,它只是如预期的那样工作,因为散列逻辑是作为浏览器中本地URL解析的一部分执行的。很简单,对吧?它只是工作。
但缺点是,如果您必须手动输入网址,则这些网址非常难看且不直观。对于散列爆炸路线来说,这并不是一个很好的论据,但是不管它们是否对HTML5路由不利。
哈希在Angular中的Bang路由
Angular使用默认的HTML5客户端路由,但它是一个简单的开关来启用Hashbang路由,而不是HTML5路由::
// in app.module.tsproviders : [ .. // make sure you use this for Hash Urls rather than HTML 5 routing { provide: LocationStrategy, useClass: HashLocationStrategy },]
只要您routerLink在HTML模板中使用链接网址,并router.navigate()
在代码链接中使用,Angular交换机就会自动在两种模式之间进行切换。
HTML5路由使用更复杂的方法 - 它使用HTML5的Pushstate API来控制客户端的路由并管理地址栏显示。
这种方法的优点是,使用HTML5 API相对容易操作,并且使用标准的无延伸路由约定,使用Web应用程序和API时,URL更加简洁,易于控制。
但是HTML5路由需要服务器的明确支持来正确理解哪些路由是服务器路由,哪些是客户路由。
如果您在ASP.NET Core应用程序中没有对HTML5路由设置进行任何特殊处理,您将在应用程序中打开错误页面,或者从Kestrel中选择此默认显示:
如果客户端路由从书签,链接或完全刷新被触发到服务器,则需要提供index.html并保持原始URL不变。
然后,客户端应用程序将自行引导,并且内部路由启动,以希望将您甩回书签/刷新位置。
如果您在主流Web服务器上运行ASP.NET Core(或ASP.NET)应用程序,最简单且最有效的解决方案是重写客户端URL并为index.html给定的URL 提供内容。
在IIS上,您可以使用IIS重写模块来执行此操作。我最近在一篇博文中更详细地介绍了这一点:
如果你在Linux上运行Docker和nginX或者Apache,那么类似的Rewrite选项就可以在那里使用。
有很多方法可用,但是我发现了在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筒仓,您可以在其中添加额外的逻辑来尝试确定需要加载哪个页面。
另一种方法是在路由定义中使用最后定义的全部捕获的 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") );}
尽管旧的Hash Bang路线看起来不那么干净,但它们工作正常,不需要任何服务器端支持。对于需要支持古代浏览器的非公众应用程序或应用程序,在没有服务器支持的情况下,散列邦线路仍然是提供路由的可行方式。
最后,如果您正在使用完整的Web服务器,UrlRewriting是处理非ASP.NET内核后端直接处理的非API内容的最干净和最有效的方式。