2011年8月25日

ASP.NET MVC 將所有的View包成DLL

有的時候開發ASP.NET MVC專案時,我們會將Model獨立出來進行開發,另外成立一個專案來進行處理,那View呢??是否View也有可能獨立成一個專案??

我們從@helper開始,把常用的東西抽離;到把整個@helper當成一個專案來開發,做成DLL;那既然@helper都能包成DLL了,感覺上View預先編譯成DLL也不遠了,但其實David和Chris早就想到了,而且各自有各自的做法,既然前面都是介紹David,我們就繼續延續下去吧。

當然,這些都是實驗性質的技術,所以請大家酌量使用。

當然,第一步還是要先把Razor Generator裝起來,位置在工具=>擴充管理員。

image

裝好後,我們可以先建立一個新的ASP.NET MVC 3應用程式專案,然後選擇"網際網路應用程式"。

image

接下來,因為我們要將View獨立出來一個專案,所以必須再加入一個類別庫專案。

image

image

接下來,我們要使用NuGet取得PreCompiledMvcViewEngine Package,選擇剛剛加上去的類別庫,然後選擇Add Library Package Reference。

image

image

然後,勇敢的按下去安裝,完成後,他預設會幫你裝上一些樣板如下。

image

因為我們要把所有的View搬移過來,所以先把類別庫專案的View資料夾砍掉,也順便把Class1.cs砍掉,並且將MVCApplication專案的View剪下,貼到類別庫專案裡面去。

image

接下來,要設定這些View的屬性,將這些View的屬性設定如下,自訂工具請輸入"RazorGenerator",建置動作選擇"無",如果成功的話,會發現.cshtml下面,會出現一個.cs檔案的樣板。

image

接下來,因為View的部分會使用到MvcApplication的Model,所以要讓View的這部分參考到MvcApplication。

image

此時,就可以先將View做個編譯了,編譯完成後,回到MVCApplication裡面,既然MvcApplication需要用到View,自然也需要參考到View,但是如果選取專案的話,會形成循環,所以這邊我們只能參考到View的DLL檔案,也就是說,如果未來View有改過東西,就必須要先將View的部分先編譯一次,MVCApplication的部分才會改變。

image

這樣就完成了。

基本上,如果能讓View打包成DLL,是有許多好處的,除了可以讓發佈的檔案更加單純,甚至可以進行View的Unit Test,如果大家有興趣的話,可以來試試看喔!!

參考資料

  1. http://blog.davidebbo.com/2011/06/precompile-your-mvc-views-using.html
  2. http://www.chrisvandesteeg.nl/2010/11/22/embedding-pre-compiled-razor-views-in-your-dll/

ASP.NET MVC 將Razor的@helper包成DLL重複使用

如果還不知道@helper的可以參考這裡,基本上@helper是一種可以讓Razor重複使用的方法,但是先天的限制,只能用於同一個View裡面,雖然可以放到App_Code這個資料夾裡面,但是如果檔案數量變多,也會變成難以管理,此外,站在某個角度來看,也沒辦法把許多寫好的@helper輕鬆地給其他地方使用,所以超強的David Ebbo寫了一個套件,來解決這方面的問題。

經過測試,HTML Helper還是不能使用,另外,這些都是屬於實驗性質專案,未來如果實驗完成,也有可能直接併到新版的MVC裡面,所以請酌量使用。

首先,我們要先從Visual Studio的工具=>擴充管理員,來新增這個套件。

image

安裝完後,可能需要重新開啟Visual Studio,接下來,我們於原來的專案裡面新增一個類別庫專案,完成後如下圖。

image

然後將原本的Class1.cs之檔名改為Sky.cshtml。
( 當然,這裡的檔名可以自己取,但是副檔名記得改成cshtml )。

因為原本的內容是要給我們撰寫類別用的,但我們現在要撰寫的是cshtml,也就是Razor的語法,所以把原本的內容都清空吧!,接下來,我們如之前範例,希望寫一個能判斷有無60分以上,並會顯示及格或是不及格的內容,如下程式碼。

@* Generator: MvcHelper *@
@helper DisplayScore(int score)
    {
    if (score > 60)
    {
    <span>合格!</span>
    }
    else
    {
    <span>不合格!</span>
    }
}

這裡要注意,第一行記得加上@* Generator: MvcHelper *@,來讓編譯器編譯。

下一步,去修改sky.cshtml屬性,將自訂工具那欄Key上RazorGenerator,自訂工具命名空間打上sky ( 也可以使用自己想用的命名空間 ),建置動作選擇"無"

