從本篇起,老週會連發N篇水文,總結一下在 MVC 專案中控制器的各種自定義設定。
本文內容相對輕鬆,重點討論一下 MVC 專案中的各種約定介面。畢竟你要對控制器做各種自定義時,多數情況會涉及到約定介面。約定介面的結構都差不多,均包含一個 Apply 方法,實現類需要通過這個方法修改關聯的模型設定。
這些約定介面是按層次來定義的,下面咱們來扒一下。
a、IApplicationModelConvention:此介面可控制的面最廣,屬於應用程式層面。它對應的模型類是 ApplicationModel。該類有個重要屬性—— Controllers,通過它你能獲取到當前應用程式已發現和識別的所有控制器資訊。每個控制器也有自己的模型類:ControllerModel。
b、IControllerModelConvention:此介面只應用於控制器層面,而不是整個應用程式。對應的模型類就是上面提到過的 ControllerModel。ControllerType屬性可以獲取控制器類的 Type 資訊,而 ControllerName 屬性最有用,因為可以改變預設的控制器命名。Actions 屬性返回此控制器中所有操作方法(Action)列表。
c、IActionModelConvention:這個介面只應用於操作方法。對應的模型類是 ActionModel。通過 ActionName 屬性可以修改操作方法的名稱。當然,操作方法的名稱可以用 ActionNameAttribute 特性類來定義。
d、IParameterModelConvention:此介面只能自定義操作方法的引數,對應的模型類是 ParameterModel。
e、IPageApplicationModelConvention、IPageHandlerModelConvention、IPageRouteModelConvention:這些介面是用在 Razor Pages 上的,也可以實現一些自定義行為。
按照需求實現對應的介面。對於應用程式層面的設定,將實現相關約定介面的類範例新增到 MvcOptions.Conventions 集合中。如果實現了 IControllerModelConvention 介面的類範例新增到 Conventions 集合中,那麼它會被應用到所有控制器上。如果只想用到特定的控制器上,應將實現類定義為特性類,然後應用程式目標控制器上。
好了,理論的東西老周就不長篇大吹了,畢竟也不是老周的特長。只要你瞭解以上各介面和相關模型類,基本上就能運用了。
下面咱們做個很實在的演示:寫一個特性類(ControllerNameAttribute),用來給控制器設定名稱。既然是針對控制器的,約定介面應選擇 IControllerModelConvention。實現程式碼如下:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)] public class ControllerNameAttribute : Attribute, IControllerModelConvention { // 私有欄位 private readonly string _name; // 建構函式 public ControllerNameAttribute(string name) { // 自定義的控制器名稱就是這樣傳遞的 _name = name; } // 這是實現介面的方法 public void Apply(ControllerModel controller) { // 修改控制器名稱 controller.ControllerName = _name; } }
這個類的邏輯很䜭智,通過建構函式的引數來傳遞自定義的控制器名稱,然後存在 _name 私有欄位中。在Apply方法中,把 _name 欄位賦值給 ControllerName屬性,就完成控制器名稱的修改了。
這個特性類用於控制器,它是一個類,所以 AttributeTargets 選用 Class。咱們建立一個新控制器,然後用 ControllerNameAttribute 來設定控制器的名稱。
[ControllerName("XinWen")] public class NewsController : Controller { [ActionName("catelogs")] public IActionResult GetCates() { return Ok(new string[] { "頭條新聞", "體育新聞", "內娛醜聞", "炒股趣聞", "生活百事", "名場面集錦", "都市傳說", "人品觀察報" }); } }
預設的時候,控制器名稱與類名相同(有 Controller 字尾的會去掉),即 News。咱們應用剛定義的特性類 ControllerNameAttribute 將控制器命名為 XinWen。操作方法 GetCates 也被重命為 catelogs。
ActionNameAttribute 是 .NET 內建已有的型別,我們可以直接用。ControllerNameAttribute 非內建,所以咱們要自己來實現。
下面程式碼初始化應用程式。
var builder = WebApplication.CreateBuilder(args); builder.Services.AddControllers(); var app = builder.Build(); app.MapControllerRoute("app", "{controller}/{action}"); app.Run();
程式執行後,存取 /xinwen/catelogs,就能看到結果了。