DOBON.NET DOBON.NETプログラミング掲示板過去ログ

Cookie変数が即座に反映されない

環境/言語:[Win7、VWD2008、VB、.NET3.5、Access2003]
分類:[ASP.NET]

更新したCookie変数が即座に反映されなくて困っております。
解決のヒントが頂ければ助かります。

DropDownListで注文したい弁当を選ばせます。
自分のお気に入りの弁当はみんな決まっていますので、その情報をCookie変数に保存して
おくのが便利と考えました。
そこで、弁当注文に使用する情報は、Cookie変数の弁当情報を利用する方法にしましたが
DropDownListで選んだ弁当情報が、DropDownListの「AutoPostBack」ではCookie変数に
即座に反映されないのです。一回遅れて反映されます。

DropDownListで選んだ弁当情報を即座にCookie変数に反映させるには、コードをどの様に
修正すれば良いでしょうか?アドバイス頂けると助かります。

日替弁当 松→竹→梅の順にDropDownListで選択して行った場合、Cookie変数の情報が
1回ずつ遅れてしまう様子の画面スナップを添付しました。

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        Label1.Text = DropDownList1.Text
 
        '毎回同じ弁当を注文する情報をクッキー変数へ保存
        'Cookie情報の書込(更新)
        Dim cookie As New HttpCookie("UserInfo")
        '日本語が文字化けしないようUrlEncodeを利用 06/02/27
        'http://social.msdn.microsoft.com/Forums/ja-JP/vsfeedbackja/thread/6ea71b80-54cf-4770-bbf5-0ea764c02f6d
        cookie.Values("MyLunch") = Server.UrlEncode(DropDownList1.Text)
        cookie.Expires = DateTime.Now.AddMonths(3)
        Response.Cookies.Add(cookie)
    End Sub

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
        Label3.Text = DropDownList1.Text
        
        'Cookie情報の読込
        Dim cookie As HttpCookie = Request.Cookies("UserInfo")
        Label2.Text = Server.UrlDecode(cookie.Values("MyLunch"))
    End Sub
</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        DropDownListのAutoPostback動作の確認  11/01/22<br />
        PostBack時DropDownList.Text:<asp:Label ID="Label3" runat="server" Text="Label"></asp:Label>
        <br />
        PostBack時CookieValue:<asp:Label ID="Label2" runat="server" Text="Label"></asp:Label>
        <br />
        <br />
        <asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" 
            DataSourceID="AccessDataSource1" DataTextField="弁当名" DataValueField="弁当名" 
            onselectedindexchanged="DropDownList1_SelectedIndexChanged">
        </asp:DropDownList>
        <asp:AccessDataSource ID="AccessDataSource1" runat="server" 
            DataFile="~/App_Data/AccessDB.mdb" SelectCommand="SELECT [弁当名] FROM [弁当テーブル]">
        </asp:AccessDataSource><br />
        DropDownList.Text:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
        <br />
    </div>
    </form>
</body>
</html>
添付ファイル: CookieValue01.jpg (70 KB)
ASP.NET の経験はありませんが、挙動をお聞きする限り、以下のイベントの順番になっていませんか?


ポストバック発生
Page_Load (前の Cookie を参照)
DropDownList1_SelectedIndexChanged (今回の Cookie を設定)


このイベントの順番だったとして、次に採るべき手は何か。
一般的な方法を存じないですが、DropDownList1_SelectedIndexChanged を Label2.Text など、必要な場所に反映するコードを書くことでしょうか。
■No28056に返信(Azuleanさんの記事)
Azuleanさん、早急なアドバイスありがとうございます。

> ASP.NET の経験はありませんが、挙動をお聞きする限り、以下のイベントの順番になっていませんか?
>
> ポストバック発生
> Page_Load (前の Cookie を参照)
> DropDownList1_SelectedIndexChanged (今回の Cookie を設定)

1.最初のPage_Load (前回の Cookie を参照)
2.注文弁当を変えたい場合
 DropDownList1_SelectedIndexChanged() (Cookie情報も更新)
  ※ Response.Cookies.Add(cookie)
3.ポストバック発生
4.Page_Load (更新した Cookie を参照) 