image

完成後,就可以先編譯看看,如果成功我們再將選擇主要的MVCApplication專案,並把剛剛準備好的類別庫專案加入參考。

image

最後,我們稍微改變一下主要MVCApplication專案的Index.cshtml,並來使用剛剛寫好的@helper方法。

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>
        @Sky.sky.DisplayScore(int.Parse(ViewData["Score"].ToString()))
    </div>
</body>
</html>

我們在中間那行加上一個sky.sky.DisplayScore此方法,第一個sky其實就是我們剛剛設定的命名空間,第二個sky是檔名,第三個就是@helper方法,完成後就可以執行看看。
( 別忘了,要在Controller裡面加上個ViewData喔,這裡就不提了 )

最後,David提供了一個方法,讓我們可以解決View區塊邏輯重複使用的問題,如果大家有興趣,可以去試試看喔!!

參考網站

  1. http://blogs.msdn.com/b/davidebb/archive/2010/10/27/turn-your-razor-helpers-into-reusable-libraries.aspx
  2. http://razorgenerator.codeplex.com/

2011年8月24日

ASP.NET MVC – Razor的@helper語法

這篇是從ScottGu那邊看來的,之前和同事的每週技術分享報告上,有分享過,但後來也隨著時間,投影片就這樣消失於地球上,剛好最近又看到這個東西,就順便把他分享出來吧。

有的時候,在View上面,也是會需要做到許多重複的事情,例如下面這個例子,將成績輸出到View,如果大於等於60會顯示及格,若小於60就顯示不及格。

<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>
        @if ( int.Parse(ViewData["score"].ToString()) >= 60)
        {
            <span>合格!</span>
        }
        else
        {
            <span>不合格!</span>
        }
    </div>
</body>
</html>

這是很簡單的例子,但搞不好會有很多頁都會需要做這樣的判斷,並顯示,如果用老方法拷貝貼上大法,當然可以很快,但這樣就會變得很難維護,總之Razor的@helper就是解決這個問題,我們可以將程式碼改成這樣。

