如何在控制器级别应用时禁用操作属性?

时间:2013-02-12 14:51:42

标签: asp.net-mvc attributes annotations

我有以下控制器:

[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操作?

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

3 个答案:

答案 0 :(得分:4)

您可以创建一个新属性,该属性可用于各个操作,以选择退出在控制器级别指定的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.
        }
    }
}

答案 1 :(得分: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");
    }
}

答案 2 :(得分:0)

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