2011年9月28日

SQL Server Compact 的好夥伴 SQL Server Compact Toolbox

2012/11/2 更新 現在,如果是要進行本地端的資料庫程式開發,建議大家可以使用LocalDB,關於LocalDB的文章可以參考Terry哥的這篇

至從SQL Server Compact 4.0出現了以後,SQL Server Compact開始支援ASP.NET Web的開發,也可以輕易地在Visual Studio去做管理的動作,而不需要再裝SQL Server Express,甚至是SQL Server;如還沒安裝,可以參考這篇

但原本的Visual Studio內建的管理還是有限,所以這邊推薦一個Visual Studio的外掛,讓你管理起SQL Server Compact更加方便。

安裝

我們可以從Visual Studio裡面的工具選項,然後選擴充管理員。

image

然後第一步選擇左邊的線上圖庫,然後於右邊的框框打上Compact,接下來,並可以找到SQL Server Compact Toolbox,安裝完成後需要重新啟動Visual Studio。

image

重開後,我們可以從伺服器總管的地方看到新圖示,這就是SQL Server Compact Toolbox。

image

以下就是SQL Server Compact Toolbox的管理介面。

image

將SQL Server上的資料轉到SQL Server Compact

假設今天我們已經在SQL Server上面寫了一些Table,想要把他轉移過來,就可以選擇此選項,此選項會連到SQL Server,並輸出給SQL Server Compact 專用的SQL檔案,最後再由SQL Server Compact Toolbox 的 SQL Editor工具來執行。

image

打開後,就是很常見的連線視窗,設定完後,就可以輸出。

image

選擇目的地。

image

接下來,我們打開Open SQL Editor。

image

接下來,使用Opne打開剛剛存的檔案,選取後,會在下面出現SQL語法,然後我們按下Execute來執行。

image

完成後,我們就可以發現北風資料庫的資料全部都匯進來了。

image

其他

其實他還有許多功能,例如將目前的SQL Server Compact匯出成SQL給其他的SQL Server使用,或是直接將此SQL Server Compact的db轉成Entity Data Model至專案。

image

總結

這個工具彌補了原本Visual Studio的不足,讓我們來使用SQL Server Compact更加的方便,在這裡推薦給大家。

參考資料

  1. http://sqlcetoolbox.codeplex.com/

開發程式的好夥伴SQL Server Compact

2012/11/2 更新 現在,如果是要進行本地端的資料庫程式開發,建議大家可以使用LocalDB,關於LocalDB的文章可以參考Terry哥的這篇

SQL Server Compact是輕量化的嵌入式SQL Server,非常的小,也不吃啥資源,但是3.5版本的時候不能拿來開發ASP.NET Web專案,也不能利用於Visual Studio的add new item方法將DB加入至專案,但這樣輕量的東西,不能來用太可惜了,所以Will保哥Demo大大這邊使用了一些方法,來讓SQL Server Compact 3.5能順利使用。

但到了SQL Server Compact 4.0版,就不一樣了,SQL Server Compact 4.0正式支援Visual Studio和ASP.NET Web,而且官方也正式公布Visual Studio 2010 SP1的SQL Server Express最佳替代方案就是SQL Server Compcat 4.0。

Starting in Visual Studio 2010 Service Pack 1, an alternative to SQL Server Express is SQL Server Compact, which offers greater ease of deployment for Web projects. For more information, see Walkthrough: Working with SQL Server Compact in Visual Studio.

2011/10/3 經過測試,目前只有Web 的專案可以正常的找到SQL Server Compact 4的Data Provider,所以如有配合Entity Framework 4,且習慣將Model放到Class Library Project ( 類別庫專案 )的人,不建議使用。

既然那麼推薦,我們就來試試看吧,首先要安裝SQL Server Compact 4.0,這裡依樣,我們使用Web Platform Installer這個超級方便( 懶人專用 ) 工具來安裝,不會用的可以參考這篇,這裡選擇Microsoft SQL Server Compact 4.0和Microsoft Visual Studio 2010 SP1 Tools for SQL Server Compact 4.0兩項,因為我已經安裝完了,所以狀態是Installed…

image

接下來很快地安裝完成,我們就可以打開Visual Studio 2010來試試看,假設我們今天的ASP.NET MVC專案要使用到這個資料庫,我們就可以在App_Data的資料夾下面新增項目。

( 如果沒有App_Data資料夾,可以自行新增 )

image

接下來,我們選擇SQL Server Compact 4.0 本機資料庫。

image

完成後,就可以在App_Data底下看到此資料庫。

image

接下來,我們就可以在伺服器總管進行資料庫的管理,例如建立Table。

image

這是一個很輕量的資料庫,我覺得很適合我這種帶著筆電跑,到處都可以來開發一些小程式,或是Demo一些程式來使用,當然也很適合開發ASP.NET Web等等,大家有機會也可以裝起來試試看喔!

參考資料

  1. http://blog.miniasp.com/?tag=/sql+server+compact
  2. http://demo.tc/Post/488
  3. http://207.46.16.252/zh-tw/library/dd692930%28SQL.10%29.aspx
  4. http://msdn.microsoft.com/zh-tw/library/ms247257.aspx

UI的設計模式MVP模式 - Passive View

最近我朋友問了我一個問題,MVP和MVC架構有甚麼不一樣,我只很簡單的回答,MVP比較運用於Win Form、ASP.NET這種有狀態的程式,而MVC運用於無狀態的應用程式;事過幾天後,我還是覺得,這個問題很不錯,但因沒有好好地回答感到遺憾XDD,雖然現在網路上也有很多的"VS”了,但我還是決定把這一些模式敘說一次。

為什麼要有MVP模式?

其實MVP模式是MVC模式演進而來的,也可能MVC剛出來的時代,網路還沒開始發展,所以MVC不適用於Win Form這類程式架構,而衍生出MVP模式;但不管怎樣,他們要解決的問題,原因都相同,都是原本的架構不易測試,耦合太高,關聯太複雜,所以使用這些模式來解決這些問題,總之,測試是很重要的=w=。

斯斯有兩種,MVP也有兩種

老實說,我也不是考古團隊,我也沒有仔細的去翻歷史,但據我所知,MVP設計模式是有分兩種,最先提出來的是Martin Fowler,最後於2006年將MVP分成Supervising Controller和Passive View;基本上這兩個的概念是相同的,但最大的差別只在於那個"P" ( 也就是Presenter ),Presenter能控制的東西程度不同罷了,而這次的主題就是其中一個MVP模式Passive View。

Passive View

首先,既然是MVP還是要說明一下這三個字的縮寫,分別為Model、View、Presenter,翻成中文,大概也就是模型、視圖、主講者!? ( 好吧,我還是用英文Presenter好了… ) ,以下是他的圖。

image

如果要說MVP的Passive View,最簡單的講法就是Model與View是完全沒溝通的,也就是說Presenter有絕對的控制權( 控制控阿!! )。

正式開始

自從上次講了MVC架構後,發現與其一開始說那麼多,大家還是聽不懂,還不如直接先給範例,就如比古清十郎所說的,從實戰中學習吧!劍心~。

假設今天我們要用ASP.NET寫一個查詢程式,非常非常簡單的查詢,只要輸入,名子,就會尋找到指定的資料,並且顯示於下方,畫面大致上是這樣。

image

啥!?很醜!!,範例嘛,就不要太苛求了,總之,就是在TextBox輸入名子,按下Button後,會在下面兩個Label顯示姓名和地址…

image

 

程式碼大概長這樣。

我們會先有一個User的類別,內容很簡單,就兩個屬性,名子和地址。

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

namespace WebAppMvpDemo
{
    public class User
    {
        public string name { get; set; }
        public string address { get; set; }
    }
}

接下來,我們實作一下存取User的類別,簡單的說,要存取User都是透過這個類別來和底層的資料傳遞;當然,既然是範例,就沒有和真實的資料庫做一個交流,也只是很單純的定義一個方法GetByName,且當輸入Sky的時候,就會傳回一個User物件回來;如果是正式的環境,我們這裡可能使用SQL存取,也可能使用ORM技術存取。

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

