【问题标题】:OutputCache and injected ActionParametersOutputCache 和注入的 ActionParameters
【发布时间】:2015-09-11 09:31:39
【问题描述】:

我们使用 ActionFilterAttribute 将一些参数注入到动作中,效果很好。

但是当我们添加 OutputCache 时,当使用 Html.RenderAction() 而不是直接浏览操作时,它仅在“MyID”上变化。

任何想法如何让 OutputCache 始终识别“MyID”?

控制器

[SiteIDs, OutputCache]
public ActionResult SiteContent(string myID)
{
    return Content(myID);
}

动作过滤器

public class SiteIDs : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (filterContext.ActionParameters.ContainsKey("MyID"))
        {
            filterContext.ActionParameters["MyID"] = GetMyIDByHostname();
        }

        base.OnActionExecuting(filterContext);
    }
}

【问题讨论】:

    标签: asp.net-mvc-5 outputcache actionfilterattribute


    【解决方案1】:

    使用 OutputCacheAttribute,当从缓存中检索页面时,操作过滤器将不会执行。您可能应该使用mvcdonutcaching 以便即使在从缓存中检索时也执行操作过滤器。我建议阅读this

    【讨论】:

    • 我现在已经尝试过 MvcDonutCaching 并且我的 ActionFilter 每次都运行但它不起作用(无论是通过 Html.RenderAction() 还是直接)。我还查看了两者的来源,似乎 [OutputCache] 在生成密钥时使用了 ActionParameters 和 [DonutOutputCache] RouteData。
    【解决方案2】:

    选项 1

    根据this answer,你只需要使用VaryByParam = "*",它会根据你传递给action方法的参数而自动变化。

    [SiteIDs, OutputCache(VaryByParam = "*")]
    public ActionResult SiteContent(string myID)
    {
        return Content(myID);
    }
    

    但是,使用IActionFilter 可能不起作用(尚未尝试过)。您可以尝试使用 IValueProvider 代替(无论如何,这是一种更简洁的方式来执行您正在使用操作过滤器所做的事情)。

    选项 2

    您可以使用VaryByCustomGetVaryByCustomString 按主机名改变缓存。

    [SiteIDs, OutputCache(VaryByParam = "none", VaryByCustom = "hostname")]
    public ActionResult SiteContent(string myID)
    {
        return Content(myID);
    }
    

    在您的Global.asax 文件中:

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
    
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }
    
        public override string GetVaryByCustomString(HttpContext context, string custom)
        {
            if (custom == "hostname")
            {
                return "HostName=" + context.Request.Url.Host;
            }
    
            return base.GetVaryByCustomString(context, custom);
        }
    }
    

    请记住,只有在未设置 OutputCache 时才会点击您的操作过滤器。因此,您需要根据与 ID 不同的相同值(或多个值)来改变缓存。最简单的解决方案是使用 HttpContext 中已有的内容,例如主机名。

    【讨论】:

    • 选项 1:是的,VaryByParam = "*" 是默认值,并且在使用 Html.RenderAction("MyAction", "MyController", new { notIncludingMyIDInRouteValueDictinary = "foo" }) 时与 IActionFilter 一起使用但在直接访问 Action 时不会。我今天尝试了 IValueProvider,没有区别。选项 2:尚未尝试过。
    猜你喜欢
    • 2012-10-21
    • 1970-01-01
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-22
    • 2012-02-13
    相关资源
    最近更新 更多