• ASP .Net Core路由(Route)


    关于纸壳CMS

    纸壳CMS是一个开源免费的,可视化设计,在线编辑的内容管理系统。基于ASP .Net Core开发,插件式设计:

    GitHubhttps://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的路由机制,我相信你应该会有所收获,:-),欢迎有兴趣的大神们加入进来!

    https://github.com/SeriaWei/ZKEACMS.Core

  • 相关阅读:
    违反了引用完整性约束。Dependent Role 具有多个具有不同值的主体。S级乌龙,自己制造的笑话
    用MVC5+EF6+WebApi 做一个小功能(二) 项目需求整理
    用MVC5+EF6+WebApi 做一个小功能(四) 项目分层功能以及文件夹命名
    用MVC5+EF6+WebApi 做一个小功能(三) 项目搭建
    ASP.NET WebApi总结之自定义权限验证
    用MVC5+EF6+WebApi 做一个小功能(一)开场挖坑,在线答题系统
    Javascript 535种方式!!!实现页面重载
    MVC页面移除HTTP Header中服务器信息
    为什么JavaScript要有null?(翻译)
    可编程渲染管线与着色器语言
  • 原文地址:https://www.cnblogs.com/seriawei/p/9732233.html
Copyright © 2020-2023  润新知