首页 文章

覆盖 ASP.NET 中的全局动作过滤器 ASP.NET 核心 MVC 1.0.1(ASP.NET 核心 1.1)

提问于
浏览
0

我正在构建一个 ASP.NET 核心 MVC 应用程序,并且我正在尝试创建一个全局操作过滤器来记录执行操作所花费的时间(它应该只记录花费的时间是否高于某个阈值)。我已成功完成此操作但现在我希望能够说单个操作或单个控制器应具有不同的阈值。当我尝试这个时,我的动作过滤器被应用 twice(which 不是我想要的)但是具有正确的两个不同的阈值。

我尝试过很多东西并四处寻找。在 MVC 3 和 MVC 4 项目中,我已经使用 Global.asax 中的 RegisterGlobalFilters()成功完成了此操作,并且当我在 controller/action 上使用该属性时,它会自动覆盖全局的项目。我也试过这篇文章中列出的方法,没有运气:

覆盖 ASP.NET 核心 MVC 1.0 中的全局授权过滤器

我的 ActionFilterAttribute 的代码:

public class PerformanceLoggingAttribute : ActionFilterAttribute
{
    public int ExpectedMax = -1; // Log everything unless this is explicitly set
    private Stopwatch sw;

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        sw = Stopwatch.StartNew();
    }

    public override void OnActionExecuted(ActionExecutedContext context)
    {
        sw.Stop();
        if (sw.ElapsedMilliseconds >= ExpectedMax)
        {
            // Log here
        }
    }

    //public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    //{
    //    // If there is another performance filter, do nothing
    //    if (context.Filters.Any(item => item is PerformanceLoggingAttribute && item != this))
    //    {
    //        return Task.FromResult(0);
    //    }
    //    return base.OnActionExecutionAsync(context, next);
    //}
}

我在我的 Startup.cs 中应用了这个全局过滤器:

services.AddMvc(options =>
            {
                if (_env.IsProduction()) options.Filters.Add(new RequireHttpsAttribute());
                //options.Filters.Add(new PerformanceLoggingFilter() { ExpectedMax = 1 }); // Add Performance Logging filter
                options.Filters.Add(new PerformanceLoggingAttribute() { ExpectedMax = 1 }); // Add Performance Logging filter
            });

在我的控制器中,我正在应用属性:

//[TypeFilter(typeof(PerformanceLoggingFilter))]
[PerformanceLogging(ExpectedMax = 2)]
public IActionResult Index()
{
    var vm = _performanceBuilder.BuildPerformanceViewModel();
    return View(vm);
}

从上面的代码片段可以看出,我已经尝试了 OnActionExecutionAsync 方法,我也尝试了 IActionFilter,并在动作上使用[9],但没有运气。

谁能帮我吗?

2 回答

  • 1

    可以建议您使用一个操作过滤器和其他自定义属性,尝试实现一些不同的实现:

    • 创建一个新的简单属性(让我们将其命名为ExpectedMaxAttribute),它只保存ExpectedMax值。将此属性应用于具有不同值的控制器操作。

    • PerformanceLogging动作过滤器保持为全局,但修改实现。在OnActionExecuted方法上检查控制器的动作是否有ExpectedMaxAttribute。如果是,则从属性读取ExpectedMax值,否则使用操作过滤器中的默认值。


    另外,我建议你根据常规命名重命名动作过滤器,如PerformanceLoggingActionFilter

  • 0

    感谢@Set 上面的回答并结合这个答案,我得到了它的工作:https://stackoverflow.com/a/36932793/5762645

    我最终得到了一个应用于所有操作的全局操作,然后有一个简单的 ExpectedMaxAttribute,我将其置于阈值应该不同的操作上。在我的全局操作过滤器的 OnActionExecuted 中,然后我检查有问题的操作是否附加了 ExpectedMaxAttribute,然后从中读取 ExpectedMax。以下是我的属性:

    public class PerformanceLoggingExpectedMaxAttribute : ActionFilterAttribute
    {
        public int ExpectedMax = -1;
    }
    

    我添加到 ActionFilter 的 OnActionExecuted 部分:

    public override void OnActionExecuted(ActionExecutedContext context)
     {
         sw.Stop();
         foreach (var filterDescriptor in context.ActionDescriptor.FilterDescriptors)
         {
             if (filterDescriptor.Filter is PerformanceLoggingExpectedMaxAttribute)
             {
                 var expectedMaxAttribute = filterDescriptor.Filter as PerformanceLoggingExpectedMaxAttribute;
                 if (expectedMaxAttribute != null) ExpectedMax = expectedMaxAttribute.ExpectedMax;
                 break;
             }
         }
         if (sw.ElapsedMilliseconds >= ExpectedMax)
         {
             _logger.LogInformation("Test log from PerformanceLoggingActionFilter");
         }
     }
    

相关问题