namespace WebAppMvpDemo
{
    public class UserRepository
    {
        public User GetByName(string userName)
        {
            //作假資料,如果搜尋到Sky,就new一個新的user回傳。
            if (userName == "Sky")
            {
                User user = new User();

                user.name = "Sky";
                user.address = "台中";
                return user;
            }
            return null;
        }
    }
}

接下來,是視覺的頁面,這頁沒甚麼,就很一般,把一些東西拖拖、拉拉,就好了,頁面有點長就是了。

<%@ Page Title="首頁" Language="C#" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebAppMvpDemo._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="Form1" runat="server">
    <div class="page">
        <div class="header">
            <div class="title">
                <h1>
                    MVP架構測試
                </h1>
            </div>
        </div>
        <div class="main">
            <div>
                <h2>歡迎使用 ASP.NET!</h2>
                <p>此為MVP架構測試。</p>
            </div>
            <div>
                <asp:TextBox ID="SearchUserTextBox" runat="server"></asp:TextBox>
                <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
           </div>
           <div>
                <asp:Label ID="UserNameLabel" runat="server" Text="Label"></asp:Label>
                <asp:Label ID="UserAddressLabel" runat="server" Text="Label"></asp:Label>
           </div>
        </div>
    </div>
    </form>
</body>
</html>

接下來是主要的程式碼,基本上就是在處理Button的Click事件,我們會先把剛剛寫好,專門用來存取User類別的UserRepository類別建立起來,來方便我們存取User,然後使用UserRepository的GetByName方法來尋找使用者;當然,事前會稍微做一些簡單的判斷,看看是不是空值之類的;

( 關於資料存取,這種做法是"比較"好一點的作法,通常我們會設計一個介面,來降低與UserRepository的耦合,這才是Repository模式的做法,不過這邊為了敘述方便,就不透過介面了,看不懂的人也沒關係,可以先跳過;此外,本來還想直接寫SQL在Click事件裡面,但想到這樣還要準備資料庫,發現更累XDD,所以最後還是用這種方法來Demo,而SQL散落於世界各地的寫法,其實是最不好的寫法,不過我以前公司幾乎都是這樣寫就是了XDD )

從UserRepository會吐回來User物件,然後我們把值顯示於ASP.NET 控制項,就完成了這簡單的Demo。

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

namespace WebAppMvpDemo
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            UserRepository userRepository = new UserRepository();
            if (string.IsNullOrEmpty(SearchUserTextBox.Text))
            {
                return;
            }

            User user = userRepository.GetByName(SearchUserTextBox.Text);
            if (user == null)
            {
                return;
            }

            UserNameLabel.Text = user.name;
            UserAddressLabel.Text = user.address;
        }
    }
}

沒錯,這幾乎就是一般的ASP.NET 開發的寫法,雖然比asp好太多了,但還是耦合得太緊,沒辦法測試,如果要測試的話,還是必須開啟網頁,填填看TextBox,然後按下Button,其次就是維護也不容易,所以接下來,我們來把這個範例改成MVP的Passive View試試看。

首先,我們先處理Model的部分,但其實,Model我們早就已經寫好了,也就是User這個類別,而這個類別改成MVP的Passive View架構,其實也不需要做變動,但是Repository模式的這個部分還沒做好,我們先定義一個介面IUserRepository。

( Repository模式和MVP Passive View模式,兩者之間並不是必須,也就是說,今天我實作MVP Passive View,是可以不用做Repository模式的,但Repository模式可以讓整個資料層分離的更好,所以就一起講吧=w= )

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebAppMvpDemo
{
    public interface IUserRepository
    {
        User GetByName(string userName);
    }
}

然後裡面再實作這個介面;不過剛剛我們已經先做好了,也就是UserRepository,其實這邊的程式碼和之前的UserRepository沒甚麼差別,唯一的差異只有UserRepository實作IUserRepository,也就是這行。

public class UserRepository : IUserRepository

以下是UserRepository完整的程式碼。

( 為什麼要做一個介面?其實原因很簡單,就是為了方便我們測試時抽換,只要有實作此介面的實體,就可以輕易地去抽換掉,後面會繼續講解。 )

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

namespace WebAppMvpDemo
{
    public class UserRepository : IUserRepository
    {
        public User GetByName(string userName)
        {
            //作假資料,如果搜尋到Sky,就new一個新的user回傳。
            if (userName == "Sky")
            {
                User user = new User();

                user.name = "Sky";
                user.address = "台中";
                return user;
            }
            return null;
        }
    }
}

好的,完成了以後,接下來我們來實作View的部分,那View在哪裡?,以我這邊的範例,頁面是Default2.aspx,所以,View就是Default2.aspx和Default2.cs檔。

而在準備View之前,也必須先準備好Interface,"IDefault2DetialView”,然後裡面定義了SearchUser、UserNmae、UserAddress三個必須實作的方法,其實這三個方法,對應的就是SearchUserTextBox、UserNameLabel、UserAddressLabel這三個控制項,目的是希望未來透過此方法來存取這三個控制項,也因為我們的程式只需要取得SearchUserTextBox的Text值,和設定UserNameLabel和UserAddressLabel的值,所以裡面也只分別設定get和set。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebAppMvpDemo
{
    public interface IDefault2DetialView
    {
        string SearchUser { get; }
        string UserName { set; }
        string UserAddress { set; }
    }
}

ok~接下來我們要處理Default2.cs了,雖然程式很簡單,但還是很長,而且有很多地方需要注意的,首先,我們會讓此類別( _Default2 )去實作此介面,目的也是一樣,為了降低耦合與測試。而我們也會在這個類別裡面去實作Presenter,目前我們還沒寫到Presenter,但這邊會用到Presenter的原因其實很簡單,因為是由Presenter來控制,如最下面的Button Click所看到,我們沒有將程式寫在_Default2裡面了,而是去呼叫Presenter的OnUserSearched方法;接下來往回看一點,有三個存取控制項的方法,這些方法會回傳或是設定控制項,最後,最關鍵的是new Presenter(this)這段,這段也就是說把_Default2塞到Presenter裡面去,讓Presenter能參照到_Default2,這代表甚麼呢?也就是說,Presenter可以控制到_Default2,所以Presenter裡面不會再有SearchUserTextBox.Text這種和控制項有關的程式碼,而通通都是透過_Default2所定義的方法來取得控制項的資訊,換言之,Presenter和控制項再也無關,View就是View,Presenter就是Presenter,個兼其職。

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

namespace WebAppMvpDemo
{
    //讓此類別實作IDefault2DetialView
    public partial class _Default2 : System.Web.UI.Page ,IDefault2DetialView
    {
        //目前還沒寫到此類別。也就是MVP的P
        private Default2Presenter _presenter;

        protected void Page_Load(object sender, EventArgs e)
        {
            //將自己,也就是_Default2注入到P裡面去,目的是為了讓P能控制View。
            _presenter = new Default2Presenter(this);
        }

        //此類別必須實作IDefault2DetialView定義的方法。
        public string UserName
        {
                //可以看到,這裡就是用來設定控制項。
                set { UserNameLabel.Text = value; }
        }


        public string UserAddress
        {
            set { UserAddressLabel.Text = value; }
        }

        public string SearchUser
        {
            get { return SearchUserTextBox.Text; }
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            //當Click事件發生的時候,不由View處理,而是轉交給Presenter處理。
            _presenter.OnUserSearched();
        }

    }
}

然後我們看一下Presenter,其實Presenter還比較簡單一點,如果你已經看到這邊,恭喜你,快解脫了XDD;Presenter,會定義兩個介面,而利用建構子的方式傳進有實作這兩個介面的物件,換言之,當我們要測試的時候,就可以傳入有實作這兩個介面的物件進來 ( 通常我們使用Mock來做模擬物件 ),而這也是為什麼前面要一直定義介面的關係,就是為了降低耦合,讓測試能更好進行,至於OnUserSearched方法,其實和之前的程式沒有多大改變,就只是進行了資料撈取的動作,只是不會直接寫到控制項裡面去了,而是會透過實作IDefault2DetialView的物件來進行存取的動作,好處就如之前說的,隔離了控制項的部分,讓耦合降更低。

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

