在以前试用VS2010的时候已经关注到它在Web开发支持上的一些变化了,为此我还专门做了一个ppt,当初是计划在4月12日那天讲的,结果因为莫名其妙的原因导致没有语音以致放弃在LiveMeeting上的这次讲课,也导致了本篇的产生。
新增了项目模板
在创建Web项目时可以看到增加了更多的Web项目模板
在VS2008中对应的情况如下:
在新模板中有如下改进:
基础MemberShip功能。在大多数网站和应用程序中需要进行认证,因此在新模板中增加了认证功能使得用户能在Web项目中队身份认证快速上手,有关身份验证的模块的文件都放在Account文件夹下;
增加了默认的母版页。使用母版页能比较方便地统一网站网页的展示,如涉及到网页顶部、用户登录状态显示及菜单部分,默认的母版页文件名为Site.master;
增加了默认的css样式文件。使用css样式文件能使我们很方便地调整网站风格,在新建网站时会增加一个名为Site.css的样式文件,它位于Styles文件夹下;
迷你的web.config文件。在VS2010中web.config文件都很小,大部分的配置都被放在machine.config文件中;
集成jQuery。jQuery是一个非常强大的javascript类库,它可以让Web开发人员很方便地操作XHTML文档,在VS2008需要安装SP1才支持,而在VS2010中就直接支持了,jQuery类库文件在Scripts文件夹下。
通过上面的做法,使我们的网站组成结构都相似,这样更加便于维护(不像早期的版本,大家存放这类文件的文件夹各不相同)。
更好的Javascript及HTML代码智能感知
在以前版本的VS中对Javascript智能感知支持是比较差的,并且也没有对HTML代码段的支持,但是现在在VS2010中提供了这样的功能。
VS2010中对JavaScript脚本智能感知作了改进,能感知到本页中的函数名和变量
VS2010中提供了HTML代码段支持
对服务器控件的ID的增强控制
我们知道一个ASP.NET服务器控件有三个ID,即:ID,ClientID和UniqueID。
其中ID为服务器控件的服务器标示,在服务器代码中通过ID来唯一区分服务器控件(因此在同一个页面中ID必须唯一);
ClientID是服务器控件在转化成HTML元素之后在客户端的ID,为了防止出现命名冲突,ASP.NET 为页上的各个服务器控件自动生成一个唯一的 ClientID 值。ClientID 值是通过连接控件的 ID 值和它的父控件的 UniqueID 值生成的。生成的 ID 的各个部分以下划线字符 (_) 分隔;
UniqueID是服务器控件的唯一的、以分层形式限定的标识符,它也是服务器控件转化成HTML元素之后在客户端的name标识。
有时候我们要在客户端使用Javascript通过HTML元素的id来操作HTML元素,如果服务器控件在数据绑定控件中,那么它最终对应的HTML元素的id和我们平常使用的大不一样,这使我们操作起来很不方便,特别是我们在用javascript实现数据的全选反选时不方便,因为在操作单个控件时我们还可以按如下方式编写javascript代码:
<script type="text/javascript"><!--
function DoSomething(){
alert('<%= Control.ClientID %>');
}
// --></script>
而在ASP.NET中提供了对服务器控件的对应的HTML元素的id的控制更强了,增加了ClientIDMode属性来控制。下面是一个展示ClientIDMode属性用法的例子,在服务端编码如下:
<asp:GridView ID="gvUserList" runat="server" AutoGenerateColumns="False">
<Columns>
<asp:TemplateField HeaderText="UserId_AutoId">
<ItemTemplate>
<asp:Label runat="server" ID="lb1" ClientIDMode="AutoID" Text='<%#Eval("UserId") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UserId_Static">
<ItemTemplate>
<asp:Label runat="server" ID="lb1" ClientIDMode="Static" Text='<%#Eval("UserId") %>' />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UserId_Predictable">
<ItemTemplate>
<asp:Label runat="server" ID="lb1" ClientIDMode="Predictable" Text='<%#Eval("UserId") %>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
如果我们进行数据绑定之后再查看生成的HTML源代码,会看到类似的部分:
<table cellspacing="0" rules="all" border="1" id="MainContent_gvUserList" style="border-collapse:collapse;" mce_style="border-collapse:collapse;">
<tr>
<th scope="col">UserId_AutoId</th><th scope="col">UserId_Static</th><th scope="col">UserId_Predictable</th>
</tr>
<tr>
<td><span id="ctl00_MainContent_gvUserList_ctl02_lb1">136</span></td>
<td><span id="lb1">136</span></td>
<td><span id="MainContent_gvUserList_lb1_0">136</span></td>
</tr>
....
</table>
可以看到ClientIDMode="AutoID" 时控件的客户端ID和我们在早期的ASP.NET没有什么区别;而ClientIDMode="Static"时控件的客户端ID不会发生变化;在ClientIDMode="Predictable"时控件的客户端ID中还带有数据行标识(如:id="MainContent_gvUserList_lb1_0"中的“0”即标识在数据源中的位置为0,即第一条记录)。
通过指定ClientIDMode属性可以让我们很方便控制服务器端控件最终生成的HTML元素的ID,这一点也是相当方便的。
ViewState视图控制
在以前的开发过程中,ViewState是一个让人又爱又恨的东西:用得好了可以带来很大的方便,用得不好也会带来很大的麻烦。我们知道ViewState在客户端是以隐藏域的形式存储的,为了保密起见会对ViewState进行Base64编码后保存在客户端隐藏域中,提交到服务器后服务器端再对网页中的这部分隐藏数据进行Base64解码,提取保存在隐藏域中的控件数据。因为HTTP请求是无状态非连接的,使用了ViewState就可以在同一个页面的不同请求间保存数据,这么做确实比较方便;但是如果如果控件的状态数据很多,就会导致ViewState的体积变大,影响了响应速度。而在ASP.NET4.0以前的版本中是默认启用的,为了减轻ViewState带来的不利影响,我们不得不在页面中或者控件中设置ViewState是否启用(尽管我们可以在web.config中设置全局禁用ViewState,但是有的时候我们可能还间接使用这个属性,比如在管理后台因为我们操作较少,对性能关注不如前台)。
现在在ASP.NET 4.0中这一切得到了改变,在ASP.NET4.0对ViewState的属性默认是不启用的,但是你可以针对某个控件单独启用(尽管你可能在控件的更高级别设置为禁用)。
看下面的部分代码:
<asp:Panel runat="server" ID="panel" ViewStateMode="Disabled">
<asp:Label runat="server" ID="lbEnableViewState" ViewStateMode="Enabled" Text="set in code"/><br />
<asp:Label runat="server" ID="lbDisableViewState" Text="set in code"/>
</asp:Panel>
<asp:Button ID="Button1" runat="server" Text="btnTestViewState" />
后台代码如下:
if (!Page.IsPostBack)
{
lbDisableViewState.Text = "The viewstate id enabled";
lbEnableViewState.Text = "The viewstate id enabled";
}
页面第一次运行效果如下:
因为第一次运行时符合!Page.IsPostBack判断,所以Text属性都被设置成了“The viewstate id enabled”,当点击页面的按钮时,变成如下效果:
出现这样结果的原因是因为第一个Label的文字通过ViewState保存了,而第二个Label控件被禁用了,所以页面刷新后状态数据没有得到保存。
SEO优化支持
针对国外的网站,搜索引擎都会读取网页中的description和keywords字段,这样搜索引擎通过这两个meta节点来识别我们的网页,比单纯通过网页中词语的频率分析来得知网页的内容要容易得多,因此如果我们很好地利用了这两个东东在搜索同样的内容时可能我们的网页显示会比较靠前,这就是所谓的SEO(Search Engine Optimization,即搜索引擎优化)技术,在以前的ASP.NET中我们没有办法直接设置每个网页的这两个属性,但是在ASP.NET4.0中我们可以直接在代码中操作了。
如下面的代码:
if (!Page.IsPostBack)
{
Page.Title = "在这里可以设置页面的Title";
Page.MetaDescription = "在这里可以设置页面的Description";
Page.MetaKeywords = "在这里可以设置页面的keywords,做SEO";
}
这样最终网页的HTML源代码中我们可以看到如下部分:
<meta name="description" content="在这里可以设置页面的Description" />
<meta name="keywords" content="在这里可以设置页面的keywords,做SEO" />
这样做搜索引擎优化就方便多了。
需要说明两点:1、SEO涉及到的东西比较多,操作起来也比较复杂,设置description和keywords仅仅是一个方面。2、由于国人在SEO方面孜孜不倦的追求,以致到了几乎走火入魔的地步,所以很多搜索引擎对国人网站中的这两个字段不是太感冒了。
路由功能
做过MVC的朋友可能熟悉路由功能,特别是ASP.NET MVC的朋友。我们知道按照常规方式对于用户名为zhoufoxcn的博客或者商店网址可能会是如下形式:
http://www.xxx.com/user.aspx?username=zhoufoxcn
http://www.xxx.com/user.aspx?userid=4419544(假如zhoufoxcn对应的userid为4419544)
这样非常不便于记忆,如果我们采用URL重写的方式可以变得更友好一点,比如:
http://www.xxx.com/user/zhoufoxcn.aspx(注取决于URL重写规则)
如果采用路由的话,可以让URL变得更友好一些,也更便于搜索引擎收录,比如:
http://www.xxx.com/user/zhoufoxcn
如果要在非ASP.NET MVC项目中使用路由,可以按照下面的步骤操作:
在应用ASP.NET程序启动时配置路由,ASP.NET应用程序启动时会执行在global.asax.cs中的Application_Start方法中的代码,我们可以这么写:
void Application_Start(object sender, EventArgs e)
{
//RouteTable.Routes.Ignore();
// Code that runs on application startup
#region 设置路由
//参数说明:
//路由名为"UserList",路由规则为"{UserList}","~/Default.aspx"是处理页面
RouteTable.Routes.Add("UserList", new Route("{UserList}/{page}", new PageRouteHandler("~/UserList2.aspx")));
#endregion
}
然后,在需要使用的地方这么写:
link.Text = "|" + i.ToString() + "|";//link为夜间中的HyperLink控件
string expression = String.Format("RouteName={0}, UserList={1}, page={2}", "UserList", "UserList", i);
link.NavigateUrl = RouteUrlExpressionBuilder.GetRouteUrl(this, expression);
这样就完成了路由功能的使用了。
总结:
除了上面提到的之外,在ASP.NET4.0中还增加了一些新的服务器控件,如QueryExtender等。利用ASP.NET4.0我们开发ASP.NET应用控制可以更灵活了,这样在满足不同场合的需要时也更方便了。