前些天,項目組將項目從mvc3升級至mvc4,完了之后,發現突然涌現出一大堆問題。主要是在前端,Razor引擎升級導致的。
Razor是從mvc3開始引入的,用過mvc2的就會知道,Razor用起來確實是灰常爽的(Razor意為"剃、剃刀",看着就有一種犀利的感覺),mvc4對Razor進行了升級。
mvc4中,一些Razor的寫法得到了簡化,例如在mvc3中,引用外部樣式文件我們會用:
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
而在mvc4中,只需這樣寫就可以了(暫時忽略Styles.Render()):
<link href="~/Content/Site.css" rel="stylesheet" type="text/css" />
給個大大的贊!!
簡寫給開發帶來便利,可是一不小心,很容易就會出錯,例如以下我們遇到最多的問題——
先看看mvc4,屬性值使用@true/fakse寫法Render出來的效果與mvc3的不同:
<label><input type="checkbox" checked="@true" />checked</label> <label><input type="checkbox" checked="@false" />uncheck</label> <label><input type="radio" checked="@true" />checked</label> <label><input type="radio" checked="@false" />uncheck</label>
看看生成的代碼:
mvc3中,會直接將值Render出來,而瀏覽器對於是否checked狀態的判斷是看這個標簽是否有checked屬性,並不會去判斷值是什么。所以在mvc3中,看到的是所有checkbox/radio都是checked狀態的。
而mvc4中,Razor渲染前會先判斷值,若為null或false,則這個屬性不會被Render出來,為true,則會被Render出來,且值為屬性名。
這種效果很爽,以后寫checkbox或是radio就不需要先判斷是否checked狀態了。同樣的,readonly、disabled... 也有相同效果。
另外,注意的是,這種效果對於data-*屬性沒效果,即:
<label attr1="@true" attr2="@false" attr3="" attr4="@null" data-test1="@true" data-test2="@false">test</label>
Razor Render出來的結果是:
(mvc4,注意,attr3="",這里值是長度為0的字符串,並非null)
我們之前有部分代碼是這樣寫的:
@{ var parameter1 = true; var parameter2 = false; } <a href="javascript:Reload('@parameter1', '@parameter2')">reload</a>
在mvc3中,這樣Render出來的結果是正確的,然而在mvc4中,卻出來這樣的結果:
parameter1的值為true,所以Render為所在屬性的屬性名href;parameter2的值為false,Render為長度為0的字符串。
需改成這樣寫就可以了:
<a href="javascript:Reload('@parameter1.ToString()', '@parameter2.ToString()')">reload</a>
Razor會對boolean類型進行判斷處理,但對string不會先進行判斷處理。