從本篇起,老週會連發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,就能看到結果了。