处理ASP.NET Core中的HTML5客户端路由回退
在使用由Angular,React,Vue等应用程序框架构建的客户端应用程序时,您总是会处理HTML5客户端路由,它将完全在浏览器中处理到页面和组件的客户端路由。几乎完全在浏览器中...
HTML5客户端路由在客户端上工作的很好,但是当深入链接到一个站点或在浏览器中按刷新时,客户端路由有一个恶习,变成服务器HTTP请求。请求可能未配置服务器的路由。
在这篇文章中,我将讨论如何使ASP.NET Core(或间接ASP.NET应用程序)通过有效地将客户端应用程序重新连接到其路由来处理这些“假”请求。
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交换机就会自动在两种模式之间进行切换。
在HTML中使用
<a routerLink="/albums" />链接在代码中使用:
router.navigate(["/album",album.id])
HTML5路由
HTML5路由使用更复杂的方法 - 它使用HTML5的Pushstate API来控制客户端的路由并管理地址栏显示。
这种方法的优点是,使用HTML5 API相对容易操作,并且使用标准的无延伸路由约定,使用Web应用程序和API时,URL更加简洁,易于控制。
但是HTML5路由需要服务器的明确支持来正确理解哪些路由是服务器路由,哪些是客户路由。
没有服务器处理的HTML5路由问题
问题在于HTML5客户端路由与服务器路由无法区分。
http://localhost:4200/albums可以很容易地将客户端URL作为服务器端URL。在完全在客户端上导航时,HTML5路线工作正常 - 应用程序可以拦截导航并在激活特定路线时路由到相应的客户端页面。
如果您使用深层链接导航到客户端驱动的应用程序,然后您将该页面书签为书签,然后使用该URL导航回到该页面,或者刷新当前活动页面,则会弹出问题。在这两种情况下,当浏览器请求路由时,客户端应用程序不运行,因此浏览器向服务器请求路由URL。但是,默认情况下不设置处理说/albums路线,所以你会得到一个错误。
如果您在ASP.NET Core应用程序中没有对HTML5路由设置进行任何特殊处理,您将在应用程序中打开错误页面,或者从Kestrel中选择此默认显示:
图1 - 未处理的客户端路由产生服务器错误
修复服务器上的客户端路由
那么你如何解决这个问题呢?
客户端SPA应用程序通常有一个或几个启动应用程序的静态页面。对于一个典型的Angular应用程序,该页面是index.html启动应用程序并启动客户端路由。大多数框架都足够聪明,可以在启动时检查当前路由,并移至首次访问请求的路由。
如果客户端路由从书签,链接或完全刷新被触发到服务器,则需要提供index.html并保持原始URL不变。
然后,客户端应用程序将自行引导,并且内部路由启动,以希望将您甩回书签/刷新位置。
从服务器提供Index.html
为了这个工作,你需要确保服务器只提供服务器负责的内容。
有几种方法可以做到这一点:
主机服务器URL重写
处理ASP.NET Core应用程序中的客户端路由
主机Web服务器上的URL重写
如果您在主流Web服务器上运行ASP.NET Core(或ASP.NET)应用程序,最简单且最有效的解决方案是重写客户端URL并为index.html给定的URL 提供内容。
在IIS上,您可以使用IIS重写模块来执行此操作。我最近在一篇博文中更详细地介绍了这一点:
ASP.NET核心应用程序的IIS重写规则
但是这里是相关的IIS重写规则:
<rewrite> <rules> <!-- Make sure you have a <base href="/" /> tag to fix the root path or all relative links will break on rewrite --><rule name="AngularJS-Html5-Routes" 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 urlrewriteWeb平台安装程序
如果你在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保持不变。这确保了当用户请求http://localhost: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服务,那么这可能是一个简单的方法来实现这个功能,包括潜在的支持服务器预渲染。
概要
HTML5路由为客户端应用程序提供了干净的URL,但它的价格必须有服务器支持才能使其工作。使用主机Web服务器中的重写规则或直接在Kestrel的中间件管道或自定义路由处理程序中进行设置并不困难,但是您必须确保将此功能显式添加到您创建的每个ASP.NET应用程序中。
尽管旧的Hash Bang路线看起来不那么干净,但它们工作正常,不需要任何服务器端支持。对于需要支持古代浏览器的非公众应用程序或应用程序,在没有服务器支持的情况下,散列邦线路仍然是提供路由的可行方式。
最后,如果您正在使用完整的Web服务器,UrlRewriting是处理非ASP.NET内核后端直接处理的非API内容的最干净和最有效的方式。
选择是好的,你有几个选择提供方便,干净的网址或简单的只是把它放在功能。你的选择...
处理ASP.NET Core中的HTML5客户端路由回退的更多相关文章
- ASP.NET Core中使用默认MVC路由
ASP.NET Core里Route这块的改动不大,只是一些用法上有了调整,提供了一些更加简洁的语法. 而对于自定义路由的支持当然也是没有问题的,这个功能应该是从MVC1.0版本就已经有这个功能. 先 ...
- ASP.NET Core中自定义路由约束
路由约束 ASP.NET Core中,通过定义路由模板,可以在Url上传递变量,同时可以针对变量提供默认值.可选和约束. 约束的使用方法是在属性路由上添加指定的约束名,用法如下: // 单个使用 [R ...
- ASP.NET Core中Middleware的使用
https://www.cnblogs.com/shenba/p/6361311.html ASP.NET 5中Middleware的基本用法 在ASP.NET 5里面引入了OWIN的概念,大致意 ...
- ASP.NET Core中使用自定义路由
上一篇文章<ASP.NET Core中使用默认MVC路由>提到了如何使用默认的MVC路由配置,通过这个配置,我们就可以把请求路由到Controller和Action,通常情况下我们使用默认 ...
- C#调用接口注意要点 socket,模拟服务器、客户端通信 在ASP.NET Core中构建路由的5种方法
C#调用接口注意要点 在用C#调用接口的时候,遇到需要通过调用登录接口才能调用其他的接口,因为在其他的接口需要在登录的状态下保存Cookie值才能有权限调用, 所以首先需要通过调用登录接口来保存c ...
- asp.net core 中配合响应 html5 的音视频播放流,以及文件下载
一.asp.net core 中配合响应 html5 的音视频播放流,以及文件下载 问题描述: 目前测试了在 Windows(谷歌浏览器).Android(系统浏览器.QQ.微信).iOS 三个系统不 ...
- ASP.NET Core 中的那些认证中间件及一些重要知识点
前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...
- ASP.NET Core 中文文档 第二章 指南(4.6)Controller 方法与视图
原文:Controller methods and views 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘) .张仁建(第二年.夏) .许登洋(Seay) .姚阿勇 ...
- ASP.NET Core 中文文档 第三章 原理(3)静态文件处理
原文:Working with Static Files 作者:Rick Anderson 翻译:刘怡(AlexLEWIS) 校对:谢炀(kiler398).许登洋(Seay).孟帅洋(书缘) 静态文 ...
随机推荐
- Linux下安装jdk8的详细步骤
一.登录Linux,切换到root用户 sudo su 二.在usr目录下建立java安装目录 cd /usr mkdir java 三.下载jdk 登录网址:http://www.oracle.co ...
- jS判断浏览器终端
在做移动端项目的时候,常常会遇到需要判断页面浏览终端的需求.要想判断是什么浏览器终端,先打印 navigator.userAgent 出来.所以收集了几种比较常用的方法: if(/(iPhone|iP ...
- Linq常见操作示例
static void DeferredQuery() { var names = new List<string> { "Nino", "Alberto&q ...
- jquery系列教程2-style样式操作全解
全栈工程师开发手册 (作者:栾鹏) 快捷链接: jquery系列教程1-选择器全解 jquery系列教程2-style样式操作全解 jquery系列教程3-DOM操作全解 jquery系列教程4-事件 ...
- 多个code.csdn.net账号切换
code.csdn.net是国内开源库 使用git需要在项目添加密钥 而如果有多个账户,一个是私人,一个是公司,那么这时怎么做? 密钥存在~/.ssh默认是id_rsa 那么一个比较笨的办法是做一个k ...
- win10 uwp json
本文讲的是关于在uwp使用json的简单使用,json应用很多,因为我只是写简单使用,说的东西可能不对或者不符合每个人的预期.如果觉得我有讲的不对的,就多多包含,或者直接关掉这篇文章,但是请勿生气或者 ...
- ST40 自制 JTAG 适配器
// 文章首发于 https://zhuanlan.zhihu.com/p/28762429 // 但是不知道为什么搜索引擎还没有收录,便在博客再次发布. 0. 引言 意法半导体生产的 SH4 架构的 ...
- 系统装机硬盘格式 >> GPT或者UEFI
预装Win8系统的电脑,硬盘都是采用这种分区格式,因为出厂安装时,是以Uefi方式启动安装的. 简单的办法,仍安装Win8系统:或者是转换磁盘分区格式为MBR,不用任何软件就可实现,需要重建分区表,会 ...
- Android基础知识02—安卓日志工具LogCat的五种方法
--------Android 02-------- >>> Android的日志工具LogCat 五个方法,记录信息的级别不一样,从低到高为: 1.Log.v()-日志 ...
- 在项目中集成jetty server
为什么使用jetty 使用 tomcat 开发效率并不是太高,并且在eclipse有时两秒做更新,有时候又得手动去部署显得非常麻烦.折算我们可以使用 jetty server 由于 eclipse开发 ...