namespace WebAppMvpDemo
{
    public class Default2Presenter
    {
        //定義這兩個型別,這也是關鍵,也就是說,我們可以自行去設計並抽換。
        //也因此和資料存取還有View的部分就沒那麼緊密的耦合。
        private readonly IUserRepository _userRepository;
        private readonly IDefault2DetialView _view;

        //這裡的建構子使用一種叫做建構子鍊的方式,
        //但關注的是,我們利用建構子來傳進有實作的介面的物件,
        //換言之,我們可以自行去設計,只要有實作介面即可。
        //( 但是比較建議使用Mock方式,可以再參考我的Blog.... )
        public Default2Presenter(IDefault2DetialView view)
            : this(view, new UserRepository())
        {
        }

        public Default2Presenter(IDefault2DetialView view, IUserRepository userService)
        {
            _view = view;
            _userRepository = userService;
        }

        //這裡定義一個方法,就是當按下Button時,View會進行此方法的呼叫。
        public void OnUserSearched()
        {
            if (string.IsNullOrEmpty(_view.SearchUser))
            {
                return;
            }

            User user = _userRepository.GetByName(_view.SearchUser);
            if (user == null)
            {
                return;
            }

            _view.UserName = user.name;
            _view.UserAddress = user.address;

        }
    }
}

結論

最後,看完了有甚麼感覺,恩,就是程式碼變的很多XDD,我們來重新看一下MVP的Passive View圖

image

就如前面所說,Model ( User ) 完全和View沒有任何關係,取得的Model ( User ),由Presenter塞到View ( _Default2  )裡面去,而從View ( _Default2 )進來的事件,也由Present ( Default2Presenter )來處理,所以Present和Model可以很輕鬆的進行測試,不再需要開啟頁面按下Button,然後看看答案對不對,各單位之間的耦合也沒那麼強烈,它們之間的關係,變得更好維護了!!

後記

這個範例,我忘記把_default2改成比較好的名子,所以一堆相關的命名都是這種沒有意義的Default2,這是不好的習慣喔!!大家不要學習喔!!。

ASP.NET MVC - 什麼是MVC?

還記得當年,第一次看到MVC,是從Java那邊看來的,但是實作,卻是PHP的Zend Framewrok,後來,隨著工作關係,又回到了Microsoft,而也因為工作的關係,整整的經歷過ASP、ASP.NET、ASP.NET MVC,三個跨時代產品XD,所以恐怖的義大利麵也吃過,萬行Fuction包含百行SQL也碰過,不過也不能怪罪於先人,畢竟,幾十年歷史的系統,軟體發展又那麼快,這中間的演變真的很大,當初也沒有什麼比較好的設計方式,所以這也是可以諒解的。

隨著時間的演進,程式設計也像神奇寶貝一樣,會開始超進化,只不過不是程式自己進化,而是許多偉大的程式設計師在撰寫程式時,發現了許多的問題,於是提出好的設計架構,而MVC就是其中一個。

還記得第一段提到的義大利麵程式碼嗎?在解釋MVC之前,先解釋一下義大利麵程式吧,所謂的義大利麵程式碼,就是一隻程式裡面,包山包地也包海,最有名的大概就是ASP吧,HTML包在裡面,JavaScript包在裡面,CSS包在裡面,還有一堆邏輯也包在裡面,別忘了,還要加一下配料SQL….;維護過的人就知道,光是要拆解,就費勁功夫了,忍痛改完,就算驗證過,還是常常發生一堆錯誤,然後又進入這可怕的循環;記得以前在公司,有好幾支這種地雷,每次有需要動到這些地雷的時候,大家覺得都會唯恐避之不及。

後來出了ASP.NET,我只能說,微軟真的是封裝得太棒了,能把整個技術封裝成這種程度,讓人開發網頁像是開發Win Form程式一班,而且針對視圖與邏輯也有一定程度的拆解,但隨著時代的轉移,現在越來越標準的HTML、CSS,還有AJAX的崛起,測試的重要性等,也讓ASP.NET的一些缺點暴露出來,如下:

  1. 傳輸過於笨重
  2. 複雜的HTML
  3. 不可測試性

ASP.NET是利用View state來處理整個生命週期,但View state實在是太重了,而且生命週期也太過複雜,PostBack到最後都不知道在做甚麼,對高手來說,可能沒有此困擾,但對於新手來講,這反而是一個開發上的一個隱憂,此外因View state過大,傳遞也會浪費許多的時間,雖然現在隨便就幾百Mb,但不可否認的,如果是大型網站,還是必須將此考量進去。

其次就是分離觀點的問題,ASP.NET變成在後端去控制前端元件,這在測試上,也是另外一種困擾,因為這樣子就很難單獨的測試到邏輯。

最後,用過ASP.NET的人都知道,很少人會自己寫標準的HTML在ASPX頁面,幾乎都是利用拖拉元件方式,並使用這些元件,而這也會形成另外一個問題,由ASP.NET產生出來的html,擁有複雜的id,而且可能不是標準的html。

當然這些問題隨著ASP.NET 4的發佈,也慢慢地改善,但畢竟先天就是這樣子了,後天再怎樣改善,還是沒辦法改到根本。

通常講到這,就一定會有人詢問,那ASP.NET就完全沒用了嗎?要被淘汰了嗎?其實Microsoft也說過,ASP.NET 還是會持續維護,而且在實際的應用上,ASP.NET還是很好用,像我們以前必須要非常快速的開發一個一兩頁的小程式,我們就很喜歡用ASP.NET快速的處理完畢,甚至有一些是拋棄式的網頁,我們也喜歡用ASP.NET快速開發;對的地方用上對的工具,才是最重要的,你說是吧!

拉哩拉哩的說了一堆古,MVC都還沒帶出來哩,這邊我們就隆重的介紹一下MVC吧,MVC是一種軟體架構的設計樣式,不只是微軟有用,PHP裡面也有許多的Framewrok來實作MVC架構( 例如Zend Framework ),連Flash也有MVC架構,而微軟實作MVC的產品,就叫做ASP.NET MVC。所以MVC是一個軟體架構的設計樣式,ASP.NET MVC是微軟實作此架構的名詞。

而MVC是由以下三個單字的第一個字母所組合而成的。

  1. Model – 資料、商業物件。
  2. View - 視圖,包含畫面、顯示的邏輯。
  3. Controller - 控制整個運作的流程。

若把它拆解開來,HTML、CSS、JavaScript等,就是屬於View,他負責顯示那些畫面,也負責處理畫面的邏輯,所以你不會在上面看到一堆SQL,但你還是會看到一些關於顯示上的邏輯。

而那些商業物件,就是Model,你可以把他當作是資料,但實際上,他應該是一種擁有商業邏輯方法的物件。

而Controller就是控管整個流程,他會控管接下來的路要怎麼走;當然也可以將SQL塞到Controller裡面,但是非常不推薦;Controller應該定義的是處理的步驟,但細節的資料庫存取,或是商業邏輯,因該要拆分到其他各自負責的物件去( 例如Repository、或是Model等 )。

說到這邊,可能已經湖煞煞了,但是沒關係,這邊只是給個觀念,後面會比較詳細的說到,現階段只要知道View是畫面,Model是資料,Controller是流程就可以了。

這裡有一張MVC,三個之間的關係。

image

所以我們可以發現,Controller會相依於Model和View,因為Controller要將Model取回,並傳遞給View,而View因為要顯示Controller傳過來的Model,所以相依於Model,而Model則可以完全獨立;也因此,MVC這種架構,大大的降低偶合,並提高了內聚力,所以MVC最大最大的優點就是可以很輕鬆的拆解,並且彼此可以獨立開發,測試達到關注點分離的設計境界。

所以當一個Team,可以有人專注於開發Model,有人專注的開發View,有人專注地開發流程,並且在測試的時候,獨立進行,這部分就是ASP或是ASP.NET比較難做到的事情了。

(要測試ASP.NET的一個按下按鈕的功能,然後不要用到View….老實說,真的是有點困難… )

