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

[索引页]
[源码下载]


精进不休 .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
    {
        
protected void Application_Start(object sender, EventArgs e)
        {
            
// 关于 Routing 可以参考以前写的 http://www.cnblogs.com/webabcd/archive/2009/04/21/1440149.html
            
// 其中 PageRouteHandler 类的作用是将 URL 路由的功能集成到 Web Form 中
            RouteTable.Routes.Add("myRoute"new Route("user/{userName}/{age}"new PageRouteHandler("~/UrlRouting/Default.aspx")));

            
/* 对应的配置如下,在 machine.config 中
            <system.web>
               <httpmodule>
                    <add name="RoutingModule" type="System.Web.Routing.UrlRoutingModule"/> 
               </httpmodule>
            <system.web>
             
*/
        }
    }
}
 
UrlRouting/Default.aspx
代码
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
    CodeBehind
="Default.aspx.cs" Inherits="AspDotNet.UrlRouting.Default" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    
<!--
        在页面上获取 url 路由而来的数据的方法
        配合以下逻辑的路由规则是:"user/{userName}/{age}"
    
-->
    
<asp:Literal runat="server" Text="<%$ RouteValue:userName%>" />
    
<br />
    
<asp:Literal runat="server" Text="<%$ RouteValue:age%>" />

    
<!--
        另外,对于数据源控件来说,也多了一种参数类型 RouteParameter 
    
-->
</asp:Content>
<%--
对应的配置如下,在 machine.config 中
<system.web>
   
<compilation debug="true" targetFrameworkMoniker=".NETFramework,Version=v4.0">
      
<expressionBuilders>
         
<add expressionPrefix="RouteValue" type="System.Web.Compilation.RouteValueExpressionBuilder" />
      
</expressionBuilders>
   
</compilation>
<system.web>
--%>

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
    {
        
protected void Page_Load(object sender, EventArgs e)
        {
            
// 获取 url 路由而来的数据
            
// 配合以下逻辑的路由规则是:"user/{userName}/{age}"
            Response.Write("userName: " + RouteData.Values["userName"].ToString());
            Response.Write(
"<br />");
            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" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    
<!--
        在页面上构造 url 路由的方式
    
-->
    
<asp:HyperLink ID="lnk1" runat="server" NavigateUrl="<%$ RouteUrl:RouteName=myRoute, userName=webabcd, age=30 %>"
        Text
="goto" />
    
<br /><br />
    
<asp:HyperLink ID="lnk2" runat="server" Text="goto" />
</asp:Content>
<%--
对应的配置如下,在 machine.config 中
<system.web>
   
<compilation debug="true" targetFrameworkMoniker=".NETFramework,Version=v4.0">
      
<expressionBuilders>
         
<add expressionPrefix="RouteUrl" type="System.Web.Compilation.RouteUrlExpressionBuilder"/>
      
</expressionBuilders>
   
</compilation>
<system.web>
--%>

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
    {
        
protected 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" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    
<%= DateTime.Now.ToString() %>
</asp:Content>

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
    {
        
protected void Page_Load(object sender, EventArgs e)
        {
            
        }
    }

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

        
private 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();
        }

        
/// <summary>
        
/// 将指定的 key ,做md5 加密后,拼出一个路径,做为保存此 key 对应的对象的文件(此例只做演示用)
        
/// </summary>
        
/// <param name="key">缓存 key</param>
        
/// <returns></returns>
        private string GetPathFromKey(string key)
        {
            
return _cachePathPrefix + MD5(key) + ".txt";
        }

        
/// <summary>
        
/// 将对象放入自定义的缓存中
        
/// </summary>
        
/// <param name="key">缓存 key</param>
        
/// <param name="entry">缓存对象</param>
        
/// <param name="utcExpiry">缓存的过期时间</param>
        
/// <returns></returns>
        public 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;
        }

        
/// <summary>
        
/// 在缓存中,根据指定的 key 获取缓存对象
        
/// </summary>
        
/// <param name="key">缓存 key</param>
        
/// <returns></returns>
        public 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;
        }

        
