ASP.NET MVC - 在Windows Azure使用TempData要小心!

09 May 2012 — Written by Sky Chang
#ASP.NET MVC#Azure

其實這篇是延續之前寫的"Windows Azure - 使用Windows Azure Storage解決Sessios問題"這個主題,前一篇提到Session在Windows Azure可能會遇到的問題 ( 如果口袋很深的話=v= ),而如果對於ASP.NET MVC比較熟的人,可能就會發現一件事情;沒錯,Session會遇到的問題,在ASP.NET MVC的TempData也會碰到,那是因為TempData是利用Session來進行實作 ( 但詳細的情況小弟我並沒有真的去翻原始碼認證,所以有錯也請告知 ),所以Session抓不到的問題,在ASP.NET MVC的TempData當然也會發生。

同樣的,沒圖沒真相,我們還是稍微實驗一下吧。

開始實驗!

首先,整個專案的檔案大致是這樣,既然是要測試Windows Azure,所以當然要有Windows Azure的專案,然後也別忘了,要將Web Role設定兩個以上,如果只設一個,當然不會發生任何問題了;接下來,我們只利用一個HomeController就可以了;因為要切換頁面,所以我們要ˇ兩個View,一個就是Index,另外一個就是Index2。

image

反正是本機模擬,執行個體開四個也沒差了,但千萬不要發布上去喔!

image

HomeControl的程式碼

HomeControl的程式碼很簡單,我們在第一個View (Index),設定了Session、ViewData、ViewBag、TempData來做測試,至於為什麼還要設定ViewData和ViewBag,那是因為小弟之前太蠢了,想說ViewData和ViewBag會不會也和TempData一樣有問題,當初還跑去問David老師,只看到David老師一臉疑惑的看著我XDD;後來回到家裡仔細想想,其實ViewData和ViewBag當然不會有這個問題,理由很簡單,從Control到View這段,其實還在同一台機器上,所以自然不會有這種問題啊!! ( David老師對不起,問了蠢問題QQ ),所以這邊的ViewData和ViewBag看看就好..,其次,我們使用RoleEnvironment.CurrentRoleInstance.Id來取得目前Windows Azure的機器id,用來判斷是否不同台。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace MvcWebRole1.Controllers
{
    public class HomeController : Controller
    {
        //
        // GET: /Home/

        public ActionResult Index()
        {
            ViewBag.id = RoleEnvironment.CurrentRoleInstance.Id;
            Session["Test"] = "Have Value";
            ViewData["Test"] = "Have Value";
            ViewBag.Test = "Have Value";
            TempData["Test"] = "Have Value";
            return View();
        }

        public ActionResult Index2()
        {
            ViewBag.id = RoleEnvironment.CurrentRoleInstance.Id;
            return View();
        }
    }
}

這樣子Controller就寫好了,接下來我們來看看View。

Index的程式碼

Index裡面很簡單,就是把剛剛那個很糗的ViewData和ViewBag秀出來,基本上,是沒甚麼意義可言啦…,但是ViewBag.id就是有意義的,我們把剛剛抓到的Windows Azure機器id給Show出來,另外,我們最後面加上一個連結,準備連到另外一個View。

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index</title>
</head>
<body>
<h1>@ViewBag.id</h1>
    <div>
    Session:
    @if(Session["Test"] == null)
    {
        @:Session is null <br />
    }else
    {
        @Session["Test"]; <br />
    }
    ViewData:
    @if (ViewData["Test"] == null)
    { 
        @:ViewData is null <br />
    }
    else
    { 
        @ViewData["Test"]; <br />
    }
    ViewBag
    @if (ViewBag.Test == null)
    { 
        @:ViewBag is null <br />
    }
    else
    { 
        @ViewBag.Test;<br />
    }

    @Html.ActionLink("Next", "Index2", "Home");
    </div>
</body>
</html>

到這邊,第一個View就結束了,接下來,我們來看看Index2。

Index2的程式碼

接下來是Index2,我們把剛剛設定好的Session和TempData,Show出在Index2頁面,當然,這邊也要使用ViewBag.id來把Windows Azure上的機器id給Show出來。

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Index2</title>
</head>
<body>
    <h1>@ViewBag.id</h1>
    <div>
    Session:
    @if(Session["Test"] == null)
    {
        @:Session is null <br />
    }else
    {
        @Session["Test"]; <br />
        Session.Clear();
    }
    TempData:
    @if (TempData["Test"] == null)
    {
        @:TempData is null <br />
    }
    else
    {
        @TempData["Test"]; <br />
    }
    </div>
</body>
</html>

這樣又完成了範例,接下來我們就執行看看。

Run

我們可以發現,目前是在編號1的Windows Azure之下,接下來,我們按下Next,看看下一頁會怎樣。

image

到了第二頁,我們可以發現目前的id是0,也就是說和第一台是不同台,而這邊我們也可以發現Session是空的,而比較重要的是TempData也為空。

image

到這邊,實驗就算結束了。

後記

當然,這篇的用意是想提醒大家,使用ASP.NET MVC丟到Windows Azure的時候,使用TempData需要特別的注意,至於解法,可以參考上一篇喔。

Sky & Study4.TW