在本文中,我们将讨论asp.net core
中的新路由。我们将了解什么是接口(endpoints
)路由,它是如何工作的,它在哪里使用,以及如何创建自己的路由。
本文主题:
- 探索接口路由
- 创建自定义接口
- 创建更复杂的接口
名词定义:端点,即我们访问的接口或者叫api,有些地方叫endpoint或者叫接口,其实源头的称呼应该叫端点会更贴切一些。或者你也可以直接叫endpoint,但是先不管那么多,大概了解这个意思就可以了。
探索接口路由
要了解接口路由(end point),您需要了解什么是端点以及什么是路由。
端点是应用程序的一部分,当路由将传入的请求映射到它时,端点就会被执行。
客户端通常从服务器请求资源。大多数情况下,客户端是一个浏览器。资源由指向特定目标的url定义。除了网页,它也可以是一个移动应用程序,从web api请求特定json数据。
另一方面,执行的端点被映射到一个特定的路由,asp.net core开发人员已经熟悉这样一种路由模式:
app.userouting(); app.useauthorization(); app.useendpoints(endpoints => { endpoints.mapcontrollerroute(name: "default", pattern: "{controller=home}/{action=index}/{id?}"); });
如果路由或路由模式与传入请求的url匹配,则请求将映射到该端点。asp.net core
可以映射到以下端点:
- controllers (例如, mvc or web apis)
- razor pages
- signalr (and blazor server)
- grpc services
- health checks
大多数端点都有非常简单的路由模式。只有mvc和web api端点使用更复杂的模式。razor页面的路由定义基于实际页面的文件夹和文件结构。
在asp.net core 2.2中引入端点之前,路由只是运用在mvc和web api中。razor pages中的隐式路由是内置的,signalr没有路由一说。blazor和grpc在当时还不不知道在哪儿,健康检查最初是作为中间件组件实现的。
引入端点路由是为了将路由与实际端点分离,说得白话一点,就是让url地址和实际执行的action进行分离,这会让框架更加灵活,同时这意味着新的端点不需要实现自己的路由。
创建自定义接口
创建端点的最简单方法是使用lambda:
app.map("/map", async context => { await context.response.writeasync("ok"); });
这里将/map路由映射到一个简单的端点,该端点将单词“ok”写入响应流。
关于早期.net 6.0
版本的说明
在.net 6.0
之前,该映射只能在startup.cs文件中的useendpoints方法中,而使用.net 6.0
和新的minimal api
方法,可以在program.cs
文件中完成映射。
另外,我们需要将microsoft.aspnetcore.http命名空间添加到using语句中。
还可以将特定的http方法(如get、post、put和delete)映射到端点。以下代码显示了如何映射get和post方法:
app.mapget("/mapget", async context => { await context.response.writeasync("map get"); }); app.mappost("/mappost", async context => { await context.response.writeasync("map post"); });
我们还可以将两个或多个http方法映射到一个端点:
app.mapmethods("/mapmethods", new[] { "delete", "put" }, async context => { await context.response.writeasync("map methods"); });
这些端点映射很像我们在第8篇定制,这些管道中间件会返回结果,例如基于html的视图、json结构化数据或类似的内容。但是,端点路由是一种更灵活的输出方式,它应该会在asp.net core 3.0以后的所有版本中进行使用。
在第8篇中,我们看到我们可以像这样的分支管道:
app.map("/map", mapped => { // …… });
以上这种方式也会创建一个路由,但只会侦听以/map
开头的url。如果您希望有一个处理/map/{id:int?}
等模式的路由引擎,来匹配/map/456
而不是/map/abc
,那么您应该使用前面所述的新的路由。
而那些基于lambda的端点映射,对于简单的场景非常有用。然而,由于它们是在program.cs
中定义的,如果您想使用这种方式来实现更复杂的场景,代码维护性将变得很差。
因此,我们应该尝试找到一种更结构化的方法来创建自定义端点。
创建更复杂的接口
接下来,我们将创建一个健康检查接口例子,有点类似于您在kubernetes集群中运行应用程序时可能需要的接口,用来检测系统的健康状态:
我们从开发者的角度定义api接口,我们首先添加一个mapmyhealthchecks方法,作为iendpointroutebuilder对象上的一个扩展方法,它没有实现:
app.mapmyhealthchecks("/myhealth"); app.mapcontrollerroute(name: "default",pattern:"{controller=home}/{action=index}/{id?}");
为了避免混淆,我们这儿采取和之前类似的方式添加新接口,后面我们进一步来实现一下。
我们创建一个名为mapmyhealthchecksextensions
的静态类,并在mapmyhealthcheck
中放置一个扩展方法,该对象扩展iendpointroutebuilder
接口并返回iendpointconventionbuilder
对象:
namespace routingsample; public static class mapmyhealthchecksextensions { public static iendpointconventionbuilder mapmyhealthchecks (this iendpointroutebuilder endpoints, string pattern = "/myhealth") { // ... } }
以上只是骨架,实际的接口将被实现为一个终止的中间件,也就是说,它不调用下一个的中间件组件,并创建响应流的输出:
namespace routingsample; public class myhealthchecksmiddleware { private readonly ilogger _logger; public myhealthchecksmiddleware (requestdelegate next, ilogger logger) { _logger = logger; } public async task invoke(httpcontext context) { // add some checks here... context.response.statuscode = 200; context.response.contenttype = "text/plain"; await context.response.writeasync("ok"); } }
实际工作是在invoke
方法中完成的。目前,只演示200状态码和ok状态响应,我们可以在这里随意扩展该方法,例如检查数据库或相关服务的可用性。
接下来我们使用这个终止中间件,我们回到mapmyhealthchecks
方法的框架。我们现在创建一个自己的管道,并将其映射到给定的pipeline:
var pipeline = endpoints.createapplicationbuilder().usemiddleware().build(); return endpoints.map(pattern, pipeline).withdisplayname("my custom health checks");
这种方法允许我们为这个新的管道添加更多的中间件。withdisplayname
扩展方法将配置的显示名称设置为接口,接下来按f5键启动程序,并在浏览器中调用https://localhost:7111/myhealth。我们将看到:
请注意,端口号可能会有所不同。我们还可以将已经存在的终止中间件组件转换为路由接口,以配置更加灵活的路由。
总结
asp.net core
支持请求处理并向请求提供信息的多种方法。接口路由是一种基于url和请求的方法提供资源。
在本文,我们学习了如何使用终止中间件组件作为接口,并用将该接口映射到新的路由引擎,从而让我们的路由变得更加强大和灵活。
每个web应用程序都需要了解系统用户,以允许或限制对特定数据的访问。在下一章中,我们将展示如何配置身份验证和识别用户。