所以,所謂的MVC,就是將原本混再一起的東西,做了拆離,讓我們能專注的處理每個部份。

提到這邊,有人會開始詢問到,MVC不就是三層式架構嗎( 3-Tier )?

早期的多層式架構,是應用於Server的溝通上面,因一台Server效能的瓶頸,或是維護上的問題,所以拆成多層來處理;後來開始有人將此概念延伸到軟體層上,3-Tier是將軟體分為展示( UI ),邏輯 ( BI ) , 資料存取( DA )等;的確,對應上看起來的確很像MVC,但我必須強調,N-Tier不等於MVC,因為MVC是實作於展示層的設計樣式,所以不要把N-Tier和MVC混為一談,也不要一直想著怎樣對應,因為兩者是講不同的東西。所以N-Tier和MVC不相等,也不要想著怎樣去對應。

接下來,我們知道這三個東西後,現在我們用一個簡單的登入系統來看看,他的流程是怎樣跑,第一步當然是先在瀏覽器上打上網址,假設是index好了,後面的程式收到你的訊息後,第一個動作的是Controller,Controller根據你打的網址,並會知道要傳怎樣的View給你看,而你看到畫面上有id和pw欄位需要輸入,並輸入進去後,按下送出,View就會將你輸入好的東西( Model )送回到Controller去做處理。

( 這裡補充一下,原則上,過程是很複雜,但有些東西是後面才會提到,所以上面敘述的是非常簡易的版本,讓大家先有一點感覺。理論上我們會先建立客戶這個物件當作Model,在輸入完index此頁面的時候,Controller並會吐回一個View給使用者,而這個View並會使用客戶這個Model,當使用者填完id、pw的時候,並會將此資料塞到客戶這個Model,並傳回Controller,Controller會再利用Repository此樣式去做資料庫的存取,來驗證是否正確,如果正確就導向到正確頁,如果錯誤就導向到錯誤頁。 )

基本上,整個MVC的流程大致上就是這樣,其實MVC這個Patten,就是來解決原本複雜的交互依賴問題,而利用了MVC進行拆離,來提高整體的維護,在ASP.NET MVC推出後,我們也實作了許多案例,無論是在開發上的清晰度,或是後續的維護,合作等等,都有一種煥然一新的感受,當然,內部同仁也有人抱怨,沒像ASP.NET那樣拖拉的方便、覺得要處理許許多多的東西,但這些其實也只是因為大家不熟悉而產生的抱怨,到後來,大家也都開開心心的活在ASP.NET MVC之中了。

最後,國外的ASP.NET MVC書籍作者給了他一段評言。

It emphasizes clean architecture, design patterns, and testability, and it doesn’t try to conceal how the Web works.

中文的意思是,"它強調簡潔的架構,設計模式,和可測性,它不試圖掩飾如何在Web上的運作"。

沒錯,這就是ASP.NET MVC,後續,我們將開始講解如何開發ASP.NET MVC。

2011年9月27日

Windows Azure 底層架構

其實,整體開發上是不需要太深入了解這些東西就可以去在撰寫開發,但我還是覺得,這些觀念是應該要知道的,所以剛剛花了一整個晚上,把Windows Azure的底層架構看過一次,所以稱還沒忘記的時候,趕快把這些記錄下來 ( 我想大概過一陣子我就忘光了吧XDD )。

以下是微軟官方白皮書圖,其實這部分還滿簡單的,簡單的說,就是整個應用程式和Data是建構於Windows Azure之上,然後企業,消費者透過網路來存取。

image

接下來我們針對Windows Azure,進去看他的架構。此圖來自於wiki,其實資料中心的每一台實體的電腦,都會利用VM的方式,虛擬出許多台的虛擬主機,而每一台實體電腦都一定會有一個裝了Windows Azure Host OS的VM,和多個裝了Windows Azure Guest OS的VM,其中Windows Azure Host OS是負責管理這台實體電腦上所有的Windows Azure Guest OS,並進行頻寬控制等等事情。

image

雖然單一的實體機有Windows Azure Host OS進行控管,但別忘了Datacenter中心有那麼多台實體電腦,所以,由數台機器組成的Cluster伺服器群 ( 我們稱為"Fabric Controller" ),而Fabric Controller就負責管理這些龐大的電腦,如下圖。

image

而Datacenter的量那麼大,所以會將Datacenter進行劃分,每一區塊我們稱之為Fault Domain,而Fabric Controller可以控制多個Fault Domain。

最後,Fabric Controller還是要知道每台實體機器裡面VM的狀況,所以Windows Azure Host OS裡面會裝一個Windows Azure Fabric Agent,Windows Azure Fabric Agent會傳回所有的VM狀況給Fabric Controller,讓Fabric Controller來掌控。

所以整體的Windows Azure底層架構大致上是這樣子,當然還有許多更細的細節,大家可以參考以下網站。

參考資料

  1. http://www.microsoft.com/taiwan/windowsazure/whitepapers/default.aspx
  2. http://www.microsoft.com/windowsazure/Whitepapers/IntroducingWindowsAzure/
  3. http://zh.wikipedia.org/wiki/Windows_Azure 

Windows Azure 安裝流程

天空終於與雲相逢了!這是我最近MSN的暱稱,其實是我最近終於比較有空可以開始看一下Windows Azure的書了,所以,天空終於與雲相逢了XDD;雖然開始研究Windows Azure,但真的要部屬上去,老實說價錢還不是我能負擔的起的,但還好,這個時代,模擬就是一切,所以我們還是可以本機模擬雲端環境,讓我這個窮人可以玩一下模擬雲QQ,所以在這邊先把簡單的安裝過程紀錄一下 ( 是真的很簡單… )。

首先還是老樣子,我還是喜歡用Web Platform Installer來安裝東西,因為真的很方便,不知道怎樣用的可以參考這篇

然後選擇Windows Azure Tools for Microsoft Visual Studio 2010…,他就會幫你把需要安裝的東西全部準備好,一口氣裝一裝了。

Install Windows Azure SDK

裝完後,打開Visual Studio 2010看一下,就可以看到雲的專案了。

image

接下來,他會要你選擇Web Role、Work Role,這兩個是Windwos Azoure獨有的,未來在解釋,我們這邊選擇ASP.NET MVC Web Role就好。

image

接下來因為是選ASP.NET MVC 的Web Role,所以會出現要你選擇ASP.NET MVC 的模板,如果不是選ASP.NET MVC 的可以略過。

 

接下來於Visual Studio啟動看看吧;接下來他會把模擬器Run起來,老實說,還滿久的,可能我電腦慢吧,但實際部屬會更久,所以測試是很重要的 ( 此測試不是run起來看看有無錯誤的測試,而是指Unit Test的測試 );此外,第一次執行的話,他還會針對資料庫做一些設定。

image

Run起來後,右下角也會出現模擬器的圖樣,其實和IIS模擬器很像。

image

我們也可以利用右下角的模擬器圖示打開Storage Emulator和Windows Azure Compute Emulator。

其中,Storage Emulator是模擬雲端儲存體的部分。

image

Windows Azure Compute Emulator是模擬Role的運行狀況,簡單的說,就是程式的運作狀況。

image

完成後,我們又可以在網頁上面看到熟悉的頁面XDD

image

基本上,準備工作不會很困難,至於實務上的開發部分,模擬器其實幾乎能完整的模擬環境了;最後,補上一句Ruddy老師所說的:

程式開發人員才是這場雲端運算之爭的主角!
所以還在等什麼呢!?,趕快下載來開發吧!!

2011年9月26日

ASP.NET MVC Controller 和 Action

當使用者Keyin網址後,瀏覽器送出請求,而透過Routing機制後,緊接著的就是Controller,就如前面MVC架構所敘說的,Controller控制著所有的流程 ( 不然他怎麼會叫做Controller!? ),取得Model、決定View,這些工作都是在Controller裡面進行,我們先看一下簡單的Controller吧。

假設網址是 blog.sanc.idv.tw/home/index