@helper DisplayScore(int score)
{
    if (score > 60)
    {
    <span>合格!</span>
    }
    else
    {
    <span>不合格!</span>
    }
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>
        @DisplayScore(int.Parse(ViewData["score"].ToString()))
    </div>
</body>
</html>

如上程式碼,我們將原本的判斷邏輯提出來,並且放到@helper DisplayScore裡面,這樣就可以重複使用,而這就是@helper的用法,最後我們可以直接使用@DisplayScore來呼叫放在@helper裡面的方法,就是這樣簡單~

但是這樣做,也只能使用到同一張Page,如果要不同張的Page使用的話,要怎麼辦呢?其實可以將@helper放到app_code裡面,如下圖,這樣就可以在其他的Page裡面使用。

image

另外,因程式碼移出至App_Code,所以原本的View表,也要稍微修改一下,需要在DisplayScore前面加上命名空間(也就是放在App_Code的檔案 )如下。

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
</head>
<body>
    <div>
        @Sky.DisplayScore(int.Parse(ViewData["score"].ToString()))
    </div>
</body>
</html>

但要注意到的一點,在App_Code裡面不能使用任何的ASP.NET MVC helper methods,例如Html.ActionLink()、Html.TextBox()等等,這部分官方也說未來會再改進,但不管如何還是將此方法提供給大家參考使用。

參考來源:

  1. ScottGu Blog
  2. 解決無法在App_Code無法使用Helper method之方法

2011年8月23日

ASP.NET MVC – Hello ASP.NET MVC ( 目錄架構篇 )

俗話說的好,樂團練習必定要練自由,寫程式第一支程式一定是Hello xxx,原本是想換一個不同的東西,但人家說,如果沒有寫Hello的話,是會招來不吉利的!?,所以為了信奉此習俗,所以第一支程式還是簡單的Hello ASP.NET MVC吧。

前面已經針對MVC有個基礎的概念,從現在開始,會教導大家,怎樣寫ASP.NET MVC。

而在這邊,我們要先將開發環境準備好,目前我們會使用到Visual Studio 2010來開發,如果沒有Visual Studio 2010的人,可以使用Visual Web Developer Express 2010 SP1,這邊建議可以直接使用Web Platform下載;如果使用Visual Studio 2010,預設是使用ASP.NET MVC 2,建議可以將Visual Studio 2010升級到SP1版本,SP1內含ASP.NET MVC 3,同樣的,以上皆可以使用Web Platform做下載。

關於Web Platform的教學可以參考這裡

東西都準備妥當後,就要開始超快速的ASP.NET MVC體驗!

首先,我們先開啟Visual Studio 2010後,選擇檔案=>新增專案,然後選擇ASP.NET MVC 3 Web應用程式。

擷取

接下來,選擇網際網路應用程式,因為目前重點在於Demo ASP.NET MVC,不是HTML5,所以使用"HTML5語意標記"就不勾選了,另外檢視引擎選擇Razor,單元測試也不是目前的重點,也暫時不勾選,然後按下確定。

( 網際網路應用程式和內部網路應用程式裡面會包含一些Microsoft預設的範例,未來如果自行開發時,覺得不太需要這些多餘的範例,可以直接選擇空白來做開發,當然,如果自行有定義一些樣板,未來也可以加入進來。至於檢視引擎,有區分兩種,一種是ASPX,也就是ASP.NET MVC 2之前所使用的,大家最常看到,最熟悉的<%%>這種符號,而ASP.NET MVC 3新的檢視引擎Razor,則是使用@來取代<%%>,目前使用過Razor的人,都會給個讚,如果對此還不熟悉的人也沒關係,未來在View的地方會在講解,目前先使用Razor就對了。)

這裡有針對Razor做快速的解講,對檢視有稍微了解的人,也可以先去看看。

擷取

建立完專案後,原則上就可以直接執行了,執行後,會出現這個畫面,這樣就完成了,最簡單的ASP.NET MVC程式,有沒有很簡單啊,連程式碼都不用Key…不過如果我這樣就結束,可能會被打死…接下來,先讓我們稍微深入的了解一下,ASP.NET MVC的結構吧。

擷取

ASP.NET MVC使用了許多"約定"的設定方法,簡單的說,就是強迫你檔名要怎麼取、位置要怎樣放,所以ASP.NET MVC是不可以隨意地亂取亂放;這是因為,如果你要檔名自己取、位置自己選,那就變成要做非常多的配置設定;設定檔名的對應、位置的對應,這樣子就會變得很複雜,而且很耗時耗力,又不容易除錯;所以ASP.NET MVC使用一種叫做Convention Over Configuration( 約定勝於配置 )的方式來定義這些檔名、位置、Function名稱等等等,所以我們來看看ASP.NET MVC固定的目錄結構。

擷取

我們從上面看下來,會有以下的基本目錄,而如上所述,ASP.NET MVC有約定必須要固定放於某個目錄之下,必須遵守的目錄有Controllers和Views這兩個目錄,雖然其他沒有規定一定要這樣存放,但如果依照他建議的方式存放,我想也沒有甚麼壞處,所以建議大家還是使用預設的存放方式。

  1. Content - 存放image,css等資源用的目錄,
  2. Controllers - 存放Controller類別。
  3. Models - 存放Model類別。
  4. Scripts - 存放JavaScript。
  5. Views - 存放檢視畫面,如果是ASPX,副檔名是aspx,如果Razor,則為cshtml,另外這裡使用的是C#版本,VB版本的附檔名也有一點點小差異。

還記得之前講到的Controller是什麼嗎?他是負責控制流程的類別,如上圖,就有一個HomeController.cs的檔案和AccountController.cs這兩個Controller檔案,到這邊,我想大家不知道有沒有發現,為什麼後面都要加上Controller呢?沒錯,就是因為這也是約定的關係,既然是約定的關係,所以ASP.NET MVC會強迫所有Controller的檔名就必須叫做xxxController,而且,連此類別的名稱也必須叫做xxxController;所以要建立一個Home的Controller,就必須建立一個叫做HomeController.cs的檔案,然後類別名稱為HomeController,且要放在Controllers的目錄下面。

( 若是用配置的話,就會有非常多設定,來設定Controller,配置哪個controller在哪裡,名稱叫什麼。 )

前面提過,Controller是負責流程控制,所以我們先打開看看HomeController.cs這隻檔案,看看裡面有甚麼吧。

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

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "歡迎使用 ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }
    }
}
首先,不用說,所有的Controller都是繼承於Controller這個父類別,( 好繞舌… )如HomeController也是繼承於Controller這個父類別,而底下有兩個Function,分別為Index()和About(),這兩個分別代表甚麼意思呢?因為Controller是控制器,他會控制流程,並會Show出要顯示的網頁;以首頁來說,首頁可能會有Index頁面、About頁面;所以這裡的Function,Index()和About()就是代表著要處理的Index頁面流程和About頁面流程,假設今天有一個客戶控制器CustController來處理客戶的新增修改刪除等,就需要add()、del()、edit()等Function,而在ASP.NET MVC中,這些Function我們也稱之為Action,代表著要執行的動作。

