[ASP.net/IIS] 多個網站併成同一個WebSite專案開發、部署技巧

[ASP.net/IIS] 多個網站併成同一個WebSite專案開發、部署技巧

在進入正題前,先回顧一般情況下,如果有一個案子,須同時開發二個以上的網站

通常大概這樣做……(以下以WebSite專案當範例)

建立第一個WebSite,架構如下:

image

Comman.cs是所有WebSite都會用到的共同邏輯

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


public class Comman
{
	public Comman()
	{
		
    }

    public string getBanner()
    {
        return "廣告輪播 by AdRotator控制項";

    }
}

images/demo.png是第一個網站自己擁有的圖片資源(相對路徑)

index.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>第一個網站的首頁</title>
</head>
<body>
    <form id="form1" runat="server">
      <img src="images/demo.png" alt="Shadow與愉快的程式" />
    </form>
</body>
</html>

index.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Configuration;

public partial class index : System.Web.UI.Page
{
    string Conn_E = WebConfigurationManager.ConnectionStrings["Conn_E"].ConnectionString;//資料庫連線字串
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Write("Shadow1的網站,做Shadow1的事情..." + "<br/>");
        
        Comman com = new Comman();

        Response.Write(com.getBanner() + "<br />"); 
        
        Response.Write("連線字串:" + this.Conn_E);
    }
}

執行首頁結果:

image

再建立第二個WebSite:

image

Comman.cs是所有WebSite都會用到的共同邏輯

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


public class Comman
{
	public Comman()
	{
		
    }

    public string getBanner()
    {
        return "廣告輪播 by AdRotator控制項";

    }
}

images/demo.png是第二個網站自己擁有的圖片資源(相對路徑)

index.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>第二個網站的首頁</title>
</head>
<body>
    <form id="form1" runat="server">
      <img src="images/demo.png" alt="Yahoo奇摩" />
    </form>
</body>
</html>

index.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.Configuration;

public partial class index : System.Web.UI.Page
{
    string Conn_E = WebConfigurationManager.ConnectionStrings["Conn_E"].ConnectionString;//資料庫連線字串
    protected void Page_Load(object sender, EventArgs e)
    {
        Response.Write("Shadow2的網站,做Shadow2的事情..." + "<br/>");
        
        Comman com = new Comman();
        Response.Write(com.getBanner() + "<br />");
  
        Response.Write("連線字串:" + this.Conn_E);
    }
}

執行首頁結果:

image

以上都是舉比較簡單的例子,如果WebSite有第三個、第四個……以此類推

這邊分享一下個人經驗,那時候我一個人維護4x個網站,架構都是這樣,一個WebSite有自己的Web.config,有自己的App_Code

但事實上那4x個網站的Web.config檔幾乎一模一樣,連線字串一樣,SMTP_SERVER設定一樣…

App_Code裡共同邏輯的類別檔也都一樣

有天客戶承辦人一聲下令,所有網站應該要像http://malsup.com/jquery/cycle/ ,廣告輪播Banner要能夠自己輪播,不要畫面重整一次才撈新的圖片

呃…( ̄▽ ̄|||),後來我先改其中一個WebSite的Comman.cs檔

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;


public class Comman
{
	public Comman()
	{
		
    }

    public string getBanner()
    {
        return "廣告輪播 by jQuery";

    }
}

然後改完的Comman.cs檔就Copy-Paste貼到其他4x個WebSite的App_Code底下覆蓋

因為是遠端連線到客戶那邊的機器作業,所以光是Copy-Paste就花了我一個上午的時間

 

而且這種需求常常發生,導致我在思考,是不是哪天應該把App_Code底下共同邏輯的CS檔改成WebService的方式?

但改成WebService的方式,其他index.aspx.cs的程式碼就一定也要跟著改呼叫方式,以4x個網站來說,真是浩大工程…

 

經過此次的教訓,後來開發的新專案

我整理出一種

各網站可以共用Web.config檔,也可以共用App_Code,各網站自己的圖片資源還是歸自己,正式上線時的DomainName對應仍對應各自自己的網站

以User角度來看會覺得是多個網站,以Developer角度來看其實只有一個WebSite專案

重點是會這麼做,一切都是為了維護方便

請看以下建立步驟:

先在檔案總管新增一個資料夾

Step 1. shadowAll

image

Step 2.把共用的檔案全複製到此資料夾裡(Web.config、App_Code)

image

Step 3. 把剛剛建立的兩個WebSite資料夾也搬到此資料夾內

image

Step 4.把那兩個WebSite裡重覆的檔案都刪除

image

Step 5.開Visual Studio先執行shadow1和shadow2內的index.aspx看看有沒有問題

image

shadow1的index.aspx執行結果:

image

shadow2的index.aspx執行結果:

image

看起來沒問題