のイベント順番になると考えコードを書きました。
どこかに認識間違いがあるのでしょうか?

Azuleanさん wrote
> このイベントの順番だったとして、次に採るべき手は何か。
> 一般的な方法を存じないですが、DropDownList1_SelectedIndexChanged を Label2.Text など、必要な場所に反映するコードを書くことでしょうか。

Azuleanさんのアドバイスのもと
Label1.Text(注文弁当)の表示を画面に用意し
以下の様なコードを書いてみました。
また、稼働画面のスナップ画像を添付しました。

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
        '最初のPage_Load時のみの処理
        If Not Page.IsPostBack Then
            'Cookie情報を「注文弁当」に表示
            'Cookie情報の読込
            Dim cookie As HttpCookie = Request.Cookies("UserInfo")
            Label1.Text = Server.UrlDecode(cookie.Values("MyLunch"))
        Else
            'PostBackによるPage_Load時の処理
            'DropDownList選択情報を「注文弁当」に表示
            Label1.Text = DropDownList1.Text
        End If
    End Sub

    Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        '毎回同じ弁当を注文する情報をクッキー変数へ保存
        'Cookie情報の書込(更新)
        Dim cookie As New HttpCookie("UserInfo")
        '日本語が文字化けしないようUrlEncodeを利用 06/02/27
        'http://social.msdn.microsoft.com/Forums/ja-JP/vsfeedbackja/thread/6ea71b80-54cf-4770-bbf5-0ea764c02f6d
        cookie.Values("MyLunch") = Server.UrlEncode(DropDownList1.Text)
        cookie.Expires = DateTime.Now.AddMonths(3)
        Response.Cookies.Add(cookie)
    End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        注文弁当のDropDownListによる変更情報の安定反映の手法検討  11/01/23<br />
        <br />
        注文弁当:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
        <br />
        <br />
        注文弁当の変更→<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" 
            DataSourceID="AccessDataSource1" DataTextField="弁当名" DataValueField="弁当名" 
            onselectedindexchanged="DropDownList1_SelectedIndexChanged" 
            AppendDataBoundItems="True">
            <asp:ListItem>注文弁当を選択</asp:ListItem>
        </asp:DropDownList>
        <asp:AccessDataSource ID="AccessDataSource1" runat="server" 
            DataFile="~/App_Data/AccessDB.mdb" SelectCommand="SELECT [弁当名] FROM [弁当テーブル]">
        </asp:AccessDataSource><br />
        <br />
    </div>
    </form>
</body>
</html>
添付ファイル: CookieValue02.jpg (25 KB)
2011/01/23(Sun) 18:46:11 編集(投稿者)

Reqeust を Request に修正
■No28057 に返信(akiraさんの記事)

> どこかに認識間違いがあるのでしょうか?

すこし違っているかもしれません。以下の順番です。

サーバー:最初の Page_Load (前回の Cookie を参照)
クライアント:DropDownList1 の選択項目を変える。
サーバー:ポストバックの Page_Load(前回の Cookie を参照) 
サーバー:DropDownList1_SelectedIndexChanged()(Cookie 情報を更新)

> 以下の様なコードを書いてみました。

拝見する限り問題ないように思いますが、不明な点はありますか?

Cookie はクライアントで情報を保持するものです。
サーバーがクライアントに Response として Cookie を送って、クライアントが Cookie を保存します。
クライアントは次回の Request でサーバーに Cookie を送ります。

Page_Load で前の Cookie が参照されるのは
クライアントから送られてきた Request を参照するためです。

DropDownList1_SelectedIndexChanged で今回の Cookie が設定されるのは
クライアントにこれから送る Response を参照するためです。

当初の質問への返答です。
> DropDownListで選んだ弁当情報を即座にCookie変数に反映させるには、コードをどの様に
> 修正すれば良いでしょうか?

ご掲示いただいたコードには3つの Cookie 変数が登場します。
Dim cookie As New HttpCookie("UserInfo")
Response.Cookies.Add(cookie)
Request.Cookies("UserInfo")

Response に追加した Cookie を即座に Request に反映したいということであれば、できません。
■No28060に返信(もりおさんの記事)
もりおさん、早急な返答ありがとうございます。