( 其實一個Controller的Action (Function) 不一定是代表一個page的流程,也有可能是子頁面,也有可能導向同一頁面,但這邊為了解釋方便,可以暫時先想像成一個Action(Function)等同於一個頁面的流程。 )

大體的介紹完Controller後,我們繼續看下去,既然Controller的Action(Function)代表著一個頁面,那他勢必也會對應到一個View,對吧!而且既然Controller都約定那麼多了,View當然也逃不了一起被約定的命運;我們剛剛看到了HomeController裡面有Index()、About(),所以,大家應該也猜的到,View檔案的命名,勢必也必須和HomeController的Action(Function)名稱相同;所以Index()這個View的檔名應該叫甚麼呢?沒錯,就是Index.cshtml,而About()就是對應About.cshtml,而且還必須要放到View的目錄下;到這邊,不知道大家有沒有發現一個問題,如果有兩個Controller都有About(),那不就要建立兩個About.cshtml了嗎?這樣不就打架了嗎?,所以ASP.NET MVC還必須在View的目錄下面,在建立一個Controller名稱的目錄,以HomeController的來說,就必須在View底下,在建立一個Home的目錄,並且把Index.cshtml和About.cshtml放到此目錄下去,才算完成喔!

( Veiw的部分也是,若是要配置,還要指定View與Controller的關係,所以才會有約定勝於配置的做法。 )

( 至於Model,Model就沒有強制要怎樣做了,甚至有時候,也會有人將Model拉出來當成一個專案來處理,這部份未來有機會會再講到。)

講到這邊,可能大家就會有開始一堆疑問了,其中,我相信大家一定會問,以前一個檔案代表一頁,例如Index.aspx這個檔案,也代表著一張Page;那現在使用ASP.NET MVC的話,要如何對應到網址呢?其實Asp.net MVC有使用一個Routing機制,但這個機制也可以講個幾個章節,所以先知道這個名詞就好;而利用此Routing機制,會將網址轉到對到應的Controller上去做執行,以預設值來說,預設的Controller為Home,Action為Index,也就是說,如果今天網址上打blog.sanc.idv.tw的話,後面程式就會自動去找Home這個Controller,並會從Controller找到Index這個Action,並找到View來顯示;那你可能又會問了,那其他Controller或是Action是怎樣對應呢?以剛剛的Home這個例子來說,如果要執行About這個Action,他的網址就是blog.sanc.idv.tw/Home/About,就這樣而已,沒錯,About後面不用加.aspx、.html,就是這樣簡單明瞭;如果是Index的話,除了使用blog.sanc.idv.tw就可以顯示出來外,也可以使用blog.sanc.idv.tw/Home/Index;所以大家應該可以發現,網址下的第一個節點,就是代表著Controller名稱,如Home,而第二個節點,就是代表著Action;所以今天如果是客戶控制器CustController,裡面有add、del、edit這些Action的話,我們就可以使用blog.sanc.idv.tw/Cust/add這個網址來新增客戶資料,blog.sanc.idv.tw/Cust/del來刪除客戶資料,還有blog.sanc.idv.tw/Cust/edit來編輯客戶資料。

說了那麼多,其實第一次寫的時候,有時還是會搞混,但是多練習幾次,就不會有甚麼問題了,而這種方式,不但可以隱藏Client對於目錄架構的了解,另外一方面,也可以針對Controller所應該處理的Action加以歸類,而不會像以前一樣,一堆Page,非常凌亂,其次,這種網址對於SEO也有很大的幫助,所以,請不要氣餒,多試幾次吧!

到這邊,突然想到,我們還沒寫到Hello World…,如果這樣就結束,會有報應的,所以我們稍微改一下HomeController的程式碼,將原本的"歡迎使用 ASP.NET MVC!”,改成""Hello ASP.NET MVC”吧,如下:

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

namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            ViewBag.Message = "Hello ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }
    }
}
然後執行看看吧!!
擷取

恭喜你,完成了第一個程式,Hello ASP.NET MVC!,好吧…我承認有點喇賽,但初步認識MVC的基礎架構是非常重要的,接下來,就是針對每個模型進行解說嚕!

2011年8月7日

