精進不休 .NET 4.0 (2) - asp.net 4.0 新特性之url路由

[索引頁]
[×××]


精進不休 .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,對數據源控件得到的數據作再檢索 
  • 其它新特性


示例
一、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 中
                        <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
        {
void Page_Load() 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
        {
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);
                }
        }
}
 
 
二、自定義 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
        {
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();
                }

                /// <summary>
                /// 將指定的 key ,作md5 加密後,拼出一個路徑,作爲保存此 key 對應的對象的文件(此例只作演示用)
                /// </summary>
                /// <param name= "key">緩存 key</param>
                /// <returns></returns>
string GetPathFromKey() 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>
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;
                }

                /// <summary>
                /// 在緩存中,根據指定的 key 獲取緩存對象
                /// </summary>
                /// <param name= "key">緩存 key</param>
                /// <returns></returns>
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;
                }

                /// <summary>
                /// 根據指定的 key 刪除緩存對象
                /// </summary>
                /// <param name= "key">緩存 key</param>
override void Remove() 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>
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);
                        }
                }

                /// <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
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);
                }
        }
}
 
 
三、表達式 <%: 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>
 
 
四、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
        {
void Page_Load() 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 { get; set; }
                         public string ProductName { get; set; }
                         public double ProductPrice { get; set; }
                }
        }
}
 
 
五、其餘新特性的簡單說明
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>
                一、Permanent Redirect - 能夠實現 301 跳轉
                <ul>
                        <li>Response.RedirectPermanent() - 永久性重定向(http 301)。</li>
                        <li>Response.Redirect() - 臨時性重定向(http 302)。</li>
                </ul>
        </p>
        <p>
                二、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>
                三、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= "<,>,*,%,&,:,\,?" requestValidationType= "Samples.MyValidator, Samples" encoderType= "Samples.MyEncoder, Samples" />
                </textarea>
        </p>
        <p>
                四、compilation 節點新增 targetFramework 屬性,用於指定程序運行的目標框架
                <br />
                <textarea>
                        <compilation targetFramework= "4.0" />
                </textarea>
        </p>
        <p>
                五、asp.net 4.0 結合 iis 7.5 可以使 web 應用程序自動啓動
                <br />
                在 web 程序中實現 System.Web.Hosting.IProcessHostPreloadClient 接口,用於被 iis 啓動
        </p>
        <p>
                六、Page 類中新增了兩個屬性,分別是 MetaDescription 和 MetaKeywords
        </p>
        <p>
                七、之前每一個可顯示的控件都有 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>
                八、web form 須要在頁面上寫入隱藏域(如爲了保存 ViewState 的隱藏域),在 asp.net 4.0 中系統將在這類的隱藏域外的 div 上標記一個名爲 aspNetHidden 的 css 類,以方便樣式控制
        </p>
        <p>
                九、ASP.NET Chart Control - 實例參考 http://code.msdn.microsoft.com/mschart
        </p>
</asp:Content>
 
 
相關文章
相關標籤/搜索