> 当初の質問への返答です。
>>DropDownListで選んだ弁当情報を即座にCookie変数に反映させるには、コードをどの様に
>>修正すれば良いでしょうか?
>
> ご掲示いただいたコードには3つの Cookie 変数が登場します。
> Dim cookie As New HttpCookie("UserInfo")
> Response.Cookies.Add(cookie)
> Request.Cookies("UserInfo")
>
> Response に追加した Cookie を即座に Reqeust に反映したいということであれば、できません。
了解しました。できないと理解しました。

> すこし違っているかもしれません。以下の順番です。
>
> サーバー:最初の Page_Load (前回の Cookie を参照)
> クライアント:DropDownList1 の選択項目を変える。
> サーバー:ポストバックの Page_Load(前回の Cookie を参照)
> サーバー:DropDownList1_SelectedIndexChanged()(Cookie 情報を更新)

私は、
1.サーバー:最初の Page_Load (前回の Cookie を参照)
2.クライアント:DropDownList1 の選択項目を変える。
3.ポストバック発生
4.サーバー:DropDownList1_SelectedIndexChanged()(Cookie 情報を更新)
5.サーバー:ポストバックの Page_Load(更新後の Cookie を参照)
の様にポストバック時の処理を4. 5.の順に行える様にする方法があるのでは?
と考えていました。ないのですね。了解しました。

>>以下の様なコードを書いてみました。
>
> 拝見する限り問題ないように思いますが、不明な点はありますか?
いいえ、不明な点はありません。
この方法で、最新の「注文弁当」情報のハンドリングが行えるコードを書いて
行きます。皆さん、ありがとうございました。
解決済み!
2011/1/23の#28057のコードでは、Cookie変数が存在しない場合、正しく動かないので
以下のコードに直しました。

<%@ Page Language="VB" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<script runat="server">
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
        'PostBackdeではなく最初のPage_Load時のみの処理
        If Not Page.IsPostBack Then
            'Cookie情報を「注文弁当」に表示
            'Cookie情報の読込
            Dim LunchCookie As HttpCookie = Request.Cookies("UserInfo")
            If LunchCookie Is Nothing Then
                'Cookie変数が存在しない場合
                Label1.Text = "日替 梅"
            Else
                'Cookie変数が存在する場合
                Label1.Text = Server.UrlDecode(LunchCookie.Values("MyLunch"))
            End If
        End If
    End Sub

    Protected Sub DropDownList1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        'DropDownList選択情報を「注文弁当」に表示
        Label1.Text = DropDownList1.Text

        '毎回同じ弁当を注文する情報をクッキー変数へ保存
        'Cookie情報の書込(更新)
        Dim LunchCookie As New HttpCookie("UserInfo")
        '日本語が文字化けしないようUrlEncodeを利用 06/02/27
        'http://social.msdn.microsoft.com/Forums/ja-JP/vsfeedbackja/thread/6ea71b80-54cf-4770-bbf5-0ea764c02f6d
        LunchCookie.Values("MyLunch") = Server.UrlEncode(DropDownList1.Text)
        LunchCookie.Expires = DateTime.Now.AddMonths(3)
        Response.Cookies.Add(LunchCookie)
    End Sub

</script>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        注文弁当のDropDownListによる変更情報の安定反映の手法検討  11/01/27<br />
        <br />
        注文弁当:<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
        <br />
        <br />
        注文弁当の変更→<asp:DropDownList ID="DropDownList1" runat="server" AutoPostBack="True" 
            DataSourceID="AccessDataSource1" DataTextField="弁当名" DataValueField="弁当名" 
            onselectedindexchanged="DropDownList1_SelectedIndexChanged" 
            AppendDataBoundItems="True">
            <asp:ListItem>注文弁当を選択</asp:ListItem>
        </asp:DropDownList>
        <asp:AccessDataSource ID="AccessDataSource1" runat="server" 
            DataFile="~/App_Data/AccessDB.mdb" SelectCommand="SELECT [弁当名] FROM [弁当テーブル]">
        </asp:AccessDataSource><br />
        <br />
    </div>
    </form>
</body>
</html>
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板