处理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 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保持不变。这确保了当用户请求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内容的最干净和最有效的方式。

选择是好的,你有几个选择提供方便,干净的网址或简单的只是把它放在功能

原文地址:http://www.cnblogs.com/tianfengcc/p/7851974.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322876.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

TFS在项目中DevOps落地进程(下)

紧接上篇 TFS在项目中Devops落地进程&#xff08;上&#xff09; 再接着说TFS相关之前先插入一个番外篇&#xff0c;虽然跟TFS关系不大但跟DevOps关系很大&#xff0c;觉得有必要在此乱入一下。 番外篇--监控之Application Insights 我们之前并没有任何监控类产品&#xff08;我…

欢乐纪中某B组赛【2019.1.28】

前言 心态爆炸 成绩 RankRankRank是有算别人的 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCCDDD3332017myself2017myself2017myself1901901901001001005050500004040401313132017zyc2017zyc2017zyc1701701707070706060600004040401313132017hzb2017hzb2017hzb1701…

这应该是目前最快速有效的ASP.NET Core学习方式(视频)

ASP.NET Core都2.0了&#xff0c;它的普及还是不太好。作为一个.NET的老司机&#xff0c;我觉得.NET Core给我带来了很多的乐趣。Linux&#xff0c; Docker&#xff0c; CloudNative&#xff0c;MicroService&#xff0c;DevOps这些都能跟它很完美的结合&#xff0c;再加ASP.NE…

大叔公开课~微服务与持久集成

闲话多说 免费报名&#xff1a;http://www.genshuixue.com/teacher/classCourseDetail/171117794648么可以通过阅读原文报名 .Net Core来了&#xff0c;带给我们的是什么&#xff1f;跨平台&#xff0c;无疑是最大的亮点&#xff01; Docker横空出世&#xff0c;让开发者和运维…

语音服务——腾讯云

腾讯语音服务文档 一、开通语音消息服务流程 &#xff08;1&#xff09;注册并认证 如果您还没有腾讯云账号&#xff0c;您需要 注册腾讯云 账号&#xff0c;并完成 企业实名认证。如果您已有企业认证的腾讯云账号&#xff0c;请直接进行下一步操作。 申请开通语音消息服务 …

Visual Studio交叉编译器提供对ARM的支持

只要ARM平台能够运行Windows&#xff0c;Visual Studio就有能力拓展ARM平台。在Visual Studio 2017 15.5预览版2中&#xff0c;该IDE通过使用GCC编译器&#xff0c;增加了对基于ARM的计算机和物联网&#xff08;IoT&#xff09;设备的支持力度&#xff0c;从而扩展了对ARM平台的…

我心中的ASP.NET Core 新核心对象WebHost(二)

这是ASP.NET Core新核心对象系列的第二篇&#xff0c;上一篇 WebHost准备阶段 我们讲到了WebHostBuilder的初始化及配置。我们给WebHostBuilder进行以下配置 UseKestrel 设置Kestrel为HttpServer ConfigureAppConfiguration 设置了配置文件 ConfigureLogging 配置了日志处理器…

Hadoop生态Flume(三)拦截器(Interceptor)介绍与使用(1)

转载自 Flume中的拦截器&#xff08;Interceptor&#xff09;介绍与使用&#xff08;一&#xff09; Flume中的拦截器&#xff08;interceptor&#xff09; 用户Source读取events发送到Sink的时候&#xff0c;在events header中加入一些有用的信息&#xff0c;或者对events的…

SOA对微服务的残余影响

近日&#xff0c;Tareq Abedrabbo在伦敦2017 Con微服务大会上说&#xff0c;SOA对微服务架构设计的残余影响仍然存在&#xff0c;包括技术选型和组织方面的问题。最直接的一个例子就是大多数企业仍然区分对待架构师和开发人员&#xff0c;架构师负责出规范&#xff0c;开发人员…

Hadoop生态Flume(四)拦截器(Interceptor)介绍与使用(2)