至目前為止多個網站併成同一個WebSite專案到這邊告一段落,如果客戶的要求會更改到共同邏輯的話,這次只要改一遍

全部資料夾裡的程式大家都一起套用,就不用再Copy-Paste 40幾次了

 

再來是部署上線問題

各網站自己的圖片資源還是歸自己:由於各資料夾裡的圖片路徑都是採用相對路徑,所以此部份不用擔心

正式上線時的DomainName對應仍對應各自自己的網站

 

部署環境Window 7 (IIS7.5)

shadow1資料夾對應DomainName:shadow1.no-ip.info

shadow2資料夾對應DomainName:shadow2.no-ip.info

Step 1.先在IIS裡,新增一個shadow1的站台

image

Step 2. 再新增一個shadow2的站台,請注意兩個站台的實體路徑指到同一個「shadowAll」資料夾(因為都在同一個WebSite專案)

image

接下來是重點!

為了達到「正式上線時的DomainName仍對應各自自己的網站」此條件

先確認shadow1和shadow2資料夾底下都有index.aspx

Step 3. 在shadowAll網站根目錄下新增一個index.aspx程式

image

此index.aspx負責做導向動作,所以UI端不寫Code

 

index.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

public partial class index : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (Request.Url.AbsoluteUri.Contains("shadow1.no-ip.info"))
        {
            Response.Redirect("shadow1/index.aspx");
        }
        else if (Request.Url.AbsoluteUri.Contains("shadow2.no-ip.info"))
        {
            Response.Redirect("shadow2/index.aspx");

        }
        else
        {
            Response.Redirect("shadow1/index.aspx");
        }
    }
}

Step 4. 回到IIS,確認shadow1和shadow2兩個站台的預設文件都是index.aspx且在最上面

image

image

Step 5. 測試&執行

在瀏覽器URL輸入http://shadow1.no-ip.info,執行結果:

image

在瀏覽器URL輸入http://shadow2.no-ip.info,結行結果:

image

執行起來沒問題,部署完成。

 

接著要測試幾種情況,看看這種開發方式經不經得起考驗

1.假設shadow1資料夾底下的index.aspx有兩個超連結,一個另開視窗連到http://www.google.com.tw

一個則是相對路徑連個另一資料夾的second.aspx程式

 

index.aspx

image

 

other/second.aspx.cs

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="second.aspx.cs" Inherits="shadow1_other_second" %>


<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
     <h1>你來到second.aspx了</h1>
    </form>
</body>
</html>

 

在URL輸入:shadow1.no-ip.info

image

點選第一個超連結:

image

正常。

接著再點選第二個超連結:

image

也正常。所以超連結這部份測試OK

 

2.再假設一種情況,我見過有些人會把圖片的URL寫成<%= 網站URL %>資料夾/images/圖片.jpg

這裡就利用shadow1/index.aspx做示範,先看Web.config設定

<?xml version="1.0" encoding="UTF-8"?>


<configuration>
  <appSettings>
    <add key="shadow1Url" value="http://shadow1.no-ip.info/"/>
    <add key="shadow2Url" value="http://shadow2.no-ip.info/"/>
  </appSettings>
  <connectionStrings>
    <add name="Conn_E" connectionString=".\sqlexpress;Initial Catalog=NorthwindChinese;Integrated Security=True" />
    
  </connectionStrings>
    <system.web>
        <compilation debug="false" targetFramework="4.0" />
    </system.web>
    <system.webServer>
        <defaultDocument>
            <files>
                <add value="index.aspx" />
            </files>
        </defaultDocument>
    </system.webServer>

</configuration>

然後shadow1/index.aspx.cs裡宣告

    protected string shadow1Url = WebConfigurationManager.AppSettings["shadow1Url"];
    protected string shadow2Url = WebConfigurationManager.AppSettings["shadow2Url"];

接著shadow1/index.aspx,兩個設定都讀讀看

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="index" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>第一個網站的首頁</title>
</head>
<body>
    <form id="form1" runat="server">

      <img src="<%= shadow1Url %>shadow1/images/demo.png" alt="Shadow與愉快的程式" />
      <img src="<%= shadow2Url %>shadow1/images/demo.png" alt="Shadow與愉快的程式" />


    </form>
</body>
</html>

執行結果:

image

兩張圖片都正常顯示出來(因為兩個DomainName都對應到同一個WebSite專案)

不過這邊個人建議shadow1資料夾裡的程式,為了避免造成維護上的困擾,請儘量使用shadow1對應的DomainName:shadow1.no-ip.info

 

 

 

以上不管怎麼測,跑起來功能都和 多個獨立WebSite專案相同,但在維護性方面,只有一個WebSite專案當然是比較好維護

而且到部署上線階段,客戶想把多個網站當做一個網站,只給一個DomainName

或客戶想要多個網站各自擁有自己的DomainName

用這種開發方式都足以應付,如此好用的技巧分享給大家^_^