/// <summary>
        
/// 根据指定的 key 删除缓存对象
        
/// </summary>
        
/// <param name="key">缓存 key</param>
        public override void Remove(string key)
        {
            var path 
= GetPathFromKey(key);

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

        
/// <summary>
        
/// 更新缓存
        
/// </summary>
        
/// <param name="key">缓存 key</param>
        
/// <param name="entry">缓存对象</param>
        
/// <param name="utcExpiry">缓存的过期时间</param>
        public 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);
            }
        }

        
/// <summary>
        
/// 封装了需要被缓存的对象的一个可序列化的对象
        
/// </summary>
        [Serializable]
        
internal class CacheItem
        {
            
/// <summary>
            
/// 缓存对象
            
/// </summary>
            public object Item;
            
            
/// <summary>
            
/// 缓存对象的过期时间
            
/// </summary>
            public DateTime Expires;
        }
    }
}

Web.config
代码
<!--缓存配置-->
<caching>
    
<!--默认的缓存实现是 AspNetInternalProvider(即 asp.net 自带的基于内存的缓存实现方式)-->
    
<outputCache defaultProvider="AspNetInternalProvider">
        
<providers>
            
<!--
                新增一个缓存的 provider 配置
                具体实现见 CachingEnhancement.aspx.cs
            
-->
            
<add name="FileCache" type="AspDotNet.FileCacheProvider, AspDotNet"/>
        
</providers>
    
</outputCache>
</caching>

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
        public 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" %>

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

    
<%= "<strong>strong</strong>" %>
    
<br />
    
<%"<strong>strong</strong>" %>
    
<br />
    
<%= HttpUtility.HtmlEncode("<strong>strong</strong>"%>

</asp:Content>


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

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="LinqDataSource1">
        
<Columns>
            
<asp:BoundField DataField="ProductId" HeaderText="ProductId" SortExpression="ProductId" />
            
<asp:BoundField DataField="ProductName" HeaderText="ProductName" SortExpression="ProductName" />
            
<asp:BoundField DataField="ProductPrice" HeaderText="ProductPrice" SortExpression="ProductPrice" />
        
</Columns>
    
</asp:GridView>
    
<asp:LinqDataSource ID="LinqDataSource1" runat="server" ContextTypeName="AspDotNet.QueryExtenderDemo"
        EntityTypeName
="AspDotNet.Product" TableName="Data">
    
</asp:LinqDataSource>

    
<!--
        QueryExtender - 和数据源控件结合使用,以对数据源控件中检索到的数据做再次检索
            SearchExpression - 根据指定的字段查找指定的数据
            RangeExpression - 在指定字段中查找指定范围的数据
            PropertyExpression - 查找某字段的值为某指定的值的数据
            OrderByExpression - 用于排序数据
            CustomExpression - 自定义查询表达式
    
-->
    
<asp:QueryExtender ID="QueryExtender1" runat="server" TargetControlID="LinqDataSource1">
        
<asp:SearchExpression DataFields="ProductName" SearchType="EndsWith">
            
<asp:Parameter Type="String" DefaultValue="0" />
        
</asp:SearchExpression>
    
</asp:QueryExtender>
</asp:Content>

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
    {
        
protected void Page_Load(object sender, EventArgs e)
        {

        }

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

                List
<Product> products = new List<Product>();
                
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 { getset; }
            
public string ProductName { getset; }
            
public double ProductPrice { getset; }
        }
    }
}


5、其他新特性的简单说明
Others.aspx
代码
<%@ Page Title="其它,一笔带过" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
    CodeBehind
="Others.aspx.cs" Inherits="AspDotNet.Others" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
    
<style>
        body
        
{
            font-size
: 12px;
        
}
        textarea
        
{
            width
: 99%;
        
}
    
</style>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    
<p>
        1、Permanent Redirect - 可以实现 301 跳转
        
<ul>
            
<li>Response.RedirectPermanent() - 永久性重定向(http 301)。</li>
            
