【问题标题】:Vary by control properties using PartialCaching in ASP.NET使用 ASP.NET 中的 PartialCaching 因控件属性而异
【发布时间】:2010-10-27 05:26:27
【问题描述】:

我在用户控件的基类上使用 PartialCaching 属性。

我希望缓存的控件根据控件实例上设置的属性而有所不同。

例如:

<mycontrols:control1 runat="server" param1="10" param2="20" />

...输出将与具有不同属性的控件实例分开缓存:

<mycontrols:control1 runat="server" param1="15" param2="20" />

...这个控件也将被单独缓存:

<mycontrols:control1 runat="server" param1="10" param2="25" />

但是,如果两个单独页面上的两个控件实例具有 相同 param1 和 param2 属性,我希望它们作为一个对象缓存(以便共享缓存的控件)。

上面的用例可以用 PartialCaching 属性来实现吗?我会使用什么设置?变化控制?

另外,是否可以在运行时使缓存持续时间可变?

谢谢。

【问题讨论】:

    标签: asp.net caching outputcache


    【解决方案1】:

    要回答你的第一个问题,让我先告诉你,你的问题本身就有答案;)。 'Shared' ... 是的,这就是关键字 :) 要在缓存中为所有页面的用户控件提供一个实例,请在 @OutputCache 指令中设置 Shared='true'。这应该在用户控制级别设置,即在 ascx 页面中。

    要基于用户控件属性缓存用户控件,您应该在 PartialCachingAttribute 的 varyByControls 部分中指定属性的完全限定名称。多个属性(如果有的话)应该用分号分隔。

    <%@ Control Language="C#" AutoEventWireup="true" 
    CodeFile="WebUserControl.ascx.cs" 
    Inherits="UC_WebUserControl" %>
    <%@ OutputCache Duration="60" 
    VaryByControl="UC_WebUserControl.param1;UC_WebUserControl.param2" 
    VaryByParam="none" Shared="true" %>
    

    或者您也可以为用户控件包含 PartialCache 属性:

    [PartialCaching(60, null, "UC_WebUserControl.param1;UC_WebUserControl.param2", null, true)]
    public partial class UC_WebUserControl : System.Web.UI.UserControl
    {
        public string param1 { get; set; }
        public string param2 { get; set; }
    
    }
    

    或者另一种缓存两个值组合的控件的方法是:

    [PartialCaching(60, null, "UC_WebUserControl.BothParams", null, true)]
    public partial class UC_WebUserControl : System.Web.UI.UserControl
    {
        public string param1 { get; set; }
        public string param2 { get; set; }
    
        public string BothParams    
        {
            get { return String.Concat(param1, param2); }
        }
    
    }
    

    最后一个参数 (true) 指定共享。持续时间由60指定。参考链接How to: Cache Multiple Versions of a User Control Based on Parameters

    要回答您的第二个问题,要在运行时为用户控制变量设置缓存持续时间,您可以通过两种方式进行:

    1. 在后面的用户控制代码中赋值:

      [PartialCaching(60, null, "UC_WebUserControl.BothParams", null, true)]
      public partial class WebUserControl1 : System.Web.UI.UserControl
      {
          ...
          protected void Page_Load(object sender, EventArgs e)
          {
              this.CachePolicy.Duration = new TimeSpan(0, 0, 60);
          }    
      }
    2. 您可以在使用用户控件的 ID 引用用户控件的页面后面的代码中分配它。

    例如如果aspx上的用户控件是:

    <mycontrols:control1 ID="ucControl1" runat="server" param1="15" param2="20" />
    

    那么在aspx后面的代码中,你应该写:

    this.ucControl1.CachePolicy.Duration = new TimeSpan(0, 0, 60);
    

    仅供参考,如果用户控件和页面都被缓存:如果页面输出缓存持续时间小于用户控件的持续时间,则用户控件将被缓存直到其持续时间到期,即使在页面的其余部分被缓存之后为请求重新生成。例如,如果页面输出缓存设置为 50 秒,而用户控件的输出缓存设置为 100 秒,则用户控件每过期两次,页面其余部分过期。

    【讨论】:

    • Response.Cache 用于页面级缓存。我对使用 PartialCaching 属性的控制级缓存感兴趣。
    • 另外,您的示例 [PartialCaching(60, "param1", null, null, true)] ...这将根据 "param1" QueryString 或 POST 参数而有所不同。那不是我想要的。 “我希望缓存的控件根据控件实例上设置的属性而有所不同。”
    • 需要在PartialCachingAttribute的VaryByControls中赋值属性
    • 相应地编辑了我的回复
    • 如果用户控件没有在 aspx 文件中静态声明,如果它是动态加载的,并且 VaryByControl 设置为用户控件上的一个属性会怎样: public long MessageID { get { return Convert. ToInt64(lblMessageID.Text); } 设置 { lblMessageID.Text = value.ToString(); } } /// 这将创建一个 catch 22!在加载控件之前无法设置属性,由于未设置属性,因此无法从缓存中加载正确的属性。
    【解决方案2】:
    【解决方案3】:

    我正在为这个非常古老的问题发布一个新答案,因为接受的答案非常不准确。 这个正确答案是:

    • 没有根据控件属性值变化的内置方法。 VaryByControl 仅适用于控件。
    • 提供缓存版本时,您的控制字段将为空。您无法在代码中更改缓存持续时间 - 您会收到 NullReferenceException。
    • 如果 VaryByControl 设置为任何值,则会出现一个错误,该错误会根据控件 ID 和 NamingContainer ID 改变缓存。这就是为什么它有时会起作用的原因。错误就在这里:http://referencesource.microsoft.com/#System.Web/xsp/system/Web/UI/PartialCachingControl.cs#530

    我最近在这里写了一篇博客:http://tabeokatech.blogspot.be/2014/09/outputcache-on-user-controls.html

    实现这项工作的一种方法是在代码隐藏中自己调用 PartialCachingControl 的构建器方法,并在 guid 参数中嵌入您想要改变的属性值:

        // PhControls is an asp:PlaceHolder
        protected void Page_Init(object sender, EventArgs e)
        {
            for (int i = 0; i < 3; i++)
            {
                System.Web.UI.StaticPartialCachingControl.BuildCachedControl(PhControls, String.Format("Test{0}", i), String.Format("1234567{0}", i), 180, null, null, null, null, new System.Web.UI.BuildMethod(GetBuilderDelegate(i)), null);
            }
        }
    
        public Func<Control> GetBuilderDelegate(int number)
        {
            return delegate()
            {
                var control = (UserControls.Test)LoadControl("~/UserControls/Test.ascx");
                control.Number = number;
                return control;
            };
        }
    

    这也巧妙地处理了代码隐藏中不同的缓存持续时间。确保在执行此操作时从 ascx 中的标记中删除 OutputCache 指令。否则 LoadControl 会为您获取另一个 PartialCachingControl 并且强制转换失败。

    【讨论】:

      猜你喜欢
      • 2015-07-16
      • 2021-11-12
      • 2014-01-20
      • 1970-01-01
      • 2011-03-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-17
      相关资源
      最近更新 更多