在.Net 2.0上執行ASP.NET MVC的網站

在.Net 2.0上執行MVC2的網站

在使用MVC開發以來,用的.Net Framework 都是.net 3.5,甚至用.net 4.0來寫

但也許有許多公司的主機還沒升級,或是在一些虛擬主機上並沒有提供2.0以上的Framework

不過由於.net 3.5在整個架構上還是在2.0上進行擴充,並且CLR依然是用同一個,

因此基本上用.net 2.0來執行MVC2 的Web是可行的。

由於我覺得MVC 是個好東西,並且希望讓更多人能都能接觸,所以今天就來試試看並記錄下來。

 

標題雖然是寫 .Net 2.0,但在實際測試時,必須要灌到 .NET Framework 2.0 SP1才能正確執行!!

否則會遇到下面的錯誤,目前我是還沒找到解法

image

 

那接下來就開始建置一個MVC2的Web 應用程式,開發的時候還是選擇 .Net 3.5來開發就行了,

這邊就直接拿預設建立起來的範例來做測試。

首先查看所有參考的組件,按F4(屬性),將版本為3.5的組件的”複製到本機”改為True

image

需注意的是,System.Web.Mvc版本是2.0,但也要複製到本機喔。

另外System.Core雖然選了複製到本機,但實際在建置或發行時,並不會到Bin資料夾中

所以必須手動去 C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.5 目錄下找到 System.Core.dll,

然後將他放到發行的Bin資料夾中。發行後我的資料夾結構大概是這樣

image

 

接著我把檔案掛在自己架的虛擬機器的IIS上,環境是 IIS6  .NET 2.0 SP1

也請記得把ASP.NET 的版本選 2.0.50727

image

接著執行時,如果遇到下面這樣的錯誤,就是有組件沒有帶到。

image

看看是哪一隻,然後把他補到Bin資料夾下就可以了。

 

補好之後再執行一次,會看到下圖這樣的錯誤。

image

image

這是因為在Web.config中有這麼一段


  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4"
                type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <providerOption name="CompilerVersion" value="v3.5"/>
        <providerOption name="WarnAsError" value="false"/>
      </compiler>

      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4"
                type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <providerOption name="CompilerVersion" value="v3.5"/>
        <providerOption name="OptionInfer" value="true"/>
        <providerOption name="WarnAsError" value="false"/>
      </compiler>
    </compilers>
  </system.codedom>

這一段設定是在指定要用哪個版本的編譯器來編譯,在本機開發時,因為本機上有.net 3.5,因此

不會遇到這個錯誤,但在只灌了2.0的機器上,沒有3.5的csc.exe,因此才會蹦出這個錯誤。

(曾經想嘗試把3.5的csc.exe一起帶過去,但在config中找不到可以設定編譯器路徑的地方,目前看到

的解法是改機碼,將預設的csc.exe換成自己指定的,但...似乎不是個好方法,所以作罷。)

因此請將Web.config中的system.codedom區段註解掉。但,這麼一來,就宣告了在View上完全不能使用

3.5的語法,例如 var 、 擴充方法、匿名物件、甚至Linq 。嗚...一次痛失好多好用的東西。

但除了View上不能用,其他在cs檔裡面都是可以正常使用的。

因為cs檔的東西會先編譯過,所以不受影響。只有在Runtime時期編譯的才會受影響。

(偉榮兄說可以連View一起編譯。不過這部分我還沒去試。)

 

接著再執行一次,會看到找不到網頁的錯誤。

因為IIS6要執行MVC的話,一種是在萬用字源對應程式的地方插入

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll

另外一種就是改Global.asax檔。這邊就假設連IIS都沒辦法自由設定,所以用

修改Route的方式來做。


public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    //這邊我就隨便註冊幾個基本的Route

    routes.MapRoute(
        "NoParameter", // 路由名稱
        "{controller}/{action}.aspx", // URL 及參數
        new { controller = "Home", action = "Index" } // 參數預設值
    );

    routes.MapRoute(
        "Null", // 路由名稱
        "", // URL 及參數
        new { controller = "Home", action = "Index" } // 參數預設值
    );
}

接著網址用 http://localhost/Home/Index.aspx 執行,還是會出錯!

這就是前面說的,因為Runtime時是不能用3.5的語法的,而RenderPartial與ActionLink都是屬於擴充方法,

因此只能忍痛跟他們說再見了。

image

接著拿掉之後再執行一次,就成功的看到畫面啦!可以看到我機器上的確是只有.Net 2.0

image

如果想直接用http://localhost 這個網址就看到頁面的話,必須在專案中的根目錄中

加入一個Default.aspx的頁面,並且IIS也要有Default.aspx的預設文件(通常都會有)

在Default.aspx的Page_Load事件中寫上下面這段Code,將Request丟給MvcHttpHandler去處理。


protected void Page_Load(object sender, EventArgs e)
{
    HttpContext.Current.RewritePath(Request.ApplicationPath);
    IHttpHandler httpHandler = new MvcHttpHandler();
    httpHandler.ProcessRequest(HttpContext.Current);
}

這樣就大功告成啦。

雖然上面寫的步驟有點凌亂,但其實不會很難。基本上就

  1. 所有.net 3.5的組件都要一起發行
  2. 必須是 .Net Framework 2.0 SP1
  3. Web.config內的system.codedom必須拿掉。並且在Runtime時期不能使用3.5的語法
  4. 修改IIS的萬用字元、或是Global.asax裡的Route

大概就是這樣了。

 

這篇寫的步驟可能有點快,因為我想會這樣玩的人,應該多少都有碰過MVC了,因此

基本的MVC專案建立我就沒有太多著墨,比較著重在除錯及佈署的部分。如果看了有疑問

或是發現我有哪個地方觀念或名詞講錯的,也麻煩用回應告知一下囉。

 

附上測試時的專案檔,可以在.net 2.0 sp1上執行。

測試專案