( 這個網址沒有打錯喔,還記得前面講的嗎,MVC的網址和以前我們熟悉的index.html這種檔案式的架構不同,所有的網址要求,會透過Routing重新轉送。 )

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

namespace MvcWebRole1.Controllers
{
    //HomeController代表著blog.sanc.idv.tw/Home <--這個路徑
    public class HomeController : Controller 
    {
        //這個Function代表著blog.sanc.idv.tw/Home/Index <--這個路徑
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            return View();
        }

        public ActionResult Contact()
        {
            return View();
        }
    }
}

所以,blog.sanc.idv.tw/Home對應到的是一個類別,也就是HomeController這個類別,而blog.sanc.idv.tw/Home/Index對應到的是HomeController這個類別的Index這個方法,裡面我們還可以看到About、Contact,其實也分別會對應到blog.sanc.idv.tw/Home/About和blog.sanc.idv.tw/Contact這兩個路徑。

所以我們可以知道,當瀏覽器請求進來的時候,就會到對應的Controller裡面,對應的Function來做指定的事情,而這個Function在MVC裡面,我們又稱為Action,( 所以未來我會用Action來稱呼 )。

到這邊,我們算是複習複習之前講的,接下來我們在繼續往下看看Controller和Action。

ActionResult

我們將Controller的其中一個Action拉出來看一下。

public ActionResult Index()
{
    return View();
}

我們可以看到,這個Action的回傳值是一個ActionResult型別,其實這是一個抽象型別,最後一行的return View();,其實會回傳一個ViewResult型別,而這個型別就是繼承於ActionResult型別,最後,Controller就會利用取得的這個ActionResult裡面的ExecuteResult方法,將畫面 ( 或是其他結果 )傳回使用者端。

既然ActionResult是抽象型別,也就表示會有很多的類別繼承於他,接下來,我們會開始介紹型別。

ASP.NET MVC 3 可用的ActionResult的型別

下面是可用的型別列表,後續會一個一個寫上範例,Controller Helper Methods代表的是可以讓我們快速地去使用,例如return View();的View(),他就會產生一個ViewResult型別出來。

型別 簡介 Controller Helper Methods
EmptyResult 甚麼事都不做…
ContentResult 回傳文字至瀏覽器,可以自行設定content-type。 Content
FileResult 回傳二位元資料,例如Server上的mp3等檔案。 File
ViewResult 呈現指定或是預設的View。 View
PartialViewResult 呈現指定或是預設的View樣板 PartialView
RedirectToRouteResult 如果產生HTTP 301、302則會重新導向到另外一個Action或是其他指定的URL、或是設定好的Router。

RedirectToAction
RedirectToActionPermanent
RedirectToRoute
RedirectToRoutePermanent

RedirectResult 如果產生HTTP 301、302則會導向至另外一個URL。 Redirect
RedirectPermanent
JsonResult 將.net 物件序列化成Json格式並回傳。 Json
JavaScriptResult 回傳一個JavaScript的程式碼片段,通常用於Ajax裡面。 JavaScript
HttpUnauthorizedResult 回傳HTTP 401 ( 未授權 )。 None
HttpNotFoundResult 回傳HTTP 404。 HttpNotFound
HttpStatusCodeResult 返回指定的HTTP代碼。

jQuery Mobile 介紹

自從行動裝置市場越來越大,上網也越來越快,智慧型手機越來越多,我們也可以確信Mobile已經是下一代的平台了,從早期的Desktop App時期到Web App時期,到現在的Mobile App時期,老實說,時代進步的也太快了吧,才幾個年頭,各種開發方式的轉換,就已經讓我快死在沙攤上了。

在談論jQuery Mobile前,不免其俗的還是要先簡單的討論一下Mobile裝置的開發方式,當然,這部分網路上已經有非常多地的"vs”,大家可以去搜尋看看,畢竟的主題還是jQuery,所以這邊只稍微的介紹一下;Mobile裝置上的開發目前大致分為兩種,一種是原生App ( Native App ),簡單的說,就是利用該平台上的專用語言寫出針對此平台的專用應用程式,所以這個App也只能在特定的裝置上執行,另外一種雖然也是用專用語言寫 ( 或是直接開Browser keyin網址),但實際運作的時候,是使用Browser來讀取網路上的Web Page,所以核心部分,是可以跨不同的Mobile裝置;但這個界線,我相信,未來也會越來越模糊。

而jQuery Mobile就是為了讓第二種方式 ( 利用Browser來處理 ) 能方便撰寫的一個方案,他為各種不同的Mobile平台提供了統一的UI介面,而且是使用標準的HTML5來處理,讓不同的裝置讀取到此頁面的時候,能夠有個統一的介面,而且也不需要針對不同手機去設計不同的頁面。

( 當然不只限於Mobile裝置,就算是用Desktop的瀏覽器,也可以看到jQuery Mobile展現的效果 )

以下是jQuery Mobile的一些特點:

  1. 使用jQuery核心,所以會和jQuery語法相同,也因此學習曲線不會很長。
  2. 兼容主要的移動和桌面平台 - IOS、Android,黑莓,WebOS,Symbian、Windows Mobile,Firefox Mobile 和所有現代的桌面瀏覽器。
  3. 輕量的大小。
  4. 使用HTML5的標記驅動(Markup-driven)來進行配置,所以只需要撰寫少量的Script,以提升開發時間。
  5. 當發現HTML標記中有使用到HTML5的data-role屬性,將自動初始化此標記。
  6. WAI - ARIA的輔助功能也包括在內,以確保頁面的螢幕閱讀器(例如:VoiceOver in iOS)和其他輔助技術。
  7. 精簡觸控和滑鼠事件,觸控、滑鼠等只需要使用一個簡單的API的方法。
  8. 等等等…

接下來,我們來看看怎樣實作。

Viewport meta tag

<meta name="viewport" content="width=device-width, initial-scale=1"> 

這是一個meta標籤,如果沒有設定此標籤的話,預設會使用"Virtual" Page來顯示,而此Page的大小為900pixels,也就等同於桌面大小了,所以官方建議加上此設定。

設定Pages

在講這個之前,有一個必須要先了解,jQuery Mobile於瀏覽器上的最小單位是"Page",但此"Page”不等同於Web Page,簡單的說,一個Web Page裡面,可能會有多個jQuery Mobile的Page,但經過jQuery Mobile處理過後,於瀏覽器上顯示,只會顯示出一張jQuery Mobile 的Page,這種做法是因為Mobile上的處理速度和傳輸速度都比較慢,而且Mobile所能顯示的大小也比較小,所以jQuery Mobile使用這種方式做處理,而如果要跳到其他Page,則是用錨點的方式去做連結,以下是jQuery Mobile的最小單位,需使用HTML5的data-*的方式來標記"Page”。

<div data-role="page">
    <div data-role="header">我是header</div>
    <div data-role="content">我是content</div>
    <div data-role="footer">我是footbar</div> 
</div>

其次,我們還可以看到"header”`、"content"、"footer",這三個屬性,這也是分別來定義Page的頁首、主文、頁角;基本上,你也可以不使用這三個屬性,但我覺得,至少還是要放一個header和content,呈現出來的會比較沒那麼突兀;以下是使用三個屬性後的效果。

image

接下來展示的是兩個Page的切換,我們使用超連結來連結錨點。

<div data-role="page" id="first">
    <div data-role="header">我是Header</div>
       <div data-role="content">    
        <a href="#second">連結到第二個Page</a>
       </div>
    <div data-role="footer">我是footbar</div>
</div>

<!-- second page -->
<div data-role="page" id="second">
    <div data-role="header"></div>
    <div data-role="content"></div>
    <div data-role="footer"></div>
</div>

image

所以,我們可以看到,雖然這兩個div標籤都是在同一個HTML裡面( body 標籤裡面 ),但透過jQuery Mobile後,一次只會顯示一頁。

最後附上整個頁面的範例程式。

<!DOCTYPE html> 
<html> 
    <head> 
        <meta charset="utf-8" />
        <title></title> 
        <meta name="viewport" content="width=device-width" />
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.css" />
        <script type="text/javascript" src="http://code.jquery.com/jquery-1.6.3.min.js"></script>
        <script type="text/javascript" src="http://code.jquery.com/mobile/1.0b3/jquery.mobile-1.0b3.min.js"></script>
    </head> 
