dotnet core 开发体验之Routing
来源:互联网 发布:深圳启讯网络骗局 编辑:程序博客网 时间:2024/06/05 05:01
开始
回顾上一篇文章:dotnet core开发体验之开始MVC 里面体验了一把mvc,然后我们知道了aspnet mvc是靠Routing来驱动起来的,所以感觉需要研究一下Routing是什么鬼。
Routing简单使用体验
首先我们用命令yo aspnet
创建一个新的空web项目。(Yeoman的使用自己研究,参考:https://docs.asp.net/en/latest/client-side/yeoman.html?#building-projects-with-yeoman)
创建完项目后,在project.json里面添加Routing依赖。
"dependencies": { ... "Microsoft.AspNetCore.Routing": "1.0.0-*"},
添加完依赖后,修改Startup里面的Configure,和ConfigureServices里面添加Routing的使用依赖
修改前:
public void Configure(IApplicationBuilder app){ app.Run(async (context) => { await context.Response.WriteAsync("Hello World!"); });}
修改后:
public void ConfigureServices(IServiceCollection services){ services.AddRouting();}
public void Configure(IApplicationBuilder app){
var endpoint = new RouteHandler((c) => c.Response.WriteAsync("Hello, I am Routing!")); app.UseRouter(endpoint);}
dotnet run 然后浏览器访问http://localhost:5000/ 显示为Hello, I am Routing! 接下来我们在http://localhost:5000/ 后面加入一些其他的东西来访问,发现其实还是一样打印Hello, I am Routing! 这让我们感觉好像并没有什么卵用的样子。不着急我们先来看看Routing是怎么运行起来的。在开始这话题之前需要先了解到什么是中间件,参考:https://docs.asp.net/en/latest/fundamentals/middleware.html
Routing的最基本运行原理
Routing的驱动入口就是基于middleware的。可以先看看 app.UseRouter(endpoint)
的内部实现,参考一个扩展方法类RoutingBuilderExtensions,可以看到最后有一句代码return builder.UseMiddleware<RouterMiddleware>(router)
。这里可以很明显看到,入口在RouterMiddleware的Invoke方法。
public async Task Invoke(HttpContext httpContext) {
var context = new RouteContext(httpContext); context.RouteData.Routers.Add(_router);
await _router.RouteAsync(context);
if (context.Handler == null) { _logger.RequestDidNotMatchRoutes();
await _next.Invoke(httpContext); }
else { httpContext.Features[typeof(IRoutingFeature)] = new RoutingFeature() { RouteData = context.RouteData, }; await context.Handler(context.HttpContext); } }
这个入口的实现是这样的:
Invoke入口 ===>>> 实例化一个 RouteContext ===>>> 把我们传进来的 IRouter 存到 RouteContext里面的 RouteData===>>> 再执行IRouter的RouteAsync方法把RouteContext对象传进去提供给具体实现使用。===>>> 如果context.Handler没有东西,就执行下一个RequestDelegate,如果有的话就把RouteData保存起来然后执行这个RequestDelegate。
看到了这里我们已经可以明白下面这个代码运行起来的原理。
public void Configure(IApplicationBuilder app){
var endpoint = new RouteHandler((c) => c.Response.WriteAsync("Hello, I am Routing!")); app.UseRouter(endpoint);}
可能还会有人不明白RouteHandler是个什么鬼,既然我们知道了代码的实现运行原理,那么肯定可以猜到RouteHandler是有实现接口IRouter的。我们可以看RouteHandler代码
public Task RouteAsync(RouteContext context) { context.Handler = _requestDelegate;
return TaskCache.CompletedTask; }
这里可以看到把我们的(c) => c.Response.WriteAsync("Hello, I am Routing!")
赋值给context.Handler,然后由RouterMiddleware来执行我们这个事件方法。于是我们就可以在浏览器上面看到输出 Hello, I am Routing!这么一句话了。
Routing的一些使用
文章到现在,我们虽然知道了Routing运行起来的一个大概原理,但是我们一直打印出相同内容,确实也没有什么卵用呀。我们要改一下让打印内容能有点改变。这个时候可以使用到Routing提供的Route类来使用。代码修改如下:
public void Configure(IApplicationBuilder app) {
var endpoint = new RouteHandler((c) => c.Response.WriteAsync($"Hello, I am Routing! your item is {c.GetRouteValue("item")}"));
var resolver = app.ApplicationServices.GetRequiredService<IInlineConstraintResolver>();
var runRoute = new Route(endpoint,"{item}",resolver); app.UseRouter(runRoute); }
修改完代码后,我们再次编译运行,然后输入http://localhost:5000/ 我们发现一片空白,然后再输入http://localhost:5000/abc 发现打印出来的是Hello, I am Routing! your item is abc。然后再输入其他的 http://localhost:5000/abc/cc 发现也是一片空白。这是因为我们给路由添加的匹配是主机地址/+{item}
那其他的路径都是匹配不到,那么肯定就是不会显示任何东西啦。假设我们要给一个默认值,那么可以改成这样
var runRoute = new Route(endpoint,"{item=home}",resolver);
OK,这个时候我们再输入http://localhost:5000/ 看到的就是Hello, I am Routing! your item is home。
匹配原理相对比较复杂点,想要了解的话可以参考 RouteBase的源码,然后看相关的类,看看我们设置的模板是如何解析的,然后如何和url进行匹配的。如果要要来解释完整个过程的话,这个文章肯定是不够的,所以各位可以自己了解一下。
假如要配置多个路由支持的话,可以使用RouteCollection
public void Configure(IApplicationBuilder app) {
var endpoint = new RouteHandler((c) => c.Response.WriteAsync($"Hello, I am Routing! your item is {c.GetRouteValue("item")}"));
var resolver = app.ApplicationServices.GetRequiredService<IInlineConstraintResolver>();
var runRoute = new Route(endpoint,"{item=home}",resolver);
var otherRoute = new Route(endpoint,"other/{item=other_home}",resolver);
var routeCollection = new RouteCollection(); routeCollection.Add(runRoute); routeCollection.Add(otherRoute); app.UseRouter(routeCollection); }
修改成上面的代码后就支持两个路由,假如输入的url是 http://localhost:5000/other 那么就是使用runRoute,如果输入的是http://localhost:5000/other/myother 那么使用的就是otherRoute。
这样书写暴露了很多细节东西,我们可以用 Routing提供的RouteBuilder类来编写相同的东西。代码修改一下如下:
public void Configure(IApplicationBuilder app) {
var endpoint = new RouteHandler((c) => c.Response.WriteAsync($"Hello, I am Routing! your item is {c.GetRouteValue("item")}")); var routeBuilder = new RouteBuilder(app) { DefaultHandler = endpoint, }; routeBuilder.MapRoute("default","{item=home}"); routeBuilder.MapRoute("other","other/{item=other_home}"); app.UseRouter(routeBuilder.Build()); }
如果有一些特殊的的路由配置,我们也可以使用routeBuilder.Routes.Add(route);
这代码来添加。至于能配置的模板都有些什么,可以看 Routing 的 Template 的测试类:https://github.com/aspnet/Routing/tree/dev/test/Microsoft.AspNetCore.Routing.Tests/Template 看完基本就知道都有些什么样的模板格式可以使用了。
实现自己的 RouteHandler
到现在,我们已经知道了Routing大概是怎么运行起来,知道了如何简单的使用。那么接下来可以来创建一个自己的RouteHandler,来加深一下对Routing的使用体验。
创建一个类MyRouteHandler,实现接口IRoute:
public class MyRouteHandler : IRouter{ public VirtualPathData GetVirtualPath(VirtualPathContext context) { return null; } public Task RouteAsync(RouteContext context) { context.Handler = (c) => { var printStr = $"controller:{c.GetRouteValue("controller")}," + $"action:{c.GetRouteValue("action")},id:{c.GetRouteValue("id")}"; return c.Response.WriteAsync(printStr); }; return TaskCache.CompletedTask; }}
然后我们的路由配置改成这样:
public void Configure(IApplicationBuilder app) { var endpoint = new MyRouteHandler(); var routeBuilder = new RouteBuilder(app) { DefaultHandler = endpoint, }; routeBuilder.MapRoute("default","{controller=Home}/{action=Index}/{id?}"); app.UseRouter(routeBuilder.Build()); }
然后打开浏览器http://localhost:5000/ 打印出来的内容是 controller:Home,action:Index,id:
。这样是不是很像我们去调用mvc的控制器和控制器的行为呢?Routing的体验文章到这来就结束了,谢谢观看。
相关文章:
ASP.NET Core 1.0 入门——了解一个空项目
ASP.NET Core 1.0 部署 HTTPS (.NET Framework 4.5.1)
.NET Core 1.0、ASP.NET Core 1.0和EF Core 1.0简介
云服务器下ASP.NET Core 1.0环境搭建(包含mono与coreclr)
使用VS Code开发ASP.NET Core 应用程序
dotnet run是如何启动asp.net core站点的
ASP.NET Core提供模块化Middleware组件
“dotnet restore"和"dotnet run"都做了些什么?
探秘 dotnet run 如何运行 .NET Core 应用程序
.NET Portability Analyzer 已开源
ASP.NET Core的配置(1):读取配置信息
ASP.NET Core的配置(2):配置模型详解
.NET Core 1.0 RC2 历险之旅
使用VS Code开发 调试.NET Core 应用程序
让我们Core在一起:ASP.NET Core & .NET Core
.NET Core VS Code 环境配置
官方博客明确了 .NET Core RC2/RTM 时间表
.NET Core全新的配置管理[共9篇]
利用记事本创建一个ASP.NET Core RC2 MVC应用
微软.NET 正式劈腿成功,横跨所有平台
.NET Core 1.0 CentOS7 尝试
解读发布:.NET Core RC2 and .NET Core SDK Preview 1
[.NET Core].NET Core R2安装及示例教程
ASP.NET Core 开发-中间件(Middleware)
结合Jexus + Kestrel 部署 asp.net core 生产环境
通过Jexus 部署 dotnetcore版本MusicStore 示例程序
ASP.NET Core 中文文档 第一章 入门
用 Visual Studio Code 在 macOS 上创建首个 ASP.NET Core 应用程序
用 Visual Studio 和 ASP.NET Core MVC 创建首个 Web API
用 Visual Studio 发布一个 Azure 云 Web 应用程序
ASP.NET Core MVC 与 Visual Studio 入门
第二章指南(4.2)添加 Controller
DotNet Core 介绍
asp.net core 中间件详解及项目实战
教你实践ASP.NET Core Authorization(免看文档教程)
asp.net core 使用 Redis 和 Protobuf 进行 Session 缓存
asp.net core 中间件详解及项目实战
第二章 指南(4.3)添加 View
原文地址:http://www.cnblogs.com/caipeiyu/p/5597775.html
.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
- dotnet core 开发体验之Routing
- dotnet core开发体验之开始MVC
- 使用 dotnet watch 开发 ASP.NET Core 应用程序
- 使用 dotnet watch 开发 ASP.NET Core 应用程序
- dotnet core 命令详解
- DotNet Core全新认识
- dotnet core 2.0 安装
- dotnet core 命令详解
- DotNet Core 介绍
- .net core 多平台开发体验
- dotnet core publish and run
- .NET Core dotnet 命令大全
- dotnet core 做微信公众号开发时遇到的问题1
- 使用 dotnet core 和 Azure PaaS服务进行devOps开发(Web API 实例)
- 通过几个helloworld感受.net core开发体验
- .NET Core多平台开发体验[2]- Mac OS X
- .NET Core多平台开发体验[2]- Mac OS X
- .NET Core多平台开发体验[4]- Docker
- 使用ContentNegotiatingViewResolver将model中的数据渲染到MappingJackson2JsonView(model转成json)
- 聊聊ASP.NET Core默认提供的这个跨平台的服务器——KestrelServer
- 数据结构——双向链表
- Visual Studio Code五月版本更新
- dotnet core开发体验之开始MVC
- dotnet core 开发体验之Routing
- asp.net core 中间件详解及项目实战
- 第二章 指南(4.3)添加 View
- hdu 1542 Atlantis
- asp.net core 使用 Redis 和 Protobuf 进行 Session 缓存
- 滚动条事件
- 微软觊觎LinkedIn算法
- JFlow CCFlow工作流引擎北京培训邀请函
- 教你实践ASP.NET Core Authorization(免看文档教程)