日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

自定义路由匹配和生成

發(fā)布時間:2023/12/4 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 自定义路由匹配和生成 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

前兩篇文章主要總結了CMS系統(tǒng)兩個技術點在ASP.NET Core中的應用:

  • 《ASP.NET Core 中的SEO優(yōu)化(1):中間件實現(xiàn)服務端靜態(tài)化緩存》

  • 《ASP.NET Core 中的SEO優(yōu)化(2):中間件中渲染Razor視圖》

而本篇文章,繼續(xù)介紹另一個技術點:自定義路由匹配和生成。

背景

在MVC5時代,默認的路由可能就是簡單的約定/{controller}/{action}/{id},第一節(jié)對應控制器(Controller)名,第二節(jié)對應操作(Action)名,第三節(jié)是參數(shù)名。
在WebApi和ASP.NET Core時代,有了Route特性來指定相應操作的路由指向,可以很靈活地配置RESTful Api。

但是,路由靈活性在注重SEO的CMS系統(tǒng)中有更苛刻的要求。例如:

  • 欄目的列表 ->/{父欄目名}/{子欄目名}-{頁碼}/

  • 文章詳情頁 ->/{欄目名}/{文章名}.html

  • 標簽頁 ->/{標簽名}

這些友好的url鏈接使用默認的路由約定是很難實現(xiàn)的,當然是可以配置路由規(guī)則去傳遞參數(shù):

  • app.UseMvc(routes =>

  • {

  • ? ?routes.MapRoute(

  • ? ? ? ?name: "article_list",

  • ? ? ? ?template: "{parentCategory}/{category}-{page}/",

  • ? ? ? ?defaults: new { controller = "Article", action = "Index" });

  • ? ?routes.MapRoute(

  • ? ? ? ?name: "article_detail",

  • ? ? ? ?template: "{category}/{article}.html",

  • ? ? ? ?defaults: new { controller = "Article", action = "Detail" });

  • ? ?routes.MapRoute(

  • ? ? ? ?name: "tags",

  • ? ? ? ?template: "{tag}/",

  • ? ? ? ?defaults: new { controller = "Article", action = "Tag" });

  • ? ?});

  • 但是,這樣配置很繁瑣,也不靈活,如果還要傳入更多規(guī)則,比如不向下匹配,就顯得捉襟見肘了。那有沒有更靈活的方案呢?當然有,就是本文接下來要介紹的IRouter接口。

    原理

    上一節(jié)最后介紹的一般路由配置方法,其實是MapRoute方法創(chuàng)建一個個IRouter的實例,添加到IRouteBuilder實例中,具體方法可以看看源碼。

    所以我們可以實現(xiàn)一個自定義的IRouter,就能不用默認的約定,去實現(xiàn)我們的苛刻需求。

    首先要看看IRouter這個接口的定義,源碼在aspnet/Routing/src/Microsoft.AspNetCore.Routing.Abstractions/IRouter.cs

  • namespace Microsoft.AspNetCore.Routing

  • {

  • ? ?public interface IRouter

  • ? ?{

  • ? ? ? ?Task RouteAsync(RouteContext context);

  • ? ? ? ?VirtualPathData GetVirtualPath(VirtualPathContext context);

  • ? ?}

  • }

  • 實現(xiàn)

    IRouter接口只有兩個方法,本文分別給出代碼示例來介紹。

    RouteAsync

    這個方法中實現(xiàn)路由匹配,從路由上下文中獲取所需要的數(shù)據(jù),存入RouteData字典中,再從控制器取出做相應的處理。

  • public async Task RouteAsync(RouteContext context)

  • {

  • ? ?var requestedUrl = context.HttpContext.Request.Path.Value.TrimStart('/').ToLower();

  • ? ?var split = requestedUrl.Split('/');

  • ? ?if (secoend != null && secoend.EndsWith(".html") && split.Length == 2)

  • ? ?{

  • ? ? ? ?var title = secoend.Replace(".html", "");

  • ? ? ? ?context.RouteData.Values["controller"] = "Article";

  • ? ? ? ?context.RouteData.Values["action"] = "Detail";

  • ? ? ? ?context.RouteData.Values["category"] = first;

  • ? ? ? ?context.RouteData.Values["title"] = title;

  • ? ?}

  • ? ?//...對請求路徑進行一系列的判斷

  • ? ?//最后注入`MvcRouteHandler`示例執(zhí)行`RouteAsync`方法,表示匹配成功

  • ? ?await context.HttpContext.RequestServices.GetService<MvcRouteHandler>().RouteAsync(context);

  • }

  • 這樣,當請求路由為/news/asp.net.html時,就會匹配到上面的規(guī)則,請求進入Article控制器中的Detail操作被處理,并且可以從控制器中的RouteData.Values["category"]?.ToString();方法拿到所需的數(shù)據(jù)。

    GetVirtualPath

    這個方法實現(xiàn)路由生成,可以從路由上下文中獲取RouteData字典中的數(shù)據(jù),進行虛擬路徑(區(qū)別與真實目錄)的生成。

  • public VirtualPathData GetVirtualPath(VirtualPathContext context)

  • {

  • ? ?var path = string.Empty;

  • ? ?var hasController = context.Values.TryGetValue("controller", out var controller);

  • ? ?var hasAction = context.Values.TryGetValue("action", out var action);

  • ? ?var hasCategory = context.Values.TryGetValue("category", out var category);

  • ? ?var hasTitle = context.Values.TryGetValue("title", out var title);

  • ? ?if (hasController && hasAction && hasCategory && hasTitle)

  • ? ?{

  • ? ? ? ?path = $"/{category/{title}.html";

  • ? ?}

  • ? ?return path != string.Empty ? new VirtualPathData(this, path) : null;

  • }

  • 這樣,當調用路徑生成方法@Url.Action("Detail","Article",new { title="asp.net", category="news" }),就會生成”/news/asp.net.html”這樣的路徑來。

    IRouter的設置生效

    自定義實現(xiàn)的IRouter如何設置到原有的MVC項目中呢?方法很簡單,上面已經(jīng)簡單說道了,其實app.UseMvc這個方法就有添加IRouter的方法:

  • app.UseMvc(routes =>

  • {

  • ? ?//添加 自定義路由匹配與url生成組件

  • ? ?routes.Routes.Add(new RouteProvider());

  • });

  • 這里RouteProvider是IRouter的實現(xiàn),這樣自定義的路由提供對象就生效啦!

    相關小技巧

  • SEO中會有一條鐵規(guī)則,就是不是有效鏈接的情況下只能返回404,比如,手動輸入了一個路徑,能匹配到文章詳情的操作(action),如果數(shù)據(jù)庫中查不出文章,本來應該不能匹配的,但是,如果在匹配的時候查詢數(shù)據(jù)庫確認是否存在的話,會加大系統(tǒng)的壓力,所以,可以放在操作(action)中查詢,查不到再返回NotFound,讓上一篇文章《ASP.NET Core 中的SEO優(yōu)化(2):中間件中渲染Razor視圖》中介紹的中間件一并處理輸出404頁面。

  • 站內鏈接如果使用帶域名的絕對路徑,能夠提高優(yōu)化效果,我們可以自己寫一個UrlHelper的擴展方法:

  • public static class UrlHelperExtensions

  • {

  • ? ?public static string AbsoluteAction(

  • ? ? ? ?this IUrlHelper helper,

  • ? ? ? ?string actionName,

  • ? ? ? ?string controllerName,

  • ? ? ? ?object routeValues = null)

  • ? ?{

  • ? ? ? ?string scheme = helper.ActionContext.HttpContext.Request.Scheme;

  • ? ? ? ?return helper.Action(actionName, controllerName, routeValues, scheme);

  • ? ?}

  • ? ?public static string AbsoluteContent(

  • ? ? ? ?this IUrlHelper helper,

  • ? ? ? ?string contentPath)

  • ? ?{

  • ? ? ? ?return new Uri(helper.ActionContext.HttpContext.Request.GetUri(), helper.Content(contentPath)).ToString();

  • ? ?}

  • ? ?public static string AbsoluteRouteUrl(

  • ? ? ? ?this IUrlHelper helper,

  • ? ? ? ?string routeName,

  • ? ? ? ?object routeValues = null)

  • ? ?{

  • ? ? ? ?string scheme = helper.ActionContext.HttpContext.Request.Scheme;

  • ? ? ? ?return helper.RouteUrl(routeName, routeValues, scheme);

  • ? ?}

  • }

  • 總結

    本文主要介紹了自定義路由匹配和生成的解決方案,把路由相關的處理集中到一個類中,避免分散在各個視圖進行維護。下篇文章,將會介紹自定義視圖搜索目錄及主題切換。

    原文:https://yangshunjie.com/A-Middleware-Implement-For-Customized-Routing-In-AspNetCore.html


    .NET社區(qū)新聞,深度好文,歡迎訪問公眾號文章匯總 http://www.csharpkit.com

    總結

    以上是生活随笔為你收集整理的自定义路由匹配和生成的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。