ASP.NET MVC 4 產品路線圖

2012/02/15 目前ASP.NET MVC 4 Beta已經出來,大家可以透過此頁面看整個ASP.NET MVC文章。

2011/09/18 ASP.NET MVC 4 Developer Preview釋出

每次寫這類主題,都不免想要回憶一下,第一次看到Preview的ASP.NET MVC,已經不知道是多久之前了,當時的第一個感覺是,太棒了,ASP.NET終於也有MVC架構可以使用,隨著第一版正式發表,並很快的拿來實戰看看,清爽的程式架構,讓人覺得真的是太棒了!,到了2010年,隨著VS2010出現的ASP.NET MVC 2,並決定將此導入至公司,而後的ASP.NET MVC 3的Razor,更是讓人驚艷!,直到現在,ASP.NET MVC已經快要進入MVC 4了,不過好佳在,整體的架構並沒有多大的起伏,多半是功能更加強大,更方便讓人使用的改善,也讓我鬆了一口氣…,接下來,讓我們看看,ASP.NET MVC 4 整個產品路線會是怎樣規劃!!

  1. 開發與佈署:讓開發與佈署能更順利,而且更快,更好。
  2. 持續強化此平台:使用Razor和helper來持續強化ASP.NET MVC。
  3. 強化AJAX:持續改善與開發,無論是單一的AJAX應用程式,或是類似Gmail這種整頁式的應用程式。
  4. HTML5、平板、與手機裝置:讓整個ASP.NET MVC能簡單的建設,並且能輕鬆地轉移。
  5. 雲端,要能更快速和容易的放置於雲端,並且將重點放於性能、安全性與可擴充性。

當然,目前畢竟還未正式發佈,未來會變得怎樣,目前官方也還不能保證,但我們還是可以先來搶先看看,未來的ASP.NET MVC 4,有怎樣的改變。

Recipes食譜(配方!?)概念

這個概念是用於提升ASP.NET MVC的開發速度,想當初在導入時期,我最常聽到的抱怨是,如果ASP.NET MVC可以像ASP.NET有拖拉拖拉元件可用就好了,老實說,當初我也不知道該怎麼解釋,因為如在寫ASP.NET,我也比較習慣直接Coding程式碼,不過,我想針對許多的ASP.NET轉換到ASP.NET MVC的人,還是會很希望能有這些簡單的拖拉元件可用吧。( 之前聽到最多的抱怨是DataGrid… )。所以這次的更新,ASP.NET MVC團隊也聽到了XD!?,反正不管怎樣,有的時候要處理一些東西,的確是很麻煩的,所有這次多了一個叫做Recipes的概念(直接翻就叫做食譜或是配方,感覺好像在玩RPG…),他可以讓你從對話框中選擇你想要的Recipes,如下圖,而選擇好的東西,後段就會利用NuGet來將相關的程式碼與使用者介面等東西插入到適當的地方。

image

當然,如果是比較複雜的配置,還可以持續的下一步,下一步。

image

但還是要強調一點,MVC的架構與之前的ASP.NET是截然不同的,雖然會有更方便的東西可以讓大家使用,但我認為,還是必須去深入了解他的概念後,再利用這些工具快速地幫忙產生,是比較好的做法。
最後,微軟官方舉的這個例子是要建立一個Ajax grid,沒錯,建立Ajax grid需要做一堆的事情,從建立view code,HTML撰寫,資料的存取,控制器等等一堆東西。而如果利用Recipes,他就會幫你將以上的這些事情處理好。當然,你也可以自行撰寫一些食譜給大家使用,不過也還沒正式發佈,所以未來會怎樣實作,也有未知數,所以這裡先不提了。

手持裝置

現在的智慧型手機已經越來越多人使用,我想未來也即將進入移動網路時代,大家利用手機隨時隨地瀏覽網頁的頻率也越來越高,這時候,原本給PC用的網頁解析度,已經不符合手持裝置來使用了( 其實以前就已經有類似問題了… ),而因越來越多人使用,人多果然就是力量( 商機 ),所以ASP.NET MVC 4也考量到這一點,為了讓手機上的網頁顯示的更漂亮,更符合手機上的解析度,按鈕更加適合人手指的大小,所以ASP.NET MVC 4也提供了簡單、靈活的方式來支持行動裝置,如下圖。

image

