【问题标题】:How to Disable Attribute on Action When Applied at Controller Level?在控制器级别应用时如何禁用操作属性?
【发布时间】:2015-02-05 04:55:46
【问题描述】:

我有以下控制器:

[NoCache]
public class AccountController : Controller
{
    [Authorize(Roles = "admin,useradmin")]
    public ActionResult GetUserEntitlementReport(int? userId = null)
    {
        var byteArray = GenerateUserEntitlementReportWorkbook(allResults);

        return File(byteArray,
                System.Net.Mime.MediaTypeNames.Application.Octet,
                "UserEntitlementReport.xls");
    }
}

public class NoCache : ActionFilterAttribute
{
    public override void OnResultExecuting(ResultExecutingContext filterContext)
    {
        var response = filterContext.HttpContext.Response; 
        response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1));
        response.Cache.SetValidUntilExpires(false);
        response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
        response.Cache.SetCacheability(HttpCacheability.NoCache);
        response.Cache.SetNoStore();
        base.OnResultExecuting(filterContext);
    }
}

如您所见,控制器用[NoCache] 属性修饰。

有什么方法可以防止这个属性被应用到GetUserEntitlementReport 动作上?

我知道我可以在控制器级别删除属性,但这不是我最喜欢的解决方案,因为控制器包含许多其他操作,我不想将属性单独应用于每个操作。

【问题讨论】:

  • 我相信您只需将 [NoCache] 应用于各个方法,而不是将其应用于整个类。这将导致手动重复所有方法的属性,但会让您在没有它的情况下运行 GetUserEntitlementReport。
  • @amhed - 我知道该选项可用,但我正在尝试寻找替代解决方案(请参阅问题描述的最后一段)。

标签: asp.net-mvc attributes annotations


【解决方案1】:

您可以创建一个新属性,该属性可用于单个操作以选择退出在控制器级别指定的 NoCache。

[AttributeUsage(AttributeTargets.Class |
                AttributeTargets.Method,
                AllowMultiple = false,
                Inherited = true)]
public sealed class AllowCache : Attribute { }

使用[AllowCache]标记您希望允许缓存的任何操作

然后在 NoCacheAttribute 的代码中,仅当 AllowCache 属性不存在时才禁用缓存

public class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        base.OnActionExecuting(filterContext);

        var actionDescriptor = filterContext.ActionDescriptor;
        bool allowCaching = actionDescriptor.IsDefined(typeof(AllowCache), true) ||
            actionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowCache), true);

        if(!allowCaching)
        {
            //disable caching.
        }
    }
}

【讨论】:

    【解决方案2】:

    有一个属性可以应用于动作。 那就是[OverrideActionFilters]。

    [NoCache]
    public class AccountController : Controller
    {
        [Authorize(Roles = "admin,useradmin")]
        [OverrideActionFilters]
        public ActionResult GetUserEntitlementReport(int? userId = null)
        {
            var byteArray = GenerateUserEntitlementReportWorkbook(allResults);
    
            return File(byteArray,
                    System.Net.Mime.MediaTypeNames.Application.Octet,
                    "UserEntitlementReport.xls");
        }
    }
    

    【讨论】:

      【解决方案3】:

      这可以通过implementing and registering a custom filter provider 完成。作为起点,我将从FilterAttributeFilterProvider 派生并覆盖GetFilters 以在适当的时候删除NoCache 属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-08
        • 2018-01-09
        • 2016-04-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多