<body> 
    <div data-role="page">
        <div data-role="header">我是Header</div>
        <div data-role="content">    
            <a href="#second">顯示第二個Page</a>
        </div>
        <div data-role="footer">我是footer</div>
    </div>

    <!-- Second Page --> 
    <div data-role="page" id="second">
        <div data-role="header"></div>
        <div data-role="content"></div>
        <div data-role="footer"></div>
</div>
</body>
</html>

這是最基本的jQuery Mobile設定,jQuery Mobile提供了讓不同裝置的瀏覽器顯示出同樣的頁面效果,來達到跨平台的目的,但有的時候,我們需要使用到一些Mobile裝置上的功能( 例如:定位 )等等,這時候有另外一套Framework可以玩玩看PhoneGap,他能HTML5這些東西轉換成Native App,並且可以和jQuery Mobile做很好的整合,未來如果有機會,再和大家介紹看看。

參考網站

  1. jQuery Mobile官方網站

2011年9月25日

點課幫 Developer Party 11-925活動完成!

首先,小弟我很感謝各位大家踴躍地參加,因這一次是第一次辦類似這種活動,其實原本也沒想到會有那麼多人來,而過程中也有很多地方沒有掌控好,也很謝謝大家的包含;其中,大家給的評分與建議,小弟也會懷恨在心,小弟也由衷感謝,未來我們也會調整整個過程與方向。

其次,也很感謝法柏咖啡的場地贊助,雖然我們人數一直不能確定,但還是肯把最大最大的場所借給我們,這真的是個非常棒的場地!!未來的大型活動,一定還會回來這邊辦~

以下是投影片連結,這個超連結位置是暫時的,未來可還會做變動,但是可以保證由這篇文章一定可以找到此連結。

  1. 使用Visual Studio 2010搭配 SQL Server Developer Tools, Codename “Juneau” 進行SQL開發
  2. ASP.NET MVC 4概念與新功能探討

以下檢討文。

場地的部分,我想大家大家應該都沒有異議,但餐點的部分,小弟想說大家應該都吃飽了,那吃點甜點會比較好,結果感覺大家比較想要吃三明治阿XD,未來這方面我會再多加確認。

今天講的兩場課,老實說,自己也沒有掌控好,幾乎都是前半段拖太長,後半段用追的,努力把課程講完,而也因此,很多地方需要詳細解說的地方,也沒辦法講得讓大家聽懂,所以看完評分表,也能感受到大家對於這次課程的怨念遺憾,下次也會把課程準備得更加恰當,也希望大家持續能給意見喔!!

以下是一些活動照片,因怕涉及到個人隱私,或許有人不想網路露臉,就不把大家的玉頭給Po出來了!!

第一場,使用Visual Studio 2010開發SQL,算是講得太簡單了,內容也有點短少。

SONY DSC

第二場 Android手機開發入門,Jim講的讓大家聽的都很開心喔~

image

第三場,ASP.NET MVC 4 概念與新功能探討,整場幾乎都用飆的…( 汗 )。

SONY DSC

結論還是很感謝大家對於活動的支持,這次沒有對外開放,但大家的朋友又帶來朋友,卻能來那麼多人,真的很感動,未來我們也會更加努力,將活動做好,謝謝各位。

2011年9月22日

開發人應該學的,用Visual Studio開發SQL( SQL Server Data Tools ) - 重構功能

2012/4/5 從SQL Server Developer Tools,Codename “Juneau” CTP3版本更新成SQL Server Data Tools – DataBase Project

上一篇講到用Visual Studio去進行SQL的開發的優點,而這次的主題,讓我們探討看看一個很簡單的功能,但是可以幫我們省下非常多的事情。

資料庫寫到後面,最怕甚麼,其中之一大概就是改欄位名稱吧,如果我一聽到要改名稱,我一定會找盡各種理由來推託~,沒辦法,因為這牽涉的東西實在太多了;我們先把範圍縮小到,DB上,光是DB上就會有View表、SP這些東西要去處理,一改下去的工,可能難以想像。

但現在,我們利用Visual Studio再也不用怕這種事情啦!!甚至可以故意把時間報很長 ( 叔叔有練過,小朋友不要學喔 ),但是只要簡單的步驟,就可以把這些事情處理完畢。

是低,這個功能的關鍵字就是"重構",其實這也是Visual Studio程式上的基本功能之一,但今天用到SQL上,感受就不同了,而且方法也很簡單。

假設今天我們的資料庫裡面的Customer表裡面的ContactName要改成CName…只要這樣做。

先把你要改的欄位名稱選起來,例如下面是選取ContactName,然後滑鼠右鍵下去,點選重新命名,就這麼簡單。( 請注意!只有Database Project模式可以這要使用喔! )

image

接下來,我們只要在新名稱這邊Key上CName。

image

然後他會跳出一個視窗,告訴你,他會改掉那些東西,然後按下確定,就會自動幫你處理完畢。

image

最後,別忘了寫回正式的資料庫,原本麻煩的事情,現在就是那麼簡單!

雖然這是個小小的技巧,但卻是非常實用的功能,在這裡分享給大家。

ASP.NET MVC - ASP.NET MVC 4 Recipes、Task支援Async Controller

2012/02/25更新

終於到了ASP.NET MVC 4 的最終章,而剩下的一點點東西,就會在這篇介紹完畢,最後剩下的新功能,大概就是Recipes和Asynchronous Controllers這兩樣,其實這兩樣東西在路線圖就已經有介紹過了,而這些東西,這次官網也沒有真的公布許多東西,所以我就稍微針對官網的敘述,做一個解釋。

Recipes

這個新功能,可以讓你在Visual Studio裡面擁有完整的解決方案,就像之前所提到的,利用NuGet來安裝jQuery Mobile,來取得完整的Mobile裝置環境,而這次官方也提供Recipes Framework來給使用者開發使用,來製作方便好用的Package,並且使用此功能,也可以讓你去新增或是處理Area、Controller、View等檔案,而且配合NuGet的更新能力,更讓整個機制更加的完整而且方便。

Task 正式支援 Asynchronous Controllers

Asynchronous Controllers的Return可以返回Task了;如以下範例,以下範例使用了C# 5.0 (or 使用了AsynC CTP )。

public async Task Index(string city) {
    var newsService = new NewsService();
    var sportsService = new SportsService();
    
    return View("Common",
        new PortalViewModel {
        NewsHeadlines = await newsService.GetHeadlinesAsync(),
        SportsScores = await sportsService.GetScoresAsync()
    });
}

第二個範例,我們可以設定TimeOut的時間。

[AsyncTimeout(2500)]
 [HandleError(ExceptionType = typeof(TaskCanceledException), View = "TimedOut")]
public async Task Index(string city,
    CancellationToken cancellationToken) {
    var newsService = new NewsService();
    var sportsService = new SportsService();
   
    return View("Common",
        new PortalViewModel {
        NewsHeadlines = await newsService.GetHeadlinesAsync(cancellationToken),
        SportsScores = await sportsService.GetScoresAsync(cancellationToken)
    });
}

原則上就是這樣,其中有一些issues的部分,因為會一直去做修正,所以就不在這裡講了,有興趣的可以直接去參考相關網站。

參考資料

  1. http://www.asp.net/learn/whitepapers/mvc4-release-notes

ASP.NET MVC - ASP.NET MVC 4 View Switcher

2012/02/25更新

不知道大家有沒有用行動裝置上過網,有一些知名的網站都會針對行動裝置來設計適合行動裝置的網頁設計,但有的時候,因為網頁變了,所以我常常找不到我想要的功能…,所以這次我們要講的是如何自動搜尋想要的功能嗎?當然不可能,這個主題要講的是"將行動裝置的頁面切換成原本的頁面",也就是View Switcher功能。

首先我們先看一下效果,產生的行動裝置頁面,紅色框框就是我常常用到的功能,用來切回原本桌面端的頁面功能。

image