ASP.NET MVC 4利用CSS和樣板的變更,來支援手機、平板等行動裝置的顯示,除了原來已經開發好的網站,可以用升級!?的方式來支援行動裝置外,也支援專門來開發手機的專案,這種專案,有別於原本的網頁專案,會將jQuery Mobile版本等符合手持裝置上的原件,預先幫你準備好,如下圖。

image

不過,我想應該很少會直接使用這個專案吧,不過也沒關係,原本的專案,還是可以去調整成手持裝置上使用,例如使用有mobile的檔案名稱等,來區分mobile,如下圖。

image

當然,建立Controller時的視窗,也會針對此mobile做調整。
image
image

最後,整個設計團隊,也希望能做到可以自由切換行動與桌面上,不過就如我一開始所講的,這些都還是ASP.NET MVC 4的產品路線圖,至於未來會怎樣呈現,能做到怎樣程度,還是要等到正式版本釋出才會知道。

Task支持AsyncController

原本在ASP.NET MVC 3裡面,要處理這些問題是件很麻煩的事情,如下:

public void IndexAsync(string city) {
    AsyncManager.OutstandingOperations.Increment(2);

    NewsService newsService = new NewsService();
    newsService.GetHeadlinesCompleted += (sender, e) =>
    {
        AsyncManager.Parameters["headlines"] = e.Value;
        AsyncManager.OutstandingOperations.Decrement();
    };
    newsService.GetHeadlinesAsync();

    SportsService sportsService = new SportsService();
    sportsService.GetScoresCompleted += (sender, e) =>
    {
        AsyncManager.Parameters["scores"] = e.Value;
        AsyncManager.OutstandingOperations.Decrement();
    };
    sportsService.GetScoresAsync();
}

public ActionResult IndexCompleted(string[] headlines, string[] scores, string[] forecast) {
    return View("Common", new PortalViewModel  {
        NewsHeadlines = headlines,
        SportsScores = scores,
    });
}