转载自 Flume中的拦截器&#xff08;Interceptor&#xff09;介绍与使用&#xff08;二&#xff09; lume中的拦截器&#xff08;interceptor&#xff09;&#xff0c;用户Source读取events发送到Sink的时候&#xff0c;在events header中加入一些有用的信息&#xff0c;或者对…

协作更进一步:微软隆重介绍Visual Studio动态分享功能

微软刚刚在 Visual Studio Code 网站上宣布了“动态分享”&#xff08;Live Share&#xff09;功能&#xff0c;开发者们可以在 VS 2017 或 VS Code 中体验全新的实施协作。微软表示&#xff0c;Live Share 可让团队在相同的代码库上启用快速协作&#xff0c;而无需同步代码或配…

python打包exe文件

首先安装pyinstaller pip3 install pyinstaller接着导报指定文件 pyinstaller.exe -F 文件路径文件名 举例 pyinstaller.exe -F C:\Users\Tecna1205\Desktop\工作目录\Python工作目录\测试\3.3\test\tk.py 如果有图形界面&#xff0c;不想打开命令行&#xff0c;可在打包命令…

使用MS Test做单元测试

声明&#xff1a;本篇博客翻译自&#xff1a;http://www.c-sharpcorner.com/article/unit-testing-with-ms-tests-in-c-sharp/ 写在翻译之前&#xff1a; 依然清晰的记得刚工作的第一个项目中&#xff0c;在完成一个功能模块开发后&#xff0c;师傅让我把代码做一下单元测试。当…

Vue组件传参

父组件向子组件传参 数据&#xff1a; 父组件 <test :message"msg"></test>msg: Hello uniApp子组件&#xff08;test.vue&#xff09; <text>{{message}}</text>props:["message"]子组件向父组件传参 子组件&#xff1a; &…

如果不懂Service mesh,就不要谈微服务了

提到微服务&#xff0c;spring cloud等经典框架被使用的最为广泛&#xff0c;但是在2016年才被提起的Service Mesh&#xff0c;已经被Paypal、Lyft、Ticketmaster和Credit Karma等等一些大流量平台所使用&#xff0c;在生产应用中添加了Service mesh。今年随着Linkerd传入国内&…

使用AspectCore动态代理

前言 最近越来越多的同学关注到AspectCore&#xff0c;并且提出不少中肯的建议&#xff0c;其中最多的提议是希望能够看到更多的关于AspectCore使用方式的文章和Demo。那么在这篇文章里&#xff0c;我们就来聊聊AspectCore核心之一的动态代理。 动态代理 在.NET平台中&#xff…

已经安装完成mysql后wamp怎么配置

如果之前安装过mysql&#xff0c;然后想要安装wamp&#xff0c;那么怎么配置呢 先安装好wamp&#xff0c;然后在以下目录中修改my.ini 将密码改为自己的mysql密码即可 这时你发现启动wamp还是黄的 不要慌&#xff0c;因为你已经安装过了wamp&#xff0c;所以wamp自己的mys…

通过 Visual Studio 的“代码度量值”来改进代码质量

1 软件度量值指标 1.1 可维护性指数 表示源代码的可维护性&#xff0c;数值越高可维护性越好。该值介于0到100之间。绿色评级在20到100之间&#xff0c;表明该代码具有高度的可维护性&#xff1b;黄色评级在10到19之间&#xff0c;表示该代码适度可维护&#xff1b;红色评级在0…

php如何接收前端返回的各种类型的数据

之前学习node后端的时候&#xff0c;因为始终无法在网上找到接收json数据的函数&#xff0c;所以后来就放弃了。最近又心血来潮&#xff0c;想学习php. 这次已经有了之前学习php的基础&#xff0c;所以直接入手thinkphp5.0 这次php的学习&#xff0c;主要是为了解决之前遗留的问…

ASP.NET Core 认证与授权[5]:初识授权

经过前面几章的姗姗学步&#xff0c;我们了解了在 ASP.NET Core 中是如何认证的&#xff0c;终于来到了授权阶段。在认证阶段我们通过用户令牌获取到用户的Claims&#xff0c;而授权便是对这些的Claims的验证&#xff0c;如&#xff1a;是否拥有Admin的角色&#xff0c;姓名是否…