2017-03-09 127 views
0

我正在構建ASP.NET核心MVC應用程序,並試圖創建一個全局操作過濾器,記錄多少花在執行動作上的時間(如果花費的時間超過某個閾值,它只應該記錄下來)。我已經成功完成了這一工作,但現在我想能夠說單個行動或單個控制者應該有不同的門檻。當我嘗試這個時,我的動作過濾器被應用了兩次(這不是我想要的),但是具有正確的兩個不同的閾值。覆蓋ASP.NET中的控制器/操作中的全局操作過濾器核心MVC 1.0.1(ASP.NET核心1.1)

我已經嘗試了很多事情並且四處搜索。在MVC 3和MVC 4項目中,我已經使用Global.asax中的RegisterGlobalFilters()成功完成了這一任務,並且在控制器/操作中使用該屬性時,它會自動覆蓋全局。我自己也嘗試在這篇文章中列出的方法,沒有運氣:

Override global authorize filter in ASP.NET Core 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,並在操作上使用[TypeFilter(typeof(PerformanceLoggingFilter))]],但沒有運氣。

任何人都可以幫我嗎?

回答

0

我把它結合工作感謝@集的回答上面這個答案: 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"); 
    } 
} 
1

可能建議你有點不同的執行試圖通過使用一個動作過濾器和其他自定義屬性來實現的:

  • 創建一個新的簡單屬性(讓我們將其命名爲ExpectedMaxAttribute),只是持有ExpectedMax值。將此屬性應用於具有不同值的控制器的操作。

  • 將您的PerformanceLogging操作篩選器保留爲全局,但修改實施。在OnActionExecuted方法檢查控制器的行爲是否有ExpectedMaxAttribute。如果是,則請從屬性讀取ExpectedMax值,否則使用操作過濾器的默認值。


另外,我建議你到相應的重命名操作篩選慣例命名類似PerformanceLoggingActionFilter

+0

你的回答使我在正確的道路上。我已經發布了我的解決方案作爲答案。謝謝! – nicklas669