91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Asp.Net中使用ModelConvention實現全局過濾器隔離

發布時間:2021-03-22 17:09:15 來源:億速云 閱讀:142 作者:Leah 欄目:開發技術

怎么在Asp.Net中使用ModelConvention實現全局過濾器隔離?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

ModelConvention

ModelConvention定義了操作模型的入口,又或者說是一種契約,通過它我們可以對模型進行修改,常用的Convention包括:

  • IApplicationModelConvention

  • IControllerModelConvention

  • IActionModelConvention

  • IParameterModelConvention

  • IPageRouteModelConvention

這些接口提供了一個共同的方法 Apply ,方法參數是各自的應用程序模型,以 IControllerModelConvention 為例看一下它的定義:

namespace Microsoft.AspNetCore.Mvc.ApplicationModels
{
 //
 // 摘要:
 //  Allows customization of the Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerModel.
 //
 // 言論:
 //  To use this interface, create an System.Attribute class which implements the
 //  interface and place it on a controller class. Microsoft.AspNetCore.Mvc.ApplicationModels.IControllerModelConvention
 //  customizations run after Microsoft.AspNetCore.Mvc.ApplicationModels.IApplicationModelConvention
 //  customizations and before Microsoft.AspNetCore.Mvc.ApplicationModels.IActionModelConvention
 //  customizations.
 public interface IControllerModelConvention
 {
  //
  // 摘要:
  //  Called to apply the convention to the Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerModel.
  //
  // 參數:
  // controller:
  //  The Microsoft.AspNetCore.Mvc.ApplicationModels.ControllerModel.
  void Apply(ControllerModel controller);
 }
}

從接口摘要可以看到,這個接口允許自定義 ControllerModel 對象,而如何自定義內容正是通過 Apply 方法來實現,這個方法提供了當前 ControllerModel 對象的實例,我們可以在它身上獲取到的東西實在太多了,看看它包含些什么:

怎么在Asp.Net中使用ModelConvention實現全局過濾器隔離

有了這些,我們可以做很多很靈活的操作,例如通過設置 ControllerName 字段強制更改控制器的名稱讓程序中寫死的控制器名失效,也可以通過 Filters 字段動態更新它的過濾器集合,通過 RouteValues 來更改路由規則等等。

說到這里,很多人會覺得這玩意兒和自定義過濾器看起來差不多,最開始我也這么認為,但經過實際代碼調試我發現它的生命周期要比過濾器早的多,或者說根本無法比較, 這個家伙只需要在應用啟動時執行一次并不用隨著每次請求而執行 。也就是說,它的執行時間比激活控制器還要早,那時候根本沒有過濾器什么事兒,它的調用是發生在 app.UseEndpoints()

回到最開始的需求。基于上面的介紹,我們可以自定義如下的約定:

 public class ApiControllerAuthorizeConvention : IControllerModelConvention
 {
  public void Apply(ControllerModel controller)
  {
   if (controller.Filters.Any(x => x is ApiControllerAttribute) && !controller.Filters.Any(x => x is AccessControlFilter))
   {
    controller.Filters.Add(new AccessControlAttribute());
   }
  }
 }

上面的主要思路就是通過判斷控制器本身的過濾器集合是否包含 ApiControllerAttribute 來識別是否API Controller,如果是API Controller并且沒有標記過 AccessControlAttribute 的話就新建一個實例加入進去。

那么如何把這個約定注冊到應用中呢?在Microsoft.AspNetCore.Mvc.MvcOptions中提供了 Conventions 屬性:

  //
  // 摘要:
  //  Gets a list of Microsoft.AspNetCore.Mvc.ApplicationModels.IApplicationModelConvention
  //  instances that will be applied to the Microsoft.AspNetCore.Mvc.ApplicationModels.ApplicationModel
  //  when discovering actions.
  public IList<IApplicationModelConvention> Conventions { get; }

通過操作它就能把自定義約定注入進去:

  services.AddMvc(options =>
   {
    options.Conventions.Add(new ApiControllerAuthorizeConvention());
   })

細心的人會發現,Conventions是一個 IApplicationModelConvention 類型的集合,而我們自定義的Convention是一個 IControllerModelConvention ,正常來說應該會報錯才對?原因是Asp.Net Core的DI框架幫我們提供了一系列擴展方法來簡化Convention的添加不用自己再去轉換:

怎么在Asp.Net中使用ModelConvention實現全局過濾器隔離

通過代碼調試發現,應用啟動時遍歷了系統中的所有控制器去執行Apply操作,那么通過 IApplicationModelConvention 一樣也能實現這個功能,因為它里面包含了控制器集合:

 public class ApiControllerAuthorizeConvention : IApplicationModelConvention
 {
  public void Apply(ApplicationModel application)
  {
   foreach (var controller in application.Controllers)
   {
    if (controller.Filters.Any(x => x is ApiControllerAttribute) && !controller.Filters.Any(x => x is AccessControlFilter))
    {
     controller.Filters.Add(new AccessControlFilter());
    }
   }
  }
 }

再改進一下

實際開發中我的AccessControlFilter需要通過構造函數注入業務接口,類似于這樣:

 public class AccessControlFilter : IActionFilter
 {
  private IUserService _userService;

  public AccessControlFilter(IUserService service)
  {
   _userService = service;
  }

  public void OnActionExecuting(ActionExecutingContext context)
  {
    //模擬一下業務操作
    //var user=_userService.GetById(996);
    //.......
  }

  public void OnActionExecuted(ActionExecutedContext context)
  {
  }
 }

如何優雅的在Convention中使用DI自動注入呢?Asp.Net Core MVC框架提供的 ServiceFilter 可以解決這個問題, ServiceFilter 本身是一個過濾器,它的不同之處在于能夠通過構造函數接收一個Type類型的參數,我們可以在這里把真正要用的過濾器傳進去,于是上面的過濾器注冊過程演變為:

 controller.Filters.Add(new ServiceFilterAttribute(typeof(AccessControlFilter)));

當然了,要從DI中獲取這個filter實例,必須要把它注入到DI容器中:

 services.AddScoped<AccessControlFilter>();

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

博客| 津市市| 庄浪县| 姜堰市| 大田县| 烟台市| 浦江县| 敖汉旗| 盐边县| 清流县| 楚雄市| 松原市| 措美县| 柳河县| 高要市| 屯门区| 长岛县| 秭归县| 三亚市| 乌鲁木齐县| 安国市| 张北县| 巨鹿县| 闻喜县| 黎城县| 台湾省| 思南县| 始兴县| 湖口县| 英超| 徐闻县| 睢宁县| 如东县| 阿尔山市| 浪卡子县| 贞丰县| 福建省| 榆中县| 金沙县| 怀集县| 洛川县|