ASP .Net Core路由(Route) - 纸壳CMS的关键
关于纸壳cms
纸壳cms是一个开源免费的,可视化设计,在线编辑的内容管理系统。基于asp .net core开发,插件式设计:
github:https://github.com/seriawei/zkeacms.core
路由
路由是asp .net里面至关重要的一个组成部分,路由的功能简单的说就是把用户请求的地址“转移”到对应的controller,action。而路由,也是纸壳cms可以自定义页面的关键。
在纸壳cms中,给路由定义了优先级,所以在处理用户请求地址的时候,通过路由的优先级来决定访问的流程走向,如果找到匹配的路由,则优先走该路由对应的 controller -> action -> view,如果没有匹配的路由,则走路由优先权最低的“全捕捉”路由来处理用户的请求,最后返回响应。
优先级最低的“全捕捉”路由是用来处理用户创建的页面。"{*path}",所有这些请求,都会到 pagecontroller -> main 进行处理。这样就可以把原来真实的页面,变为虚拟的,并由用户来创建,存到数据库中。请求流程,大致如下图所示:
全捕捉路由和通用后台路由的定义,priority值越大,优先级越高:
new routedescriptor { routename = "pageroute", template = "{*path}", defaults = new { controller = "page", action = "main" }, constraints = new { path = new pagerouteconstraint() }, priority = -1 }, new routedescriptor { routename = "admin", template = "admin/{controller=dashboard}/{action=index}/{id?}", defaults=new { module = "admin" }, priority = 10 }
pagerouteconstraint
pagerouteconstraint,这里并不是用来约束路由的,而是在这里处理路由数据,要在这里构建routedata,所以看代码,始终是返回true。
namespace zkeacms { public class pagerouteconstraint : irouteconstraint { public bool match(httpcontext httpcontext, irouter route, string routekey, routevaluedictionary values, routedirection routedirection) { var value = values[routekey]; if (routekey == "path" && value != null) { string path = "/" + value.tostring(); var routedataproviders = httpcontext.requestservices.getservice<ienumerable<iroutedataprovider>>(); foreach (var item in routedataproviders.orderby(m => m.order)) { path = item.extractvirtualpath(path, values); } if (path.isnullorwhitespace()) { path = "/"; } values[routekey] = path; } return true; } } }
纸壳cms里面使用iroutedataprovider来自定义处理请求url和routedata。例如使用htmlroutedataprovider来实现伪静态:
namespace zkeacms.route { public class htmlroutedataprovider : iroutedataprovider { const string htmlext = ".html"; public int order { get { return 0; } } public string extractvirtualpath(string path, routevaluedictionary values) { if (path.endswith(htmlext, stringcomparison.ordinalignorecase)) { path = path.substring(0, path.lastindexof(htmlext)); } return path; } } }
使用paginationroutedataprovider来获取分页数据等等:
namespace zkeacms.route { public class paginationroutedataprovider : iroutedataprovider { public int order { get { return 1; } } public string extractvirtualpath(string path, routevaluedictionary values) { if (customregex.pageregex.ismatch(path)) { int page = -1; path = customregex.pageregex.replace(path, evaluator => { int.tryparse(evaluator.groups[1].value, out page); return string.empty; }); if (page >= 0 && !values.containskey(stringkeys.routevalue_page)) { values.add(stringkeys.routevalue_page, page); } } return path; } } }
插件里路由
每个插件都可以定义自己的路由,所以一定要处理它们的优先级关系。定义的方式很简单,在插件类(xxxplug.cs)里面,实现registroute方法就可以了。例如自定义表单插件里面的提交数据路由:
namespace zkeacms.formgenerator { public class formplug : pluginbase { public override ienumerable<routedescriptor> registroute() { yield return new routedescriptor { routename = "formdata", template = "formdatahandle/submit", defaults = new { controller = "formdata", action = "submit" }, priority = 11 }; } } }
最后
纸壳cms充分利用了路由来实现自定义页面的功能,而路由不再单纯的只有{controller}/{action}。看了纸壳cms的路由机制,我相信你应该会有所收获,:-),欢迎有兴趣的大神们加入进来!
上一篇: 昨天晚上