感覺很Cool吧,現在我們看看在ASP.NET MVC 4該怎麼寫。

首先,我們要先準備一個_ViewSwitcher這個View。_ViewSwitcher的程式碼了,如下,首先第一行會判斷是否為Mobile裝置,如果是的話,才會顯示切換的連結,如果是Desktop的話,就不會顯示連結了。

假設我們這邊一開始是使用Mobile裝置,進入第二個if,接下來,我們會使用GetOverriddenBrowser()方法來取得HttpBrowserCapabilitiesBase的實體,然後使用IsMobileDevice來判斷是否為Mobile裝置,如果是的話,就會顯示切換到Desktop頁面的連結,如果不是的話,就會切換到Mobile的連結。

@if (Request.Browser.IsMobileDevice && Request.HttpMethod == "GET")
{
    <div class="view-switcher ui-bar-a">
        @*這裡使用GetOverriddenBrowser來取得HttpBrowserCapabilitiesBase實體,
        並且使用IsMobileDevice來判斷是否為Mobile裝置*@
        @if (ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice)
        {
            @*是Mobile裝置的話執行這段*@
            @: Displaying mobile view
            @*切換頁面,並且將要傳入Controller的mobile屬性設為false,
              這樣Controller才會切換成Desktop的頁面,
              另外PathAndQuery如同其名,就是取得網址後面的路徑與參數。
            *@
            @Html.ActionLink("Desktop view", "SwitchView", "ViewSwitcher"
                , new { mobile = false, returnUrl = Request.Url.PathAndQuery }
                , new { rel = "external" })
        } 
        else 
        {
            @: Displaying desktop view
            @Html.ActionLink("Mobile view", "SwitchView", "ViewSwitcher"
                , new { mobile = true, returnUrl = Request.Url.PathAndQuery }
                , new { rel = "external" })
        }
    </div>
}

既然有這個View了,我們接下來要開始撰寫處理這個View的Controller,如下,當第一次進來的時候,變數mobile會是false,因為我們希望切換成Desktop,所以和IsMobileDevice判斷的時候,就會false,然後進入最下面的設定,也就是SetOverriddenBrowser()這個方法,這邊使用列舉型別BrowserOverride來設定並產生HttpBrowserCapabilitiesBass的實體,這裡是指定為選擇Desktop的HttpBrowserCapabilitiesBass實體,然後,就會重新倒回這個頁面一次。

( 其實這裡利用的概念,是使用HttpContext.Item來存放這些HttpBrowserCapabilitiesBass的實體,也就是HttpBrowserCapabilitiesWrapper,而在進去查看,是利用這個物件的屬性來判別是不是Mobile裝置,而這次MVC 4的方法,其實也都是在控制HttpContext.item,並非控制原本的HttpContext.Request,但詳細的細節,未來可能還要再去看原始碼 )

public class ViewSwitcherController : Controller
{
    public RedirectResult SwitchView(bool mobile, string returnUrl) {
        if (Request.Browser.IsMobileDevice == mobile)
            //這行會將HttpBrowserCapabilitiesBass的實體清掉。
            HttpContext.ClearOverriddenBrowser();
        else
            //這行會設定HttpBrowserCapabilitiesBass的實體。
            HttpContext.SetOverriddenBrowser(mobile ? BrowserOverride.Mobile : BrowserOverride.Desktop);

        return Redirect(returnUrl);
    }
}

所以當繞回View的時候,碰到這段判斷邏輯,就會判斷為false,( 因為現在是Desktop ),也因此,下面的連結就會顯示是否切換成Mobile。

@if (ViewContext.HttpContext.GetOverriddenBrowser().IsMobileDevice)

如果此時又按下切換成Mobile的連結,回到Controller時後,遇到此判斷,因傳入的mobile變數為true,且我們原本的裝置就是Mobile,所以下面這段程式碼就會成立。

( Request.Browser是不變的,也就是目前瀏覽器的狀態 )

if (Request.Browser.IsMobileDevice == mobile)

於是會執行這行,而這行就會把HttpBrowserCapabilitiesBass的實體清除。

HttpContext.ClearOverriddenBrowser();

雖然清除了,但是回到View時,View的建構子又會將Request.Browser ( HttpBrowserCapabilitiesWarpper )放一份到HttpContext.Item裡面,因此我們的裝置原本為Mobile,所以,遇到View的判斷,又會顯示Desktop的連結。

基本上這樣就形成了互相切換的機制,而關鍵點就在於這切換機制使用一個叫做Browser Overriding的機制,他可以去設定不同的請求來源( 例如是Mobile或是Desktop ),因還沒看到原始碼,目前我看起來此機制是會去判斷HttpContext.Item裡面的HttpBrowserCapabilitiesWarpper,而MVC 4提供了以下一些方法可以去控制。

HttpContext.SetOverriddenBrowser(userAgentString)
設定模擬瀏覽器的類型,會寫入一個HttpBrowserCapabilities的實體。
HttpContext.GetOverriddenUserAgent()
取得模擬瀏覽器類型的字串。
HttpContext.GetOverriddenBrowser()
取得HttpBrowserCapabilitiesBase的實體。
HttpContext.ClearOverriddenBrowser()
清除所有HttpBrowserCapabilitiesBase 的實體。

最後,我們把寫好的_ViewSwitcher放到要切換的頁面上,如下,我們使用Html.Partial這個HTML Helper方法,來載入剛剛寫好的_ViewSwitcher。

<div data-role="page" data-theme="a">
    @Html.Partial("_ViewSwitcher")

    <div data-role="header">
        <h1>@ViewBag.Title</h1>
    </div>

    <div data-role="content">
        @RenderSection("featured", false)
        @RenderBody()        
    </div>

</div>

這樣就完成了!!

最後,默認的情況下,這些覆蓋的資訊,會存一份於Cookie,所以如果畫面留在Desktop的Mobile裝置,這些模擬資訊會持續保留;此外如果想要替換存取位置,可以替換默認的提供者 ( BrowserOverrideStores.Current )。

總結,這次的文章內容,超級難打,如有錯誤的話,也煩請糾正指教,非常感謝。

參考資料

2011年9月21日

ASP.NET MVC - ASP.NET MVC 4 使用NuGet安裝jQuery Mobile並來建立行動頁面

2012/02/25 更新

其實這篇的內容和上一篇很類似,只是上一篇是用手工打造,而這篇利用了強大的NuGet來安裝jQuery Mobile,並且來建立Mobile Page。

我有想過,這篇要不要探討比較技術性的東西,但後來還是放棄,因為這樣標題很難下,內容也很難分,所以最後我決定拆成兩篇,接下來,這篇我們先單純的看了一下NuGet幹了啥事情。

jQuery Mobile是開源的Libray,它的主要的用途是用於行動裝置上,他重點在於強行動裝置UI和觸控體驗,我們只要於HTML標籤內,加上特定的屬性,jQuery Mobile就會幫助我們來識別,並利用jQuery Mobile預設的CSS和images,他就會產生出適合的行動裝置的網頁,如下:

image

不過,這不是我們這次要討論的重點,未來會在針對jQuery Mobile來做介紹。

而以往我們要裝類似的東西,都很麻煩,要上網去下載下來後,再裝上去,但現在我們利用NuGet,他會幫我們全部搞定!

我們只要在專案上,按下滑鼠右鍵,選擇Manage NuGet Packages。

image

然後我們就可以由online(第一步)裡面,搜尋jQuery Mobile(第二步),挑選到jQuery Mobile,並選安裝( 第三步 )。

image

裝完後的效果,它會自動的把jQuery Mobile需要的東西裝上去,但這邊預設就是放在Content底下了。

image

現在,如果有需要建立Mobile的網頁,就可以快速地使用jQuery Mobile來建立!

最後,為了方便測試各種不同的手機,我們這邊使用Firefox的一個擴充套件,User Agent Switcher,這個擴充套件可以快速的切換你要測試的User平台,如下。

image

然後照舊,我把Firefox縮小成像手機的樣子,這樣比較有感覺。

image

就是這樣簡單。

參考網址

2011年9月20日