<li>Response.Redirect() - 临时性重定向(http 302)。</li>
        
</ul>
    
</p>
    
<p>
        2、Session 压缩(设置 sessionState 节点的 compressionEnabled 属性)
        
<br />
        对于使用进程外会话状态服务器的会话状态提供程序,或者将会话状态保存在 sqlserver 数据库中的会话状态提供程序,现在为提高其效率新增了压缩 Session 数据的功能(使用System.IO.Compression.GZipStream来压缩数据),像如下这样的配置
        
<br />
        
<textarea rows="6">
            
<sessionState
              
mode="SqlServer"
              sqlConnectionString
="data source=dbserver;Initial Catalog=aspnetstate"
              allowCustomSqlDatabase
="true"
              compressionEnabled
="true"
            
/>
        
</textarea>
    
</p>
    
<p>
        3、httpRuntime 节点的新增配置
        
<ul>
            
<li>maxRequestPathLength - url 路径的最大长度(基于NTFS文件路径的最大长度就是 260)</li>
            
<li>maxQueryStringLength - url 的最大长度</li>
            
<li>requestPathInvalidChars - 指定 url 路径的无效字符</li>
            
<li>requestValidationType - 继承 System.Web.Util.RequestValidator 抽象类,重写其 IsValidRequestString() 方法,以实现自定义的请求验证。在 requestValidationType 可以指定使用这个自定义的类</li>
            
<li>encoderType - 重写 System.Web.Util.HttpEncoder,可以实现自定义的 html编码, url编码, http header编码。在 encoderType 指定这个自定义编码的类后,程序中所用到的 System.Web.HttpUtility 或 System.Web.HttpServerUtility 的相关方法将会使用自定义的编码实现</li>
        
</ul>
        
<br />
        
<textarea rows="2">
            
<httpRuntime maxRequestPathLength="260" maxQueryStringLength="2048" requestPathInvalidChars="&lt;,&gt;,*,%,&amp;,:,\,?" requestValidationType="Samples.MyValidator, Samples" encoderType="Samples.MyEncoder, Samples" />
        
</textarea>
    
</p>
    
<p>
        4、compilation 节点新增 targetFramework 属性,用于指定程序运行的目标框架
        
<br />
        
<textarea>
            
<compilation targetFramework="4.0" />
        
</textarea>
    
</p>
    
<p>
        5、asp.net 4.0 结合 iis 7.5 可使 web 应用程序自动启动
        
<br />
        在 web 程序中实现 System.Web.Hosting.IProcessHostPreloadClient 接口,用于被 iis 启动
    
</p>
    
<p>
        6、Page 类中新增了两个属性,分别是 MetaDescription 和 MetaKeywords
    
</p>
    
<p>
        7、以前每个可显示的控件都有 Enabled 属性(如果 Enabled="false" 则对应的 HTML 为 disabled="disabled"),但是 HTML 4.01 的标准是只有 input 才能有 disabled 属性
        
<ul>
            
<li>
                在 pages 节点中设置 controlRenderingCompatibilityVersion="3.5",则所有可显示控件都会输出 disabled="disabled"
            
</li>
            
<li>
                在 pages 节点中设置 controlRenderingCompatibilityVersion="4.0",则只有 input 元素才会输出 disabled="disabled",非 input 元素将会自动标记一个名为 aspnetdisabled 的 css 类
            
</li>
        
</ul>
    
</p>
    
<p>
        8、web form 需要在页面上写入隐藏域(如为了保存 ViewState 的隐藏域),在 asp.net 4.0 中系统将在这类的隐藏域外的 div 上标记一个名为 aspNetHidden 的 css 类,以方便样式控制
    
</p>
    
<p>
        9、ASP.NET Chart Control - 实例参考 http://code.msdn.microsoft.com/mschart
    
</p>
</asp:Content>


OK
[源码下载]
posted @ 2010-05-20 08:54  webabcd  阅读(7041)  评论(11编辑  收藏  举报