但是ASP.NET MVC 4後,就可以很簡單的實現( 但需要配合Visual Studio Async CTP,或是未來的C# 5.0 )

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

其他部分還有些像是Razor與ASP.NET的支援、CSS和Javascript的綁定、EF的Code First不會再覆蓋舊的資料、WCF API的支援、Ajax的改善、HTML 5的helpers、支持donut hole cache、更安全的AreaAttribute class等等,這些東西也會努力改善與實現。

最後,如一開始所說的,這些東西其實沒有很大的差異與變化,但是讓使用者更方便了,所以看到這篇文章的人也不用擔心,就算準備學習ASP.NET MVC 3的人也可以不用猶豫,可以放心的從ASP.NET MVC 3開始進入,我相信到時候,也可以順利的銜接,並且讓你更能感受到,哇~有ASP.NET MVC 4真好。

參考資料:
http://haacked.com/archive/2011/07/13/asp-net-mvc-4-roadmap.aspx
http://www.asp.net/mvc
http://aspnet.codeplex.com/wikipage?title=ASP.NET%20MVC%204%20RoadMap

2011年8月4日

IIS使用Windows驗證時,無法登入,且會出現401.1 錯誤。

剛剛在整理舊的備忘資訊時剛好看到這個事項,這是之前花了好幾天的時間解決的一個問題,不過也因為時間已經太久,現在也沒機器設備可以將當時狀況還原,所以只能用文字的方式描述。

這個問題的來源,是因為當時要建設本機的開發環境,而每個人的開發環境下,都有自己的一個網址,例如說,我本機的開發網址是sky.sanc.idv.tw,而其他人的可能是xxx.sanc.idv.tw,當然,姑且先不討論這種方式好或不好,畢竟有的時候,在公司下的某些限制,不是一般人能想像的( 說到這就想哭了… ),當然,這種設定,其實也不難,只要在DNS下,設定一下就好了,可憐就可憐在於IT部門用了一堆理由藉口,不準這樣做,好吧,既然不准設DNS,那我設定自己電腦上的host總可以了吧,於是,故事就這樣展開了…

因為我的主機,也必須要當其他人的Web Server ( 當初原本是每個人設定每個人本機上的iis,但有一台因特殊原因,必須利用我這台當跳板 ),所以,我這台的電腦上,除了sky.sanc.idv.tw外,還要設定aaa.sanc.idv.tw。

所以我把當時我所做的事情,稍微還原一下。

1.我先於windows下,將想要解析的Domain name加入於hosts檔案中。
a.使用記事本打開/WINDOWS/system32/drivers/etc/hosts檔案( 因有權限問題,所以別忘了先調整權限 )。
b.在最下面加入要解析的網址如下。( 改完存檔,也別忘了把權限調整回來。 )

image

到此,就可以於本機上解析到sky.sanc.idv.tw還有xxx.sanc.idv.tw。
然後我們去ping一下,看看正不正確。

image

看來是沒有任何問題了,這時候我們要開始設定IIS

1.打開IIS,然後新增網站,設定基本上如下,xxx的網站又是同步驟來執行。

image

2.因為我們是使用AD驗證,所以要開啟windows驗證功能,並且將匿名驗證的功能關掉,如果沒看到Windows驗證,就可能要去給他裝一下。
image

到這邊為止,IIS也設定完成了,這時候,就可以很開心的在本機上模擬兩個網址…原本應該是如此,但果然事不從人願…,怎樣登入,都登入不進去,都會一直卡在登入畫面。

image

這時候按下取消出現的是

HTTP 錯誤 401.1 - Unauthorized

使用您提供的認證,沒有權限檢視此目錄或網頁。

嗯,我想也是,畢竟沒有登入成功,所以一定會出現沒有權限之問題,原本猜想是資料夾問題,但是將windows驗證關閉,開啟匿名登入,又可以順利進去,所以把矛頭指向Domain name解析的問題,猜想說,難道IIS不支援嗎?,不可能吧,Apache都可以輕易達成了,IIS怎麼可能不支援這基本的東西,就這樣,搞了我一兩天。

後來在Microsoft的網站上找到一篇,疑是很像這問題的文章。
http://support.microsoft.com/kb/896861
雖然裡面的症狀,幾乎都不是我所碰到的,但是這段話,卻讓我開始懷疑。

當網站上使用 「 整合式驗證 」 且具有對應至本機回送位址的名稱時,就會發生這個問題。

於是詳細了查詢這個問題,原來是因為安全性的問題,讓IIS會禁止回應,具體的安全性文題如下:

之所以發生這個問題,是因為 NT LAN Manager (NTLM) 將不同的命名慣例視為遠端個體,而非本機個體。當用戶端先計算與快取在本機 "lsass" 記憶體中由伺服器傳送對 NTLM 挑戰的正確回應,再將回應傳回伺服器時,會無法驗證本機。當 NTLM 的伺服器碼發現在本機 "lsass" 快取中有已接收的回應時,伺服器碼不遵循驗證請求,並將該請求視為重新顯示攻擊。這個行為導致本機驗證失敗。

所以產生了此問題

在套用此安全性更新之後,如 Microsoft SQL Server 或 Internet Information Services (IIS) 等應用程式在進行本機 NTLM 驗證請求時可能失敗。

那要如何解決此問題呢,官方有兩種解決方法,第一種是停用NTLM 反映保護,但不推薦,所以我們採用第二種方式,停用特定位置的保護,步驟如下。

1.打開Regedit,並找到這個位置HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0
2.在MSV1_0上,按下滑鼠右鍵,選新增,多字串值。
image

3.將此值命名為BackConnectionHostNames

image

4.點選剛剛建立好的值,並按下滑鼠右鍵,選修改,然後於視窗內填入要略過的網址如下。

image

5.按下確定後,Regedit就可以關閉了,這時候需要將IIS的網站重啟。

image

然後,就可以順利的登入了!!

這次的事情,老實說,碰到了兩次,第二次的時候,因已經過了一段時間,又給他熊熊的忘記了,所以,又處理了一兩天,所以,把資訊記錄下來,是非常重要的 >"< 。

以下是參考文章:
http://support.microsoft.com/kb/957097
http://support.microsoft.com/kb/896861

2011年8月3日

Visual Studio 2010 DSL (一) DSL的簡介

最近又看到IThome的一篇文章,IBM個人電腦和MS-DOS邁入30年頭,才驚覺其實電腦真正開始發展也不過短短30年頭,而短短的30年頭,就已經佔領了每個人的生活,同樣的,程式的發展也沒幾年,所以,不要太苛求我們寫程式的了,整個軟體工程,也不過短短的幾年發展而已啊~~回想當年,以前上課所教的瀑布式開發法,直到現在,演進也算是非常快的了。

最近因為公司再導入軟體工程的一些東西,所以又開始看了一些關於架構,設計等等之類的書籍,說到軟體工程的一些東西,除了超久超久以前上課所學的瀑布式等等外,當初比較有印象的就是好幾年前在學校做專題的案例了,那時候是要寫一個網頁UI程式碼自動產生器,也就是利用UML的循序圖和類別圖來斷定必須要有那些UI介面,並讓他自動產生,而整個專案過程,是使用MDA配合UML來開發,後來隨著時間,又看了一堆敏捷、XP等等等,直到最近,因DDD的關係,不小心看到了DSL。

廢話說了一堆,那到底甚麼是DSL,今天的主題並不是要用Visual Studio 2010開發任天堂的NDSL喔…,如果是的話,我想我大概就會紅了,其實DSL的全名是Domain Specific Languages,直接翻譯就是"領域特定語言",或是倒裝一下"特定領域語言",目前看下來,"特定領域語言"這種中翻比較多人使用。

在解釋甚麼是DSL之前,我必須要先強調,DSL並不是像C#、Java這類的程式語言,也不是像UML這類的圖形語言,反而言之,他應該是可以包含C#、Java和UML等,換言之,他比較像是一種概念。其實DSL的概念,可以簡單說成,"利用你自己所定義的東西,來處理不斷重複的事情,並且最終可以產生你所預期的程式碼。"

舉例來說,Visual Studio裡面的LinqToSql和EntityFramework設計器,就是用DSL所寫出來的,所以DSL定義了每個Entity圖是代表著甚麼意義,兩個Entity之間的線是代表著甚麼關聯,最終畫出來的圖,應該怎樣產出程式碼。也因此,DSL其實是一種特別用來描述某個特殊領域的語言,而這個EntityFramework,就是種特殊的領域。除此之外,Visual Studio 2010的UML Modeling Project裡面的循序、類別圖等,也都是用Visual Studion DSL開發出來的。

我們再來看另外一個例子,大家應該常常會有這種感覺,今天做完這個專案,下次做另外一個專案的時候,有許多東西是很類似的,這時大家會怎麼做?,像我比較笨一點就會使用拷貝貼上改改改的方式來完成吧,而這種區塊,可能就是某種特定的領域,這時候,就可以考慮使用DSL來將此區段模組化,未來就可以直接使用。

像是EntityFramework設計器就是一個例子,我們不同的專案,不可能都用一套全新的設計器吧,而是所有專案都會使用EntityFramework設計器,所以今天把此領域模組化,未來就可以不斷的適用於各種不同地方。

而講到DSL,就不能不提DSD。

利用DSL所設計與開發的模式,就稱之為DSD Domain Specific Development

我們再從整個系統的角度來看,整個系統中,通常設計完後,可能會有固定不常變動的區塊和常常需要變動的區塊,而DSD的設計,就是尋找出經常需要變動的區塊,由設計人員使用DSL預先定義好所有的Domain,來讓那些站在更高層次,領域專家的角度,(或是程式設計師自己)來處理這類需要不斷重複解決問題的方法,而不需要讓程式設計師不斷的重複的撰寫這些程式,最後由DSL產生出來的程式碼,並整合於固定不變的部分,這就是一種DSD。

就如下圖一樣,一個系統裡面的Framework,除了手寫的Code外,不常變動的區塊外,還有一塊是由DSL寫出來的Model(左上角)所產生出來的,而產出的程式碼,就這樣嵌入於Framework裡面。

image

另外,我們通常設計一個程式時,最基本的,我們會分成三層,我們也可以利用DSL來定義這三層,並讓他自動產生相對應的程式碼,這樣未來我們製作其他專案的時候,就可以不需要再重複地打某些程式碼,如下圖,是Microsoft所做出來的一個例子,他們使用DSL來描述這三層式的架構。

image

我們可以知道,如果跨越層級存取,是非常嚴重的一個錯誤,所以當UI直接存取Data時,就會產生錯誤,這些也可以從DSL裡面定義。

image

說了非常多的東西,看到最後,或許有人會覺得這和UML有啥不同?,就如前面所述,DSL是一種用於解決特定領域的語言,他的關鍵在於解決,這和描述用途的UML是非常不同的,雖然現在像是類別圖也可以用來產生程式碼,但是UML最初的用意,是用來描述整個系統架構,讓開發者了解,這和DSL是有很大的差異,DSL的初本,就是去解決特定重複性的問題。

說了那麼多,未來我會帶一些範例,我想,大家就會更清楚的了解領悟。

以下是一些參考網站,大家也可以過去看看喔。

http://en.wikipedia.org/wiki/Domain-specific_language
http://msdn.microsoft.com/zh-tw/vstudio/cc963628
http://msdn.microsoft.com/en-us/vstudio/ff637756
http://msdn.microsoft.com/en-us/vstudio/ff637759