2011年1月27日

ASP.NET MVC 3 (二) Razor的@model

原本打算將Razor的部分,寫成一篇,
但是光是寫第一部份的時候,感覺就已經烙烙長了。
為了以後查詢方便等,結論還是分開吧。

這邊要說的是@model
之前在MVC 2,如果要將model傳入view的話,會需要寫下面這段
<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage<Customer>" %>

而如過是Razor的話,就不用寫那麼長的一段。
@* 這裡可以設定model *@
@model ASPNETMVC3_View.Models.Customer

當然,如果是List的話。
@* 這裡可以設定model *@
@model List<ASPNETMVC3_View.Models.Customer>

後續我們就可以直接使用model。
<h2>Index</h2>
<p>
@Model.name
@Model.phone
</p>

而這邊,大家可能會想到一件事情,
以前會有這段Inherits="System.Web.Mvc.ViewPage"
現在直接使用@model的話,為何不用了,
因為Razor將默認繼承自System.Web.Mvc.WebViewPage
當然你也能通過更改視圖目錄下的web.config文件選擇性覆蓋這個默認類別,
但這部分,未來再提吧。

參考網址
http://weblogs.asp.net/scottgu/archive/2010/10/19/asp-net-mvc-3-new-model-directive-support-in-razor.aspx

ASP.NET MVC 3 (一) 新的視圖引擎Razor

ASP.NET MVC 3 強化了許多的功能,其中一個就是新的視圖引擎Razor。
Razor有許多的特色,例如:
  1. Razor的語法非常乾淨,不會像以前aspx一堆框框與符號。
  2. Razor的語法很簡單易學,其實也就是C#和VB。
  3. VS2010對Razor完全的支援IntelliSense和程式碼顏色。
  4. Razor還可以支援Unit Test,而不需要啟動web Server。


其中Unit Test的部分,未來再來解說吧,
現在,來看看Razor是怎樣子的吧。

首先,寫程式最基本最基本要會的就是註解。
Razor的註解也很簡單,只要使用@* *@包起來就可以。
@* 這是簡單的Hello Razor*@
<p>Hello Razor</p>

接下來,還記得ASP.NET MVC 2之前的ASPX視圖引擎是怎樣寫的嗎?
我們先看一下ASP.NET MVC時使用的。
<p>Hello <%=name%><p>

到了ASP.NET MVC 2時我們可以改寫成這樣。
<p>Hello <%:name%><p>
使用<%:%>來將輸出的文字編碼,以防遭受到攻擊。

而Razor就很簡單了,如下
<p>Hello @name<p>
沒錯,就是那麼的簡單,只要在@後面接變數,就會自動輸出變數內容。

另外,當初在寫ASPX視圖時,遇到最大的問題,就是一堆的<%%>
不但礙眼,又難看,現在Razor可以使用{}來替代。
<ol>
@foreach(var c in customers){
  <li>@c.name</li>
}
</ol>

變的超級簡潔!!甚至還可以這樣用
<p>
@{
string name = "Razor";
string message = "Hello " + name;
if(name == "Razor")
{
  @message
}else
{
  @:Error
}
}</p>
這時可能會看到一個比較特別的@:符號,
他的用途有點像跳脫字元,如上面的程式碼,在p標籤裡面包了if判斷式,
如果沒有加上@:,在IDE就會出現錯誤,因為IDE會判斷這是一個變數,
當執行時,當然也會出錯,因為編譯器也會認定他是一個變數。
所以我們要加上一個@:,告訴編譯器,其實Error只是單純的一個文字而已。

那如果有很多行的文字呢?例如:
@{
  @:Test1
  @:Test2
  @:Test3
}

也很簡單,只要加上Razor特定的Text標籤,就不用打一堆@:
@{
  <text>
  Test1
  Test2
  Test3
  </text>
}

當然,也可很複雜的混搭,但這樣就失去了Razor簡單明瞭的意義了。
<p>
@{
  <text>
  @{
    string test2 = "2";
    <text>
    test1
    @test2
    </text>
  }
  </text>
}
</p>

另外是單行,也可以寫成這樣。
<p>@("Hello" + name)</p>

當然,既然能處理變數了,基本的物件與方法也可以直接叫用。
<p>Now : @DateTime.Now</p>

就如前面所說的,Razor視圖引擎和aspx比較起來,非常的乾淨,
也很容易去閱讀,但不代表說,所有的邏輯就可以直接放在這裡處理,
這裡要處理的應該是視圖邏輯,這要注意喔!

參考資料
http://weblogs.asp.net/scottgu/archive/2010/07/02/introducing-razor.aspx

2011年1月26日

ASP.NET MVC 3 RTM

沒錯,已經發佈了,而且早在1/13號的時候就發佈了,
我的消息還算慢的....

需要下載可以至http://www.asp.net/mvc/mvc3下載

