繁体   English   中英

仅缓存子级用户控件

[英]Caching child user control only

有父级用户控件,如下所示。

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="TestUserControl.ascx.cs" Inherits="TestUserControl" %>
<%@ Register Src="~/UserControls/ChildUserControl.ascx" TagName="ChildUserControl" TagPrefix="FLI" %>
<div>    
    <FLI:ChildUserControl ID="child1" runat="server"/>    
</div>

子usecontrol具有公共属性MatchDescription ,该属性在父控件的Page_Load中设置。 我想基于MatchDescription属性缓存子控件的多个版本。

问题是,不能在Page_Load设置MatchDescription属性,因为子控件的缓存副本一旦可用就被使用。

我该如何解决这个问题?

谢谢!

看起来使用GetVaryByCustomString是这里的方法。 我的概念证明包括以下内容:

  • WebUserControl.ascx:测试控件。 它具有单个公共属性MatchDescription
  • Global.asax:重写GetVaryByCustomString方法。
  • WebForm.aspx:承载控件的简单表单。

WebUserControl.ascx

将以下内容添加到控件上的标记中:

<%@ OutputCache Duration="120" VaryByParam="none" VaryByCustom="MatchDescription" %>

这指定了缓存控件的持续时间(以秒为单位),而VaryByCustom="MatchDescription"指定了我们将要缓存的参数的名称。

WebUserControl.ascx.cs

public partial class WebUserControl1 : System.Web.UI.UserControl
{
    public string MatchDescription { get; set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        object description = this.Context.Application["MatchDescription"];

        if (description != null)
        {
            this.MatchDescription = description.ToString();
        }
        else
        {
            this.MatchDescription = "Not set";
        }

        Label1.Text = "Match description: " + this.MatchDescription;
    }
}

这将检查MatchDescription值是否存在。 由于父页面中代码的工作方式,您永远都不会看到“未设置”,尽管在您的实现中它可能会有用,以防万一未设置该值。

Global.asax

Global.asax文件添加到您的项目,然后添加以下方法:

public override string GetVaryByCustomString(HttpContext context, string custom)
{
    if (custom == "MatchDescription")
    {
        object description = context.Application["MatchDescription"];

        if (description != null)
        {
            return description.ToString();
        }
    }

    return base.GetVaryByCustomString(context, custom);
}

这是检查与缓存控件关联的MatchDescription的位。 如果找不到,则将正常创建控件。 之所以使用context.Application是因为我们需要一种在父页面,用户控件和global.asax文件之间传递描述值的方法。

WebForm.aspx.cs

public partial class WebForm : System.Web.UI.Page
{
    private static string[] _descriptions = new string[]
    {
        "Description 1",
        "Description 2",
        "Description 3",
        "Description 4"
    };

    protected override void OnPreInit(EventArgs e)
    {
        //Simulate service call.
        string matchDescription = _descriptions[new Random().Next(0, 4)];
        //Store description.
        this.Context.Application["MatchDescription"] = matchDescription;

        base.OnPreInit(e);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        var control = LoadControl("WebUserControl.ascx") as PartialCachingControl;
        this.Form.Controls.Add(control);

        //Indicate whether the control was cached.
        if (control != null)
        {
            if (control.CachedControl == null)
            {
                Label1.Text = "Control was cached";
            }
            else
            {
                Label1.Text = "Control was not cached";
            }
        }
    }
}

请注意,在这段代码中,我正在/模拟OnPreInit方法中的服务调用。 这是必需的,因为它发生在页面生命周期中的GetVaryByCustomString方法之前。

请记住,如果控件已被缓存,则例如,在Page_Load方法中访问它将需要以下形式的代码:

    if (control is PartialCachingControl &&
        ((PartialCachingControl)control).CachedControl =!= null)
{
    WebUserControl1 userControl = (WebUserControl1)((PartialCachingControl)control).CachedControl;
}

参考文献:

我的答案受到启发:是否有任何方法可以清除/刷新/删除OutputCache?

我在以下问题中找到了Pre_Init提示: 输出缓存-基于PageLoad()中设置的值的GetVaryByCustomString

此知识库文章讨论了为什么PartialCachingControl.CachedControl属性始终可以返回null的原因: http : //support.microsoft.com/kb/837000

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM