OutputCache 使用 PostBack 返回无效版本

发布于 2024-08-21 02:55:32 字数 1733 浏览 4 评论 0原文

我在输出缓存方面遇到了一个奇怪的问题。我在一个页面上有多个用户控件,其中一个是登录控件。页面和登录控件不会被缓存,但其他用户控件会使用 VaryByParam 进行缓存。现在,当我点击不同的页面时,所有这些都与缓存一起工作。但一旦我登录,该页面上的其他用户控件就会显示旧的缓存版本。如果刷新页面,我将获得所有用户控件的正确缓存版本。仅当发生回发时才会出现问题。由于回发时的某种原因,返回的缓存版本不考虑 VaryByParam 字符串。在网上搜索这个问题时,我确实在 asp.net 上看到了类似的问题,其中有一个代码解释了这一点。

为什么回发会导致缓存返回无效版本?

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%@ Register src="WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>  
</head>
<body>
    <form id="form1" runat="server">       
        <uc1:WebUserControl1 ID="WebUserControl11" runat="server" EnableViewState="false" />           
    </form>
</body>
</html>

WebUserControl1.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<%@ OutputCache Duration="3600" VaryByParam="MenuID" %>
<asp:LinkButton ID="test" runat="server" Text="PostBack"></asp:LinkButton>
<br /><br />
<a href="Default.aspx?menuid=1">1</a> - <a href="Default.aspx?menuid=2">2</a> - <a href="Default.aspx?menuid=3">3</a>
<br /><br />
MenuID: <%= Request.QueryString["MenuID"] != null ? Request.QueryString["MenuID"].ToString() : "null" %>

运行演示,您将看到在页面之间单击会获得正确的缓存版本。但是尝试一下单击页面并导致回发,然后您会发现有时会得到错误的缓存版本。

I am having a weird issue happening with outputcache. I have multiple user controls on a page, one of which is a login control. The page and the login control is NOT cached, but other user controls are cached with VaryByParam. Now all of this works along with caching when I click on to different pages. But as soon as I login, other user controls on that page display old cached versions. If I refresh the page, I get the correct cached version of all user controls. The problem is only when a postback happens. For some reason on a postback, the cached version returned does not take into account the VaryByParam string. When searching for this online, I did see a similar problem being asked on asp.net, which had a code explaining this.

Why would postback cause the cache to return back invalid version ?

Default.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%@ Register src="WebUserControl1.ascx" tagname="WebUserControl1" tagprefix="uc1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>  
</head>
<body>
    <form id="form1" runat="server">       
        <uc1:WebUserControl1 ID="WebUserControl11" runat="server" EnableViewState="false" />           
    </form>
</body>
</html>

WebUserControl1.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<%@ OutputCache Duration="3600" VaryByParam="MenuID" %>
<asp:LinkButton ID="test" runat="server" Text="PostBack"></asp:LinkButton>
<br /><br />
<a href="Default.aspx?menuid=1">1</a> - <a href="Default.aspx?menuid=2">2</a> - <a href="Default.aspx?menuid=3">3</a>
<br /><br />
MenuID: <%= Request.QueryString["MenuID"] != null ? Request.QueryString["MenuID"].ToString() : "null" %>

Run the demo and you will see clicking between pages gets the correct cached version. But play around with clicking a page and causing a postback and then you will see that you get the wrong cache version sometimes.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

涫野音 2024-08-28 02:55:32

我认为这是 ASP .Net 中的一个错误,在解决之前,这里有一个解决方法。

对于每次回发,我想要一个新版本而不是缓存版本。但除此之外我想要缓存的版本。所以我可以看看这是什么类型的请求。如果这是“POST”,我将获得新版本,如果这是“GET”,我将从缓存中获取版本。为此,我在用户控件上设置了 VaryByCustom 缓存设置。在我的 global.asax 中这样做了:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg.Trim().ToLower() == "getorpost")
    {
           //for a POST request (postback) force to return back a non cached output
            if (context.Request.RequestType.Equals("POST"))
            {
                return "post" + DateTime.Now.Ticks;
            }
            return "get";
     }
     return base.GetVaryByCustomString(context, arg);
}

I think this is a bug in ASP .Net, and until its solved, here is a workaround.

For every postback I want a fresh version and not a cached version. But otherwise I want the cached version. So I can look if what kind of request this is. If this is a 'POST' I will get a new version, if this is a 'GET' I will get the version from cache. To do this, I setup a VaryByCustom cache setting on the usercontrol. And in my global.asax did this:

public override string GetVaryByCustomString(HttpContext context, string arg)
{
    if (arg.Trim().ToLower() == "getorpost")
    {
           //for a POST request (postback) force to return back a non cached output
            if (context.Request.RequestType.Equals("POST"))
            {
                return "post" + DateTime.Now.Ticks;
            }
            return "get";
     }
     return base.GetVaryByCustomString(context, arg);
}
薔薇婲 2024-08-28 02:55:32

来自 MS 内部的某个人:

控件的输出缓存行为最初是为了关闭查询字符串集合或表单值集合而编写的(现在仍然是这样编写的)。内部逻辑根据请求是 GET 还是 POST 来确定要查看哪个集合。我同意这种行为不太明显,但这显然是控制输出缓存行为的初衷。

将查询字符串值包含在输出缓存决策中的两种解决方法是:

  1. 将查询字符串值镜像到
    隐藏表单变量,如果是的话
    可能的。
  2. 或者使用您的解决方法
    已经发现——即使用
    因定制而异和
    GetVaryByCustomString。定制
    实施
    GetVaryByCustomString 可以返回一个
    包含一个或多个值的字符串
    从 Request.Querystring 读取
    POST 请求以获得所需的
    影响。

From someone inside MS:

The output cache behavior for controls was originally written (and still is written) to key off of either the query-string collection or the form value collection. The internal logic determines which collection to look at based on whether the request is a GET or a POST. I agree that the behavior is less than obvious, but that was apparently the original intent of the control output caching behavior.

The two workarounds to include query string values are part of output cache decisions are:

  1. Mirror query-string values into
    hidden form variables if that is
    possible.
  2. Alternatively use the workaround you
    already discovered – which is to use
    VaryByCustom and
    GetVaryByCustomString. A custom
    implementation of
    GetVaryByCustomString can return a
    string containing one or more values
    read from Request.Querystring for
    POST requests to get the desired
    effect.
悍妇囚夫 2024-08-28 02:55:32

我同意 Garfield 的观点,并且认为使用 VaryByCustom 的建议也是一个聪明的主意。为此,您可以简单地在 Global.asax 中使用 Response.Cache.SetNoServerCaching(),它只需要在 Global.asax 中感知页面是否是回发。 此处 是一个代码示例。

I agree with Garfield as to the cause, and think the suggestion to use VaryByCustom is a smart idea too. In order to do that, you can simply use Response.Cache.SetNoServerCaching() in Global.asax, which just requires sensing in Global.asax whether the page is a post-back or not. Here is a code example.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文