根據官方網站所言,這次大概多了這些東西,
The Razor View Engine
Support for Multiple View Engines
Controller Improvements
Global Action Filters
New "ViewBag" Property
New "ActionResult" Types
JavaScript and Ajax Improvements
Client-Side Validation Enabled by Default
Remote Validator
JSON Binding Support
Model Validation Improvements
"DataAnnotations" Metadata Attributes
"ValidationAttribute" Class
Validation Interfaces
Dependency Injection Improvements
Other New Features
NuGet Integration
Partial-Page Output Caching
Granular Control over Request Validation
Extensible "New Project" Dialog Box
Scaffolding Improvements
New Overloads for "Html.LabelFor" and "Html.LabelForModel"
Sessionless Controller Support
New "AdditionalMetadataAttribute" Class

有些部份,之前在RC2的時候也玩得差不多了,
而我也開始打算針對MVC 3的新功能,全部玩一遍,
大家也可以至這裡來取得全部的說明。

2011年1月25日

ASP.NET MVC - Area與Controller之Routing問題

今天在測試MVC的Area的時候,發現了一個問題,目錄的層級大概是這樣
Area - Test -Controllers - AAController.cs
-Views - AA - Index.cshtml
Controllers - 無東西
Views - 無東西
此時跑測試的時候。
http://xxx/Test/AA 這是正常沒問題的。
http://xxx/AA 顯示的卻是一個例外,找不到Index.cshtml這個View,可見如果根目錄下的Controller如果沒有任何Controller的話,http://xxx/AA也會直接到Area -> Test -> Controller這個目錄下讀取AAController。

對我來說,這是一個很奇怪的現象,而且未來很容易出錯,假設,今天我在根目錄也建立了一個AAController和的Views,未來刪除掉根目錄的AAController但又忘記刪除Views,此時就會讀到Test這個Area的AAController,並且順利執行。( 但實際上我是不要順利執行的 .... )

會產生這個原因是因為,如果在當下之NameSpace找不到Controller,會自動的去搜尋別的Controller,本來以為在Routing設定的時候,加上NameSpace就可以了,但實際上不然,整個要改寫成這樣,才會正常

routes.MapRoute(
  "Default" , // 路由名稱
  "{controller}/{action}/{id}" , // URL 及參數
  new  { action = "Index" , id = UrlParameter .Optional }, new  string [] { "MVC.Controllers"  }
).DataTokens["UseNamespaceFallback" ] = false ;

必須加上DataTokens["UseNamespaceFallback" ] = false ; 告訴路由,只要抓取這個NameSpace底下的Controller就好,不要再去找整個目錄的Controller。

ASP.NET MVC 、AJAX、img標籤當button的問題

在ASP.NET MVC 2裡,當使用ajax helper時,如果使用不當,是會造成個瀏覽器的一些問題。
但如果您是使用ASP.NET MVC 3,就不用繼續看下去了。

function send() {
  $("#webForm").trigger("onsubmit");
}

中間程式碼略

<a href="#">
<img src="" alt="send" name="Test" width="150"
height="37" border="0" id="Test"
onclick="send();" />
</a>

上面這段程式碼看請來滿正常的,畢竟在設計師設計的時候,
通常都不會使用標準的Button控制項來做Submit..
通常都會將Button包成漂漂的img,然後外面包一個a標籤,
然後在img裡面加上JavaScript的觸發事件,
也就是onClick事件,來觸發JavaScript的send方法,
畢竟有的時候會需要JavaScript做驗證,
然後驗證完成後,在觸發submit事件,
這是一個行之多年的爛方法,
當然,我們也知道利用a標籤來框住img標籤的這個方法很蠢,
但是使用到現在,也沒發生什麼問題,從設計師那邊接手過來的HTML是這樣,
時間緊迫,也懶得再去修改,但結果,事情就這樣的發生了。
平常可能還沒甚麼問題,
但在使用Ajax helper的時候,卻會產生大大的問題,
Ajax helper配合上Model的驗證時,我們雖然在.cs裡面只需要在多加上幾行,
就會有強大的效過,但也產生大大的問題,
回來看這由Ajax helper產生的html,卻會在form裡面插入了兩個事件,
onClick與onSubmit,也因如此,在配合上各家瀏覽器的"風格"不同,造就了不同的結果....

首先,看到jQuery的部分,為何不寫成 $("webForm").submit();
就是因為在ie系列,配合上form的onSubmit時會送出兩次的post....
至於為什麼,我也只能猜測,在ie上,javascript的submit會直接送出表單,然後onSubmit事件會再送出一次,
那改成$("webForm").trigger("onsubmit");這樣寫就沒問題了嗎?

錯.....

如果使用這樣的寫法,firefox是不會有動作的....
原因似乎是因為onSubmit標準上是不會送出submit事件的( ie除外,所以ie會post兩次= = )
所以要怎麼辦呢...要改成以下程式碼

function send() {
$("#webForm").trigger("onsubmit");
}




中間程式碼略

<input type="image" src=""  alt="send" name="Test" id="Test"
onclick="send();" />

這樣IE,Firefox都可以了,為何會這樣,我的推測,在HTML裡,input送出的事件,會呼叫onSubmit,然後再送出。
所以這樣子,ie就不會送出兩次,firefox也可以順利執行。

所以,正規的HTML寫法還是很重要..