How to disable attribute on action when applied at controller level?

I have the following controller:

[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);
    }
}

      

As you can see, the controller is decorated with an attribute [NoCache]

.

Is there a way to prevent this attribute from being applied to the action GetUserEntitlementReport

?

I know I can remove an attribute at the controller level, but this is not my favorite solution because the controller contains a lot of other actions and I don't want to apply the attribute for each action independently.

+3


source to share


3 answers


You can create a new attribute that can be used in separate actions to opt out of NoCache specified at the controller level.

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

      

Check all actions where you want to enable caching with [AllowCache]



Then in the code for your NoCacheAttribute

disable caching disable if attribute is AllowCache

missing

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.
        }
    }
}

      

+4


source


There is an attribute that you can apply to an action. This is [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


source


This can be accomplished by implementing and registering a custom filter provider . As a starting point, I would get the FilterAttributeFilterProvider and override GetFilters to remove the NoCache attribute when needed.

0


source







All Articles