前些天,项目组将项目从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不会先进行判断处理。