ASP .Net Core路由(Route) - 紙殼CMS的關鍵


關於紙殼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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM