[索引页]
[×××]


精进不休 .NET 4.0 (2) - asp.net 4.0 新特性之url路由, 自定义CacheProvider, 新增的表达式<%: expression %>, QueryExtender控件, 其它新特性


作者: webabcd


介绍
asp.net 4.0 的新增功能
  • 在 web form 中做 url 路由 
  • 通过实现自定义的 CacheProvider ,来实现自定义的页面缓存逻辑 
  • 新增的表达式 <%: expression %> 相当于 <%= HttpUtility.HtmlEncode(expression) %> 
  • 控件 QueryExtender,对数据源控件获得的数据做再检索 
  • 其它新特性


示例
1、web form 中的 url 路由的 demo
Global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;

using System.Web.Routing;

namespace AspDotNet
{
         public class Global : System.Web.HttpApplication
        {
void Application_Start() void Application_Start(object sender, EventArgs e)
                {
                        // 关于 Routing 可以参考以前写的 http://webabcd.blog.51cto.com/1787395/341116
                        // 其中 PageRouteHandler 类的作用是将 URL 路由的功能集成到 Web Form 中
                        RouteTable.Routes.Add( "myRoute", new Route( "user/{userName}/{age}", new PageRouteHandler( "~/UrlRouting/Default.aspx")));

                        /* 对应的配置如下,在 machine.config 中
                        
                            
                                        "RoutingModule" type= "System.Web.Routing.UrlRoutingModule"/>    
                            

                        
                         */
                }
        }
}
 
UrlRouting/Default.aspx
<%@ Page Title= "" Language="C# " MasterPageFile="~/Site.Master " AutoEventWireup=" true"
        CodeBehind= "Default.aspx.cs" Inherits= "AspDotNet.UrlRouting.Default" %>

"Content1" ContentPlaceHolderID= "head" runat= "server">

"Content2" ContentPlaceHolderID= "ContentPlaceHolder1" runat= "server">
        
        "server" Text= "<%$ RouteValue:userName%>" />
        

        "server" Text= "<%$ RouteValue:age%>" />

        

<%--
对应的配置如下,在 machine.config 中

     "true" targetFrameworkMoniker= ".NETFramework,Version=v4.0">
            
                 "RouteValue" type= "System.Web.Compilation.RouteValueExpressionBuilder" />
            

    


--%>
 
UrlRouting/Default.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace AspDotNet.UrlRouting
{
         public partial class Default : System.Web.UI.Page
        {
void Page_Load() void Page_Load(object sender, EventArgs e)
                {
                        // 获取 url 路由而来的数据
                        // 配合以下逻辑的路由规则是: "user/{userName}/{age}"
                        Response.Write( "userName: " + RouteData.Values[ "userName"].ToString());
                        Response.Write( "
"
);
                        Response.Write( "age: " + RouteData.Values[ "age"].ToString());
                }
        }
}
 
UrlRouting/RouteUrlExpressionBuilderDemo.aspx
<%@ Page Title= "" Language="C# " MasterPageFile="~/Site.Master " AutoEventWireup=" true"
        CodeBehind= "RouteUrlExpressionBuilderDemo.aspx.cs" Inherits= "AspDotNet.UrlRouting.RouteUrlExpressionBuilderDemo" %>

"Content1" ContentPlaceHolderID= "head" runat= "server">

"Content2" ContentPlaceHolderID= "ContentPlaceHolder1" runat= "server">
        
        "lnk1" runat= "server" NavigateUrl= "<%$ RouteUrl:RouteName=myRoute, userName=webabcd, age=30 %>"
                Text= "goto" />
        


        "lnk2" runat= "server" Text= "goto" />

<%--
对应的配置如下,在 machine.config 中

     "true" targetFrameworkMoniker= ".NETFramework,Version=v4.0">
            
                 "RouteUrl" type= "System.Web.Compilation.RouteUrlExpressionBuilder"/>
            

    


--%>
 
UrlRouting/RouteUrlExpressionBuilderDemo.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.Web.Compilation;

namespace AspDotNet.UrlRouting
{
         public partial class RouteUrlExpressionBuilderDemo : System.Web.UI.Page
        {
void Page_Load() void Page_Load(object sender, EventArgs e)
                {
                        // 在代码中构造 url 路由的方式
                         string expression = String.Format( "RouteName={0}, userName={1}, age={2}", "myRoute", "webabcd", "30");
                        lnk2.NavigateUrl = RouteUrlExpressionBuilder.GetRouteUrl(this, expression);
                }
        }
}
 
 
2、自定义 CacheProvider
CachingEnhancement.aspx
<%-- OutputCache 目前不支持直接设置 providerName 属性 --%>
<%@ OutputCache Duration= "30" VaryByParam= "None" %>

<%@ Page Title= "" Language="C# " MasterPageFile="~/Site.Master " AutoEventWireup=" true"
        CodeBehind= "CachingEnhancement.aspx.cs" Inherits= "AspDotNet.CachingEnhancement" %>

"Content1" ContentPlaceHolderID= "head" runat= "server">

"Content2" ContentPlaceHolderID= "ContentPlaceHolder1" runat= "server">
        <%= DateTime.Now.ToString() %>
 
CachingEnhancement.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

using System.Web.Caching;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace AspDotNet
{
         public partial class CachingEnhancement : System.Web.UI.Page
        {
void Page_Load() void Page_Load(object sender, EventArgs e)
                {
                        
                }
        }

        // 重写 OutputCacheProvider 抽象类,以实现自定义的缓存实现(需要重写的方法是 Add, Get, Remove, Set
        // 本 Demo 演示了,如何开发一个自定义的 CacheProvider,来实现将数据缓存到硬盘的功能
         public class FileCacheProvider : OutputCacheProvider
        {
                 private string _cachePathPrefix = @"c:\";

string MD5() string MD5( string s)
                {
                        var provider = new MD5CryptoServiceProvider();
                        var bytes = Encoding.UTF8.GetBytes(s);
                        var builder = new StringBuilder();

                        bytes = provider.ComputeHash(bytes);

                        foreach (var b in bytes)
                                builder.Append(b.ToString( "x2").ToLower());

                        return builder.ToString();
                }

                ///
                /// 将指定的 key ,做md5 加密后,拼出一个路径,做为保存此 key 对应的对象的文件(此例只做演示用)
                ///

                /// "key">缓存 key
                ///
string GetPathFromKey() string GetPathFromKey( string key)
                {
                        return _cachePathPrefix + MD5(key) + ".txt";
                }

                ///
                /// 将对象放入自定义的缓存中
                ///

                /// "key">缓存 key
                /// "entry">缓存对象
                /// "utcExpiry">缓存的过期时间
                ///
override object Add() override object Add( string key, object entry, DateTime utcExpiry)
                {
                        var path = GetPathFromKey(key);

                        // 指定的 key 已被缓存了,则不做任何处理
                         if (File.Exists(path))
                                return entry;

                        // 将对象缓存到硬盘上的指定文件
                        using (var file = File.OpenWrite(path))
                        {
                                var item = new CacheItem { Expires = utcExpiry, Item = entry };
                                var formatter = new BinaryFormatter();
                                formatter.Serialize(file, item);
                        }

                        return entry;
                }

                ///
                /// 在缓存中,根据指定的 key 获取缓存对象
                ///

                /// "key">缓存 key
                ///
override object Get() override object Get( string key)
                {
                        var path = GetPathFromKey(key);

                        // 未找到缓存
                         if (!File.Exists(path))
                                return null;

                        CacheItem item = null;

                        // 如果有缓存的话,则取出缓存对象
                        using (var file = File.OpenRead(path))
                        {
                                var formatter = new BinaryFormatter();
                                item = (CacheItem)formatter.Deserialize(file);
                        }

                        // 缓存过期或缓存中无数据,则删除此缓存所对应的硬盘上的物理文件
                         if (item == null || item.Expires <= DateTime.Now.ToUniversalTime())
                        {
                                Remove(key);
                                return null;
                        }

                        return item.Item;
                }

                ///
                /// 根据指定的 key 删除缓存对象
                ///

                /// "key">缓存 key
override void Remove() override void Remove( string key)
                {
                        var path = GetPathFromKey(key);

                         if (File.Exists(path))
                                File.Delete(path);
                }

                ///
                /// 更新缓存
                ///

                /// "key">缓存 key
                /// "entry">缓存对象
                /// "utcExpiry">缓存的过期时间
override void Set() override void Set( string key, object entry, DateTime utcExpiry)
                {
                        var item = new CacheItem { Expires = utcExpiry, Item = entry };
                        var path = GetPathFromKey(key);

                        using (var file = File.OpenWrite(path))
                        {
                                var formatter = new BinaryFormatter();
                                formatter.Serialize(file, item);
                        }
                }

                ///
                /// 封装了需要被缓存的对象的一个可序列化的对象
                ///

                [Serializable]
                internal class CacheItem
                {
                        ///
                        /// 缓存对象
                        ///

                         public object Item;
                        
                        ///
                        /// 缓存对象的过期时间
                        ///

                         public DateTime Expires;
                }
        }
}
 
Web.config


        
        "AspNetInternalProvider">
                
                        
                        "FileCache" type= "AspDotNet.FileCacheProvider, AspDotNet"/>
                

        

 
Global.asax.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;

using System.Web.Routing;

namespace AspDotNet
{
         public class Global : System.Web.HttpApplication
        {
                // 根据 HttpContext 的不同,可以为其指定不同的 CacheProvider
override string GetOutputCacheProviderName() override string GetOutputCacheProviderName(HttpContext context)
                {
                        // 符合此条件的,则缓存的实现使用自定义的 FileCacheProvider
                        // 自定义缓存实现见 CachingEnhancement.aspx.cs
                        // CacheProvider 的配置见 web.config
                        // 页面的缓存时间见 CachingEnhancement.aspx
                         if (context.Request.Path.ToLower().EndsWith( "cachingenhancement.aspx"))
                                return "FileCache";
                         else
                                return base.GetOutputCacheProviderName(context);
                }
        }
}
 
 
3、表达式 <%: expression %> 的 demo
HtmlEncodedCodeExpressions.aspx
<%@ Page Title= "" Language="C# " MasterPageFile="~/Site.Master " AutoEventWireup=" true"
        CodeBehind= "HtmlEncodedCodeExpressions.aspx.cs" Inherits= "AspDotNet.HtmlEncodedCodeExpressions" %>

"Content1" ContentPlaceHolderID= "head" runat= "server">

"Content2" ContentPlaceHolderID= "ContentPlaceHolder1" runat= "server">
        
        <%--
                新增的一个表达式 <%: expression %> 相当于 <%= HttpUtility.HtmlEncode(expression) %>
        --%>

        <%= "strong" %>
        

        <%: "strong" %>
        

        <%= HttpUtility.HtmlEncode( "strong") %>

 
 
4、QueryExtender 控件的 demo
QueryExtenderDemo.aspx
<%@ Page Title= "" Language="C# " MasterPageFile="~/Site.Master " AutoEventWireup=" true"
        CodeBehind= "QueryExtenderDemo.aspx.cs" Inherits= "AspDotNet.QueryExtenderDemo" %>

"Content1" ContentPlaceHolderID= "head" runat= "server">

"Content2" ContentPlaceHolderID= "ContentPlaceHolder1" runat= "server">
        "GridView1" runat= "server" AutoGenerateColumns= "False" DataSourceID= "LinqDataSource1">
                
                        "ProductId" HeaderText= "ProductId" SortExpression= "ProductId" />
                        "ProductName" HeaderText= "ProductName" SortExpression= "ProductName" />
                        "ProductPrice" HeaderText= "ProductPrice" SortExpression= "ProductPrice" />
                

        

        "LinqDataSource1" runat= "server" ContextTypeName= "AspDotNet.QueryExtenderDemo"
                EntityTypeName= "AspDotNet.Product" TableName= "Data">
        


        
        "QueryExtender1" runat= "server" TargetControlID= "LinqDataSource1">
                "ProductName" SearchType= "EndsWith">
                        "String" DefaultValue= "0" />
                

        

 
QueryExtenderDemo.aspx.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace AspDotNet
{
         public partial class QueryExtenderDemo : System.Web.UI.Page
        {
void Page_Load() void Page_Load(object sender, EventArgs e)
                {

                }

                // 为 GridView 提供数据
                 public List Data
                {
                         get
                        {
                                Random random = new Random();

                                List products = new List();
                                 for (int i = 0; i < 100; i++)
                                {
                                        products.Add( new Product { ProductId = i + 1, ProductName = "名称" + i.ToString().PadLeft(2, '0'), ProductPrice = random.NextDouble() });
                                }

                                return products;
                        }
                }

                // 为 GridView 提供数据的实体类
                 public class Product
                {
                         public int ProductId { get; set; }
                         public string ProductName { get; set; }
                         public double ProductPrice { get; set; }
                }
        }
}
 
 
5、其他新特性的简单说明
Others.aspx
<%@ Page Title= "其它,一笔带过" Language= "C#" MasterPageFile= "~/Site.Master" AutoEventWireup= "true"
        CodeBehind= "Others.aspx.cs" Inherits= "AspDotNet.Others" %>

"Content1" ContentPlaceHolderID= "head" runat= "server">
        

"Content2" ContentPlaceHolderID= "ContentPlaceHolder1" runat= "server">
        


                1、Permanent Redirect - 可以实现 301 跳转
                


                            
  • Response.RedirectPermanent() - 永久性重定向(http 301)。

  •                         
  • Response.Redirect() - 临时性重定向(http 302)。

  •                 

        


        


                2、Session 压缩(设置 sessionState 节点的 compressionEnabled 属性)
                

                对于使用进程外会话状态服务器的会话状态提供程序,或者将会话状态保存在 sqlserver 数据库中的会话状态提供程序,现在为提高其效率新增了压缩 Session 数据的功能(使用System.IO.Compression.GZipStream来压缩数据),像如下这样的配置
                

                
        


        


                3、httpRuntime 节点的新增配置
                


                            
  • maxRequestPathLength - url 路径的最大长度(基于NTFS文件路径的最大长度就是 260)

  •                         
  • maxQueryStringLength - url 的最大长度

  •                         
  • requestPathInvalidChars - 指定 url 路径的无效字符

  •                         
  • requestValidationType - 继承 System.Web.Util.RequestValidator 抽象类,重写其 IsValidRequestString() 方法,以实现自定义的请求验证。在 requestValidationType 可以指定使用这个自定义的类

  •                         
  • encoderType - 重写 System.Web.Util.HttpEncoder,可以实现自定义的 html编码, url编码, http header编码。在 encoderType 指定这个自定义编码的类后,程序中所用到的 System.Web.HttpUtility 或 System.Web.HttpServerUtility 的相关方法将会使用自定义的编码实现

  •                 

                

                
        


        


                4、compilation 节点新增 targetFramework 属性,用于指定程序运行的目标框架
                

                
        


        


                5、asp.net 4.0 结合 iis 7.5 可使 web 应用程序自动启动
                

                在 web 程序中实现 System.Web.Hosting.IProcessHostPreloadClient 接口,用于被 iis 启动
        


        


                6、Page 类中新增了两个属性,分别是 MetaDescription 和 MetaKeywords
        


        


                7、以前每个可显示的控件都有 Enabled 属性(如果 Enabled= "false" 则对应的 HTML 为 disabled= "disabled"),但是 HTML 4.01 的标准是只有 input 才能有 disabled 属性
                


                            

  •                                 在 pages 节点中设置 controlRenderingCompatibilityVersion= "3.5",则所有可显示控件都会输出 disabled= "disabled"
                            

  •                         

  •                                 在 pages 节点中设置 controlRenderingCompatibilityVersion= "4.0",则只有 input 元素才会输出 disabled= "disabled",非 input 元素将会自动标记一个名为 aspnetdisabled 的 css 类
                            

  •                 

        


        


                8、web form 需要在页面上写入隐藏域(如为了保存 ViewState 的隐藏域),在 asp.net 4.0 中系统将在这类的隐藏域外的 div 上标记一个名为 aspNetHidden 的 css 类,以方便样式控制
        


        


                9、ASP.NET Chart Control - 实例参考 http://code.msdn.microsoft.com/mschart
        


 
 
OK
[×××]