.NET探索模型路由約定實現偽靜態

概述

IPageRouteModelConvention介面用於自定義PageRouteModel,這個對象在Microsoft.AspNetCore.Mvc.ApplicationModels命名空間中,
代表著Razor Page路由設置,換句話說我們可以通過實現該介面覆蓋默認的實現。
該介面需要實現一個成員void Apply(PageRouteModel model)。通過這個方法,我們可以訪問有關當前路由設置的元數據,並根據需要對其內容進行修改。
下面示例,將解決提供一個偽靜態的解決方案,因此我們可以通過index.html about.html….去訪問我們的頁面,也就是說我們可以從Index-Index.html的支援

    public class HtmlExtensionPageRouteModelConvention : IPageRouteModelConvention
    {
        private readonly ILogger _logger;
        public HtmlExtensionPageRouteModelConvention(ILogger logger)
        {
            _logger = logger;
        }
        public void Apply(PageRouteModel model)
        {
            var log = new StringBuilder();
            log.AppendLine("====================================================");
            log.AppendLine($"Count:{model.Selectors.Count} ViewEnginePath:{model.ViewEnginePath} RelativePath:{model.RelativePath}");

            var selectorsCount = model.Selectors.Count;
            for (var i = 0; i < selectorsCount; ++i)
            {
                var attributeRouteModel = model.Selectors[i].AttributeRouteModel;
                //添加之前
                log.AppendLine($"Template:{attributeRouteModel.Template}");

                if (string.IsNullOrEmpty(attributeRouteModel.Template))
                {
                    continue;
                }
                //該規則是否禁止鏈接的生成,默認為生成(支援TagHelpers) asp-page="/Index" 
                attributeRouteModel.SuppressLinkGeneration = true;
                //添加新的路由模板
                model.Selectors.Add(new SelectorModel
                {
                    AttributeRouteModel = new AttributeRouteModel
                    {
                        //Order 路由匹配順序
                        //SuppressLinkGeneration = true,
                        Template = $"{attributeRouteModel.Template}.html",
                    }
                });
            }
            //添加完後
            log.AppendLine($"Count:{model.Selectors.Count} ");
            foreach (var item in model.Selectors)
            {
                log.AppendLine($"Template:{item.AttributeRouteModel.Template} ");
            }
            _logger.LogInformation(log.ToString());
        }
    }

在啟動時,為所有可導航的Razor頁面構建PageRouteModel。Apply方法接收這個對象,並訪問於PageRouteModel相關聯的SelectorModel對象集合。它們包含頁面路由和任何約束的資訊,在每個頁面的selector集合中通常有一個SelectorModel,但可以有任意數量,默認頁面為Index.cshtml通常有兩個選擇器,一個包含一個路由模板,由相對文件路徑和”Index”組成,另一個模板中有一個空字元串,文件名通常放在那裡(這使它成為文件夾的默認文件)。在這個例子中的Index.cshtml原始模板生成的(Index),將變成一個Index.html

我們需要將attributeRouteModel.SuppressLinkGeneration設置為true,禁止對鏈接的生成,默認值為false(支援TagHelpers如:asp-page=”/Index”),
如下圖所示滑鼠箭頭放到Home上面,在下面可以顯示出來為我們生成的路徑,這個路由則是根據我們設置的規則而生成出來的.

file

當我們在Selectors.Add方法內中的new AttributeRouteModel對象中將SuppressLinkGeneration設置為true,這樣的話我們是將路由規則設置禁止了,看下圖可以看出,
當我們把所有的規則都設置為禁止生成後,我們當滑鼠剪頭再次放到Home上面時已經不會為我們再生成新的鏈接了

file

添加約定

自定義約定要在Startup中的void ConfigureServices(IServiceCollection services)方法下中的 services.AddRazorPages()方法下追加RazorPagesOptions方法並添加約定的集合:

    public void ConfigureServices(IServiceCollection services)
     {
            ...
            services.AddRazorPages().AddRazorPagesOptions(options =>
            {
             //options.Conventions.AddPageRoute("/Index", "Index.html");
             options.Conventions.Add(new HtmlExtensionPageRouteModelConvention(_loggerFactory.CreateLogger<HtmlExtensionPageRouteModelConvention>()));
         });
      }

通過如上程式碼,我們便在.NET中實現了偽靜態,對URL路由匹配規則的附加操作.

//github.com/hueifeng/BlogSample/tree/master/src/PageRouteModelConventionURLRewrite