[英]How to use Action Filters with Dependency Injection in ASP.NET CORE?
我在我的ASP.NET CORE
應用程序中到處使用基於構造函數的依賴注入,我還需要在我的操作過濾器中解決依賴關系:
public class MyAttribute : ActionFilterAttribute
{
public int Limit { get; set; } // some custom parameters passed from Action
private ICustomService CustomService { get; } // this must be resolved
public MyAttribute()
{
}
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// my code
...
await next();
}
}
然后在控制器中:
[MyAttribute(Limit = 10)]
public IActionResult()
{
...
如果我將 ICustomService 放到構造函數中,那么我將無法編譯我的項目。 那么,我該如何在操作過濾器中獲取接口實例呢?
如果你想避免服務定位器模式,你可以通過構造函數注入使用 DI 和TypeFilter
。
在您的控制器中使用
[TypeFilter(typeof(MyActionFilterAttribute), Arguments = new object[] {10})]
public IActionResult() NiceAction
{
...
}
並且您的ActionFilterAttribute
不再需要訪問服務提供者實例。
public class MyActionFilterAttribute : ActionFilterAttribute
{
public int Limit { get; set; } // some custom parameters passed from Action
private ICustomService CustomService { get; } // this must be resolved
public MyActionFilterAttribute(ICustomService service, int limit)
{
CustomService = service;
Limit = limit;
}
public override async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
await next();
}
}
對我來說,注釋[TypeFilter(typeof(MyActionFilterAttribute), Arguments = new object[] {10})]
似乎很尷尬。 為了獲得更易讀的注釋,如[MyActionFilter(Limit = 10)]
您的過濾器必須從TypeFilterAttribute
繼承。 我如何將參數添加到 asp.net 中的操作過濾器? 顯示了此方法的示例。
您可以使用Service Locator
:
public void OnActionExecuting(ActionExecutingContext actionContext)
{
var service = actionContext.HttpContext.RequestServices.GetService<IService>();
}
請注意,通用方法GetService<>
是一個擴展方法,位於命名空間Microsoft.Extensions.DependencyInjection
。
如果要使用構造函數注入,請使用TypeFilter
。 請參閱如何將參數添加到 asp.net 中的操作過濾器?
您可以使用ServiceFilters在控制器中實例化您需要的 ActionFilters。
在控制器中:
[ServiceFilter(typeof(TrackingAttribute), Order = 2)]
您需要在依賴項容器中注冊 TrackingAttribute 以便 ServiceFilter 可以解析它。
在https://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/閱讀更多相關信息
一個不錯的選擇是這樣做(在 .NET Core 3.1 中測試) :
在 Filter 類中放置:
公共靜態類 FilterContainer {
public class GenericFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { string Action = filterContext.ActionDescriptor.RouteValues["action"]; Console.WriteLine($"[action]: {Action} STARTING"); } public override void OnActionExecuted(ActionExecutedContext filterContext) { string Action = filterContext.ActionDescriptor.RouteValues["action"]; Console.WriteLine($"[action]: {Action} FINISHED"); } public override void OnResultExecuting(ResultExecutingContext filterContext) { string Action = filterContext.ActionDescriptor.RouteValues["action"]; Console.WriteLine($"[action]: {Action} GIVING RESULT"); } public override void OnResultExecuted(ResultExecutedContext filterContext) { string Action = filterContext.ActionDescriptor.RouteValues["action"]; ObjectResult ObjectResult = (ObjectResult)filterContext.Result; Console.WriteLine($"[action]: {Action} RESULT GIVEN. Value: {ObjectResult.Value}"); } } }
在 Startup.cs/ConfigureServices(IServiceCollection services) 里面放這個:
services.AddControllers().AddMvcOptions(options => options.Filters.Add(new FilterContainer.GenericFilter()));
結果是,對 .NET Core 應用程序內任何類型操作的請求將通過此管道進出,而無需在任何操作上方聲明過濾器屬性。
讓我向您展示 Visual Studio 的輸出窗口中的一個示例:
[action]: JSON STARTING
[action]: JSON FINISHED
[action]: JSON GIVING RESULT
[action]: JSON RESULT GIVEN. Value: TestId: 103, FullName:...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.