開發人應該學的,用Visual Studio開發SQL( SQL Server Data Tools ) - DataBase Project模式

2012/4/4 從SQL Server Developer Tools,Codename “Juneau” CTP3版本更新成SQL Server Data Tools – DataBase Project

記得這篇的撰寫,是因為TechDays 2011最後一場太棒了,而撰寫的記憶筆記,事到如今也已經快要過一年了,記得那場的主題是"開發人應該懂的SQL Server進階開發 - 活用Visual Studio 2010”,講師是高光弘老師,但到現在,我還是到處都找不到他的Blog,所以只能給恆益的連結,本人比較帥喔XDD。

回歸正題,我覺得這是非常實務且好用的主題,剛好之前的一篇文章安裝SQL Server Data Tools - DataBase Projects也還沒寫後續應用,又剛好的那次的課程剛好的補齊了一些之前沒看到忽略掉的,所以很多很多的剛好,就成了這次想要分享給大家的題目。

現在大家是怎麼寫SQL的!?我想可能會有很多種回答,我聽過最酷的回答是"不用寫,因為是DBA的工作",不過,就算是這樣,還是可以稍微繼續往下看;我們以前開發是使用SQL Server Management Studio來做撰寫SQL的工作,所以碰到的第一個問題(不便)就是都要在視窗間切來切去,不過好在後來我和IT部門A了一個螢幕,所以雙螢幕就解決了這個問題。(然後工作量就加倍,因為雙螢幕,就要有雙產能…= =|| ),接下來,開始導入版控,程式碼都開開心心的進入版控了,但是SQL語法,還是像孤兒一樣,然後動到一個東西掛掉,就四處找備份…,其次也沒有支援Intellsense( 記得2008版本的SQL就有開始支援 ),然後正式機與測試機的SQL又不同,等等…,我想,大家應該都有類似的經歷吧( 那位由DBA寫的不算… ),所以以下列出幾個目前我們常用到的問題。

  1. 開發環境沒有統一,且需要學習不同工具。
  2. 版本控制不易處理。
  3. 重構能力不足。
  4. 沒辦法做到差異比較。

當然,零零總總還有許多沒列出來;而這些的問題,微軟幫我們解決了… ( 這台詞用了好幾年了 )

那要怎麼做到呢?技術的主軸在於離線開發,此工具會在正式資料庫的Schema複製一份到本機的記憶體裡面,而未來新增欄位、修改欄位、刪除欄位都在本機端執行,而不會立即的影響到正式機端,如確定完成,可以再發佈回正式機去做修改,接下來,我們先把資料拉回來吧。

首先我們打開Visual Studio,可以看見SQL Server物件總管,如果找不到的人可以去檢視裡面找,如果還是找不到的人,你可能沒有安裝SQL Server Data Tools..,我們可以按下如下圖的加入Server按鈕加上伺服器。

image

然後就會出現以下畫面,我們這一步要做的是先連接到正式的資料庫,這樣才有辦法從正式的資料庫裏面拉Schema回來進行本機上的模型建置。

image

然後左邊就會出現剛剛加入的SQL Server,Cool!。接下來,針對想要處理的資料庫,瞄準後按下滑鼠右鍵,並選擇,建立新專案。

image

其實,在Visual Studio裡面開發SQL,也是利用專案的方式去進行,也因為使用專案的方式,未來無論是版控,或是檔案的控管就會更加的方便;設定完無誤後,就按下啟動吧

image

接下來,會出現匯入資料庫的視窗,但老實說,這邊命名也覺得怪怪的,因該將資料庫的Schema轉成專案,怎麼會寫成匯入資料庫哩- -??

image

完成後,我們就可以從方案總管看到,原本是ClientBasic的Table,已經幫忙轉成SQL了,而且也幫我們建立了一個DB Project – TestDB。

image

首先我們點選右邊方案總管的視窗,我們選擇ClientBasic.sql,然後就會出現左邊的編輯視窗,其實這個視窗和SQL Server Management Studio很像,我們可以從左邊的地方迅速的修改屬性,如果是SQL神人,想直接Key SQL也可以,下面的視窗供神人使用,改完後會自動連動上面的視窗,這次我們在裡面加了一個CName,完成後就可以使用Ctrl+S來存檔。

image

這時候我們可以回到SQL Server物件總管,結果發現,CName欄位沒有加進去!!這是理所當然的,上面的儲存和正式的資料庫是沒有關係的,上面所儲存的是存在本機端,也就是sql這個檔案。

image

本機端的Table結構寫好後,我們可以利用綠色小箭頭 ( 開始偵錯 )來run run看,看看有無相依性等問題,這裡的綠色小箭頭,並不會正式部屬到正式DB上去,就如前面所說,他會檢查本機記憶體裡面的Schema來進行驗證比對。( 雖然輸出框的內容是建立,但實際是是不會發佈回SQL Server的 )

image

因為現在都已經拉回本機去做處理,如果有四個人同時開發,到底現在正式的SQL內容是甚麼呢?和目前本機的SQL差異多大?我想這個問題應該是每個人心中的疑惑,既然有疑惑!Microsoft一定會幫你搞定!於是,他有一個工具叫做結構描述比較,這個功能可以比較資料庫、專案的差異,甚至也可以比較資料庫對資料庫,或是專案對專案喔。

image

然後我們這邊就可以選擇要比對的兩個位置,左邊是目前的位置,也就是本機的專案位置,右邊則是目標為,我們可以點選箭頭,選擇目標位置。

image

他可以去和其他專案做比較,也可以和資料庫的內容作比較,連應用程式檔案都可以,感覺有沒有酷斃了!?

image

選好後,我們可以從左上角,按下比較。

image

出來的結果如圖,這裡不要衝動按下1、2、3、4,這裡的數字是方便我解釋…

image

首先,中間沒有紅框的畫面,會顯示出兩者之間差異的列表,所以我們可以看到ClientBasic這部分有差異,我們可以從中間鉛筆符號,看到即將要做怎樣的動作,這邊這個符號的意思,就是變更的意思。

1的部分就是更新目標,也就是準備要將兩邊的SQL做一個同步了;如果真的很擔心,也可以先使用隔壁的"產生指令碼"按鈕,來檢視產生的SQL。

2的部分是左右切換,還記得現在左邊是本機專案嗎?如果今天我們想要以Server為主,我們就可以按下此按鈕左右切換,這樣子,更新目標的時候,就會以Server為主,也就是說,本機上的CName會被Alter掉,畢竟Server目前是還沒有這個欄位的。

3的部分表示整段程式碼,差異的地點在哪裡,所以這邊會有兩條,紅色的區塊,代表著這個地方程式碼有並沒有,黃色代表這個地方有增加東西,而綠色的框框,表示目前顯示的區塊所佔的位置。

接下來,4的部分,代表著和左邊和右邊差異的SQL語法,這裡要提醒一下,如果看完整個SQL語法,會發現他是用Creat,但不用擔心,更新目標的時候,系統會自動判斷。

接下來,我們來看一下實際上會執行怎樣的SQL,我們點選上圖"更新"旁邊的產生指令碼,就會跳出產生的SQL給你看,但這部分有個地方要特別注意一下,如下圖,這裡會有兩個綠色小箭頭,上面的綠色小箭頭是針對專案來進行驗證偵錯的工作,而從產生指令碼開出來的視窗是Script處理視窗,Script處理視窗的綠色小箭頭,按下去,雖然會看到單步除錯,但實際上這個地方的綠色小箭頭,是已經開始針對DB進行修改的動作了,所以這部分要特別注意。

image

最後,無論我們使用"更新目標",或是開啟Script來進行處理,都可以輕鬆地就同步了兩邊的資訊。

後記

記得之前講這個工具的課程,讓大家為之轟動XDD,因為以往SQL的管理上,總是會有許多問題,例如目前的結構正式機和測試機差在哪邊,SQL要如何版控,SQL要如何佈署!?但現在SQL Server Data Tools的出現,徹底的強化整個開發的流程與管理,也解決了許多以往繞來繞去才能解決的問題,總之,這是非常好的工具,真的強力推薦大家試試看!!