2

outputcacheで奇妙な問題が発生しています。1つのページに複数のユーザーコントロールがあり、そのうちの1つがログインコントロールです。ページとログインコントロールはキャッシュされませんが、他のユーザーコントロールは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" %>

デモを実行すると、ページ間をクリックすると正しいキャッシュバージョンが取得されます。しかし、ページをクリックしてポストバックを発生させることで遊んでください。そうすると、間違ったキャッシュバージョンを取得することがあります。

4

3 に答える 3

2

これは 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);
}
于 2010-02-11T21:59:16.193 に答える
0

MS内部の誰かから:

コントロールの出力キャッシュ動作は、クエリ文字列コレクションまたはフォーム値コレクションのいずれかをキーオフするために最初に作成されました (現在も作成されています)。内部ロジックは、リクエストが GET であるか POST であるかに基づいて、参照するコレクションを決定します。動作が明白ではないことに同意しますが、それは明らかに制御出力キャッシュ動作の本来の意図でした。

クエリ文字列値を出力キャッシュの決定の一部に含めるための 2 つの回避策は次のとおりです。

  1. 可能であれば、クエリ文字列の値を非表示のフォーム変数にミラーリングします。
  2. または、すでに発見した回避策を使用してください。これは、VaryByCustom と GetVaryByCustomString を使用することです。GetVaryByCustomString のカスタム実装は、POST リクエストの Request.Querystring から読み取った 1 つ以上の値を含む文字列を返して、目的の効果を得ることができます。
于 2010-03-10T15:09:39.000 に答える
0

原因については Garfield に同意します。また、VaryByCustom を使用するという提案も賢明な考えだと思います。これを行うには、Global.asax で Response.Cache.SetNoServerCaching() を使用するだけで、ページがポストバックかどうかを Global.asax で検出する必要があります。コード例を次に示します

于 2015-06-12T20:12:37.757 に答える