﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园--------來自寒冷的國度</title><link>http://www.cnblogs.com/Harlan/</link><description>跳舞吧，像没有人欣赏一样；唱歌吧，像没有人聆听一样;生活吧，像今天是末日一样；去爱吧，像不曾受伤一样 ......</description><language>zh-cn</language><lastBuildDate>Thu, 21 Aug 2008 17:20:46 GMT</lastBuildDate><pubDate>Thu, 21 Aug 2008 17:20:46 GMT</pubDate><ttl>60</ttl><item><title>自己寫的一個流量分析（用存儲過程實現）</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/20/1203218.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Tue, 20 May 2008 03:23:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/20/1203218.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1203218.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/20/1203218.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1203218.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1203218.html</trackback:ping><description><![CDATA[<p><font face="Verdana">set ANSI_NULLS ON<br />
set QUOTED_IDENTIFIER ON<br />
go</font></p>
<p><font face="Verdana">/*<br />
後端流量統計<br />
*/<br />
Create&nbsp;procedure [dbo].[P_SiteVisitCount]<br />
as<br />
begin<br />
&nbsp;set nocount on<br />
&nbsp;declare @FirstDate varchar(10),@Today varchar(10)<br />
&nbsp;declare @TempFirstDate datetime,@TempToday datetime<br />
&nbsp;declare @ThisDayVisit int ,&nbsp; @MaxVisitDay varchar(20)<br />
&nbsp;declare @ThisMonthVisit int ,&nbsp; @MaxVisitMonth varchar(20)<br />
&nbsp;declare @ThisYearVisit int ,&nbsp; @MaxVisitYear varchar(20)<br />
&nbsp;declare @VisitCount int<br />
&nbsp;declare @AvgDayVisit int , @AvgMonthVisit int, @AvgYearVisit int<br />
&nbsp;declare @Days int , @Months int , @Years int<br />
&nbsp;<br />
&nbsp;select @TempFirstDate = min(VisitDate) from T_SiteVisit <br />
&nbsp;set @TempToday = getdate() </font></p>
<p><font face="Verdana">&nbsp;set @FirstDate = convert(varchar,@TempFirstDate,111) --啟用日<br />
&nbsp;set @Today = convert(varchar,@TempToday,111)&nbsp;&nbsp; --本日<br />
&nbsp;select @VisitCount = sum(VisitCount) from T_SiteVisit --總訪問數<br />
&nbsp;</font></p>
<p><font face="Verdana">&nbsp;set @Days = datediff(day,@FirstDate,@Today) + 1<br />
&nbsp;set @Months = datediff(month,@FirstDate,@Today) + 1<br />
&nbsp;set @Years = datediff(year,@FirstDate,@Today) + 1<br />
&nbsp;<br />
&nbsp; <br />
&nbsp;set @AvgDayVisit = @VisitCount/@Days&nbsp;&nbsp;--平均日訪數<br />
&nbsp;set @AvgMonthVisit = @VisitCount/@Months&nbsp;--平均月訪數<br />
&nbsp;set @AvgYearVisit = @VisitCount/@Years&nbsp;&nbsp;--平均年訪數</font></p>
<p><font face="Verdana">&nbsp;--本日訪問數<br />
&nbsp;select @ThisDayVisit = sum(VisitCount) from T_SiteVisit <br />
&nbsp;where convert(varchar,VisitDate,111) = convert(varchar,getdate(),111)</font></p>
<p><font face="Verdana">&nbsp;--本月訪問數<br />
&nbsp;select @ThisMonthVisit = sum(VisitCount) from T_SiteVisit <br />
&nbsp;where datepart(year,VisitDate) = datepart(year,getdate()) and <br />
&nbsp;datepart(month,VisitDate) = datepart(month,getdate()) </font></p>
<p><font face="Verdana">&nbsp;--本年訪問數<br />
&nbsp;select @ThisYearVisit = sum(VisitCount) from T_SiteVisit <br />
&nbsp;where datepart(year,VisitDate) = datepart(year,getdate())</font></p>
<font face="Verdana">
<p><br />
&nbsp;--最大日訪問數<br />
&nbsp;select top 1 @MaxVisitDay = convert(varchar,VisitCount) + '(' + <br />
&nbsp;convert(varchar,VisitDate,111) + ')' from T_SiteVisit order by VisitCount desc <br />
&nbsp;</p>
<p>&nbsp;--最大月訪數<br />
&nbsp;select top 1 @MaxVisitMonth = convert(varchar,MonthVisit) + '(' + Date + ')'<br />
&nbsp;from (<br />
&nbsp;select&nbsp; MonthVisit = sum(VisitCount),<br />
&nbsp;Date = convert(varchar,datepart(year,VisitDate)) + '/' + convert(varchar,datepart(month,VisitDate))<br />
&nbsp;&nbsp;&nbsp; from T_SiteVisit <br />
&nbsp;group by&nbsp; convert(varchar,datepart(year,VisitDate)) + '/' + convert(varchar,datepart(month,VisitDate))<br />
&nbsp;) T order by&nbsp; MonthVisit desc </p>
<p>&nbsp;--最大年訪數<br />
&nbsp;select top 1 @MaxVisitYear = convert(varchar,YearVisit) + '(' + Date + ')' <br />
&nbsp;from (<br />
&nbsp;select&nbsp; YearVisit = sum(VisitCount),<br />
&nbsp;Date = convert(varchar,datepart(year,VisitDate)) from T_SiteVisit <br />
&nbsp;group by&nbsp; datepart(year,VisitDate)<br />
&nbsp;) T order by YearVisit desc </p>
<p>&nbsp;select <br />
&nbsp;FirstDate = @FirstDate, <br />
&nbsp;Today = @Today,<br />
&nbsp;ThisDayVisit = @ThisDayVisit,<br />
&nbsp;ThisMonthVisit = @ThisMonthVisit,<br />
&nbsp;ThisYearVisit = @ThisYearVisit,<br />
&nbsp;AvgDayVisit = @AvgDayVisit,<br />
&nbsp;AvgMonthVisit = @AvgMonthVisit,<br />
&nbsp;AvgYearVisit = @AvgYearVisit,&nbsp;<br />
&nbsp;MaxVisitDay = @MaxVisitDay,<br />
&nbsp;MaxVisitMonth = @MaxVisitMonth,<br />
&nbsp;MaxVisitYear = @MaxVisitYear,<br />
&nbsp;VisitCount = @VisitCount</p>
<p>&nbsp;select&nbsp; No = row_number()over(order by T.MenuID),T.*&nbsp; from (<br />
&nbsp;select distinct T1.MenuID,<br />
&nbsp;SitePathName = dbo.F_GetSiteNameByMenuID(T1.MenuID),<br />
&nbsp;ThisMonthVisit = T3.VisitCount,<br />
&nbsp;VisitCount = T2.VisitCount from T_UnitVisit<br />
&nbsp;T1 inner join <br />
&nbsp;(<br />
&nbsp;&nbsp;select MenuID,VisitCount=sum(VisitCount) from T_UnitVisit group by MenuID <br />
&nbsp;) T2 on T1.MenuID = T2.MenuID<br />
&nbsp;inner join <br />
&nbsp;(<br />
&nbsp;&nbsp;select MenuID,VisitCount=sum(VisitCount) from T_UnitVisit <br />
&nbsp;&nbsp;where datepart(year,VisitDate) = datepart(year,getdate()) and <br />
&nbsp;&nbsp;datepart(month,VisitDate) = datepart(month,getdate())<br />
&nbsp;&nbsp;group by&nbsp; MenuID,<br />
&nbsp;&nbsp;datepart(year,VisitDate),<br />
&nbsp;&nbsp;datepart(month,VisitDate)<br />
&nbsp;) T3 on T1.MenuID = T3.MenuID<br />
&nbsp;)T<br />
&nbsp;order by T.MenuID<br />
&nbsp;<br />
end<br />
<br />
表結构如下：<font face="Verdana"><br />
/****** 物件:&nbsp; Table [dbo].[T_SiteVisit]&nbsp;&nbsp;&nbsp; 指令碼日期: 05/20/2008 11:17:59 ******/<br />
SET ANSI_NULLS ON<br />
GO<br />
SET QUOTED_IDENTIFIER ON<br />
GO<br />
CREATE TABLE [dbo].[T_SiteVisit](<br />
&nbsp;[VisitId] [int] IDENTITY(1,1) NOT NULL,<br />
&nbsp;[VisitDate] [datetime] NOT NULL,<br />
&nbsp;[VisitCount] [int] NOT NULL CONSTRAINT [DF_T_SiteVisit_VisitCount]&nbsp; DEFAULT ((0)),<br />
&nbsp;CONSTRAINT [PK_T_SiteVisit] PRIMARY KEY CLUSTERED <br />
(<br />
&nbsp;[VisitId] ASC<br />
)WITH (PAD_INDEX&nbsp; = OFF, STATISTICS_NORECOMPUTE&nbsp; = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS&nbsp; = ON, ALLOW_PAGE_LOCKS&nbsp; = ON) ON [PRIMARY]<br />
) ON [PRIMARY]<br />
</font></font></p>
<img src ="http://www.cnblogs.com/Harlan/aggbug/1203218.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41822/" target="_blank">[新闻]第一财经周刊:当前互联网世界正处无秩序时代</a>]]></description></item><item><title>如何讓 Lynx 純文字瀏覽器讀取 UTF-8 的 ASP.NET 網頁 </title><link>http://www.cnblogs.com/Harlan/archive/2008/05/19/1202317.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Mon, 19 May 2008 01:00:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/19/1202317.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1202317.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/19/1202317.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1202317.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1202317.html</trackback:ping><description><![CDATA[<p><strong>需求 for 身心障礙同胞</strong> </p>
<blockquote>
<p>在國內卻有許多身心障礙同胞使用 Lynx 這套軟體，最近因為我們公司正在積極建置一個無障礙的網站，光是想到 UTF-8 編碼的網頁無法讓這些身心障礙同胞使用到我們製作的網站服務，就覺得內心實在有股衝動想趕快解決這個問題！ </p>
</blockquote>
<p><strong>需求 for 製作無障礙網站的 ASP.NET 2.0 開發人員</strong> </p>
<blockquote>
<p>我想大多數 ASP.NET 開發人員不懂 Linux 作業系統，唯一能使用 Lynx 軟體測試的方式，就是在 Windows 主機上使用 <a title="Cygwin (另開視窗)" href="http://www.cygwin.com/" target="_blank">Cygwin<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -799px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/green/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" src="http://i.ixnp.com/images/v3.30/t.gif"  alt="" /></a> + <a title="Lynx Information (另開視窗)" href="http://lynx.browser.org/" target="_blank">Lynx<img class="snap_preview_icon" id="snap_com_shot_link_icon" style="border-top-width: 0px; padding-right: 0px; background-position: -799px 0px; display: inline; padding-left: 0px; font-weight: normal; border-left-width: 0px; min-height: 0px; left: auto; float: none; background-image: url(http://i.ixnp.com/images/v3.30/theme/green/palette.gif); visibility: visible; border-bottom-width: 0px; padding-bottom: 0px; margin: 0px; vertical-align: top; width: 14px; line-height: normal; padding-top: 1px; background-repeat: no-repeat; font-style: normal; font-family: 'trebuchet ms', arial, helvetica, sans-serif; position: static; top: auto; height: 12px; background-color: transparent; border-right-width: 0px; text-decoration: none; maxheight: 2000px; maxwidth: 2000px; minwidth: 0px; cssfloat: none" src="http://i.ixnp.com/images/v3.30/t.gif"  alt="" /></a> 軟體進行測試，不過我今天研究出來一個最簡單、最容易、最省時省力的方式，讓你的 ASP.NET 網站伺服器看到使用 Lynx 上網的瀏覽者，就改以 BIG5 的方式回應輸出編碼字集！ </p>
</blockquote>
<p><strong>解決方案</strong> </p>
<blockquote>
<p>在 ASP.NET 2.0 新增了一個特殊的資料夾，叫做 App_Browsers，ASP.NET 會使用這些檔案來辨識個別瀏覽器並判斷它們的功能與應該回應的方式。 </p>
<p>你只要在你的 Web Application 根目錄建立這個目錄，並建立一個 Lynx.browser 檔案，檔案裡面的內容如下： </p>
<p>
<div class="code">[code:html]<br />
<span class="rem">&lt;!--</span> <span class="rem">&nbsp;&nbsp;&nbsp; You can find existing browser definitions at</span> <span class="rem">&nbsp;&nbsp;&nbsp; &lt;windir&gt;\Microsoft.NET\Framework\&lt;ver&gt;\CONFIG\Browsers</span> <span class="rem">--&gt;</span><br />
<span class="kwrd">&lt;</span><span class="html">browsers</span><span class="kwrd">&gt;</span><br />
&nbsp; <span class="kwrd">&lt;</span><span class="html">browser</span> <span class="attr">id</span><span class="kwrd">="Lynx"</span> <span class="attr">parentID</span><span class="kwrd">="Default"</span><span class="kwrd">&gt;</span><br />
&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">identification</span><span class="kwrd">&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">userAgent</span> <span class="attr">match</span><span class="kwrd">="Lynx/\d+\.\d+"</span> <span class="kwrd">/&gt;</span><br />
&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;/</span><span class="html">identification</span><span class="kwrd">&gt;</span><br />
&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">capture</span><span class="kwrd">&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">userAgent</span> <span class="attr">match</span><span class="kwrd">="Lynx/(?'version'(?'browserMajorVersion'\d+)\.(?'browserMinorVersion'\d+))"</span> <span class="kwrd">/&gt;</span><br />
&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;/</span><span class="html">capture</span><span class="kwrd">&gt;</span><br />
&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">capabilities</span><span class="kwrd">&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">capability</span> <span class="attr">name</span><span class="kwrd">="browser"</span> <span class="attr">value</span><span class="kwrd">="Lynx"</span> <span class="kwrd">/&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">capability</span> <span class="attr">name</span><span class="kwrd">="version"</span> <span class="attr">value</span><span class="kwrd">="${version}"</span> <span class="kwrd">/&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">capability</span> <span class="attr">name</span><span class="kwrd">="majorVersion"</span> <span class="attr">value</span><span class="kwrd">="${browserMajorVersion}"</span> <span class="kwrd">/&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">capability</span> <span class="attr">name</span><span class="kwrd">="minorVersion"</span> <span class="attr">value</span><span class="kwrd">="${browserMinorVersion}"</span> <span class="kwrd">/&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">capability</span> <span class="attr">name</span><span class="kwrd">="preferredRequestencoding"</span> <span class="attr">value</span><span class="kwrd">="big5"</span> <span class="kwrd">/&gt;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;</span><span class="html">capability</span> <span class="attr">name</span><span class="kwrd">="preferredResponseencoding"</span> <span class="attr">value</span><span class="kwrd">="big5"</span> <span class="kwrd">/&gt;</span><br />
&nbsp;&nbsp;&nbsp; <span class="kwrd">&lt;/</span><span class="html">capabilities</span><span class="kwrd">&gt;</span><br />
&nbsp; <span class="kwrd">&lt;/</span><span class="html">browser</span><span class="kwrd">&gt;</span><br />
<span class="kwrd">&lt;/</span><span class="html">browsers</span><span class="kwrd">&gt;</span><br />
[/code]</div>
<p>&nbsp;</p>
<p><br />
<strong>夠簡單吧！</strong>這要照這樣子做，你的網站只要遇到 Lynx Browser 上網，馬上就可以「自動」變成 Big5 編碼摟！ <strong>真心感謝 ASP.NET 這個漂亮的 Web 開發架構！</strong> </p>
</blockquote>
<p><strong>注意事項</strong> </p>
<ul>
    <li>
    <div>如果在你的網頁中有使用到以下這個 meta 標籤，請將他移除：<br />
    <br />
    <div class="code">[code:html]<br />
    <span class="kwrd">&lt;</span><span class="html">meta</span> <span class="attr">http-equiv</span><span class="kwrd">="Content-Type"</span> <span class="attr">content</span><span class="kwrd">="text/html; charset=utf-8"</span><span class="kwrd">&gt;</span><br />
    [/code]</div>
    <br />
    </div>
    <li>
    <div>並將以下的程式碼加到你的 MasterPage 或 Page 的 Code Behind 的 Page_Load 事件中：<br />
    <br />
    <div class="code">[code:c#]<br />
    <span class="kwrd">public</span> <span class="kwrd">partial</span> <span class="kwrd">class</span> MasterPage : System.Web.UI.MasterPage<br />
    {<br />
    &nbsp;&nbsp;&nbsp; <span class="kwrd">protected</span> <span class="kwrd">void</span> Page_Load(<span class="kwrd">object</span> sender, EventArgs e)<br />
    &nbsp;&nbsp;&nbsp; {<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; HtmlMeta metaContentType = <span class="kwrd">new</span> HtmlMeta();<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metaContentType.HttpEquiv = "Content-Type";<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">if</span> (Request.Browser.Browser == "Lynx")<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metaContentType.Content = "text/html; charset=big5";<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="kwrd">else</span><br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; metaContentType.Content = "text/html; charset=utf-8";<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Page.Header.Controls.AddAt(0, metaContentType);<br />
    &nbsp;&nbsp;&nbsp; }<br />
    }<br />
    [/code]</div>
    <br />
    </div>
    <li>
    <div>另外說明一下，如果你的網頁中的外部載入檔案 ( *.css 或 *.js ) 的話，如果檔案是用 UTF-8 編碼且內容中有非 ASCII 的字元，也有可能在使用 big5 瀏覽時造成網頁發生問題！但 Lynx 本來就不支援 CSS 與 JavaScript，所以也沒這個問題啦！但誰知道以後的 Lynx 版本會不會支援這些功能！</div>
    </li>
</ul>
<img src ="http://www.cnblogs.com/Harlan/aggbug/1202317.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41820/" target="_blank">[新闻]Visual Studio 2008 SDK 1.1 发布</a>]]></description></item><item><title>WCF开发入门的六个步骤</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/17/1200920.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Sat, 17 May 2008 11:39:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/17/1200920.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1200920.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/17/1200920.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1200920.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1200920.html</trackback:ping><description><![CDATA[在这里我就用一个据于一个简单的场景：服务端为客服端提供获取客户信息的一个接口读取客户信息，来完成WCF开发入门的六个步骤。 <br />
1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 定义WCF服务契约
<p>A.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 项目引用节点右键添加System.ServiceModel引用。</p>
<p>B.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在代码文件里，添加以下命名空间的引用</p>
<p>using System.ServiceModel;</p>
<p>using System;</p>
<p>C.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 新建一个命为ICustomerService 接口，并添加一个获取客户信息的方法定义名为CustomerInfomation,返回字符串类型的客户信息。</p>
<p>D.&nbsp;&nbsp;&nbsp;&nbsp; 为接口ICustomerService添加ServiceContract的属性修饰使它成为WCF服务中公开的接口。 </p>
<p>E.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为方法CustomerInfomation添加OperationContract的属性修饰使它成为WCF服务公开接口中公开的成员。</p>
<p>F.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 代码：</p>
<p><br />
&nbsp;1 using System;<br />
&nbsp;2 <br />
&nbsp;3 using System.ServiceModel;<br />
&nbsp;4 <br />
&nbsp;5 namespace ConWCF<br />
&nbsp;6 <br />
&nbsp;7 {&nbsp;&nbsp; [ServiceContract(Namespace = "<a href="http://microsoft.servicemodel.samples/">http://microsoft.servicemodel.samples/</a>")]<br />
&nbsp;8 <br />
&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp; public interface CustomerService<br />
10 <br />
11&nbsp;&nbsp;&nbsp;&nbsp; { <br />
12 <br />
13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [OperationContract]<br />
14 <br />
15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String CustomerInformation();<br />
16 <br />
17&nbsp;&nbsp;&nbsp;&nbsp; }<br />
18 <br />
19 }<br />
20 </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 实现WCF服务契约 <br />
&nbsp;</p>
<p>实现WCF服务契约很简单，就是实现上一步聚定义的WCF服务契约定义的接口就可以。下面看代码</p>
<p><br />
&nbsp;1 using System;<br />
&nbsp;2 <br />
&nbsp;3 using System.ServiceModel;<br />
&nbsp;4 <br />
&nbsp;5 namespace ConWCF<br />
&nbsp;6 <br />
&nbsp;7 {&nbsp;&nbsp; [ServiceContract(Namespace = "<a href="http://microsoft.servicemodel.samples/">http://microsoft.servicemodel.samples/</a>")]<br />
&nbsp;8 <br />
&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp; public interface ICustomerService<br />
10 <br />
11&nbsp;&nbsp;&nbsp;&nbsp; { <br />
12 <br />
13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [OperationContract]<br />
14 <br />
15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; String CustomerInformation();<br />
16 <br />
17&nbsp;&nbsp;&nbsp;&nbsp; }<br />
18 <br />
19&nbsp;&nbsp;&nbsp;&nbsp; public class CustomerService:ICustomerService<br />
20 <br />
21&nbsp;&nbsp;&nbsp;&nbsp; {<br />
22 <br />
23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #region ICustomerService 成员<br />
24 <br />
25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string CustomerInformation()<br />
26 <br />
27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
28 <br />
29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return "这是客户的信息!";<br />
30 <br />
31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
32 <br />
33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion<br />
34 <br />
35&nbsp;&nbsp;&nbsp;&nbsp; }<br />
36 <br />
37 }<br />
38 <br />
39 </p>
<p>&nbsp;</p>
<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 启动WCF服务</p>
<p>A．添加一个应用程序配置文件，文件件名为App.config。</p>
<p>B．配置WCF服务的基本地址,如下所示</p>
<p>&lt;host&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;baseAddresses&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;addbaseAddress="<a href='http://localhost:8000/conwcfr"/'>http://localhost:8000/conwcfr"/</a>&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/baseAddresses&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/host&gt;</p>
<p>C．配置WCF服务的端口。Address=&#8220;&#8221;，意思就是使用上面配置的基本地址，当然也可以在这里指定。Bingding=&#8220;wsHttpBinding&#8221;,意思是WCF服务使用的是HTTP协议。再接下来就是配置WCF服务契约了（命名空间.服务契约接口名），如下所示:</p>
<p>&lt;endpointaddress=""</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binding="wsHttpBinding"</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; contract="ConWCF.ICustomerService" /&gt;</p>
<p>D．配置文件</p>
<p>E．启动服服就简单了</p>
<p>ServiceHost host = new ServiceHost(typeof(CustomerService));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host.Open();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("客户信息服务已启动");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("按任意键结束服务！");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.Read();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; host.Close();</p>
<p>F．当服务启动时，在IE栏中输入: <a href="http://localhost:8000/conwcfr">http://localhost:8000/conwcfr</a>,将会收到一些帮助的提示信息。</p>
<p><br />
G．异常：配置文件中的服务名称一定是：命名空间.实现WCF服务契约类的名称，否则将会发生找到不配置的异常。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;service</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="ConWCF.CustomerService"</p>
<p>&nbsp;&nbsp;&nbsp; 异常信息: Service 'ConWCF.CustomerService' has zero application (non-infrastructure) endpoints. This might be because no configuration file was found for your application, or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.</p>
<p>这个异常搞得我昏了半天，害得我以为从IIS、端口到配置环境排除错误,就是搞不明白为什么会跟类的命称联系起来。不过，最终也解决了。</p>
<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 创建一个基本的WCF客服端</p>
<p>WCF服务端创建好啊，创建客户端就容易多了，直接用SVCUTIL 命令行工具去完成代码的生成。我安装了WINDOWS SDK，其带了一个CMDShell 命令行工具，打开后就可以运行SVCUTIL命令，这个命令是运行于 framework 3.0以上环境。查看详细帮助信息可以输入:svcutil /?,回车。</p>
<p>1． 启动上几步骤创建好的WCF服务端。</p>
<p>2． 在CMDShell工具中用CD 转到你要存放客户端代码的目录下，输入以下命令生成代码和配置文件。</p>
<p>D:"client&gt;svcutil /language:c# /out:CustomerClient.cs /config:app.config http:/</p>
<p>/localhost:8000/conwcfr</p>
<p>上面命令指定了要生成代码的语言，代码文件和配置文件名，WCF服务端地址，注意运行命令时必须确定WCF服务端正在运行中。</p>
<p>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WCF客服端基本配置</p>
<p>WCF客户端配置就是配置调用WCF服务端的协议，输传宽带，服务地址，安全等等信息。下面就上一步骤命令自动生成的配置文件。</p>
<p><br />
&nbsp;1 &lt;?xml version="1.0" encoding="utf-8"?&gt;<br />
&nbsp;2 &lt;configuration&gt;<br />
&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp; &lt;system.serviceModel&gt;<br />
&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bindings&gt;<br />
&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;wsHttpBinding&gt;<br />
&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;binding name="WSHttpBinding_ICustomerService" closeTimeout="00:01:00"<br />
&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"<br />
&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"<br />
&nbsp;9&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxBufferPoolSize="524288" maxReceivedMessageSize="65536"<br />
10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"<br />
11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; allowCookies="false"&gt;<br />
12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"<br />
13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; maxBytesPerRead="4096" maxNameTableCharCount="16384" /&gt;<br />
14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;reliableSession ordered="true" inactivityTimeout="00:10:00"<br />
15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enabled="false" /&gt;<br />
16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;security mode="Message"&gt;<br />
17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;transport clientCredentialType="Windows" proxyCredentialType="None"<br />
18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; realm="" /&gt;<br />
19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;message clientCredentialType="Windows" negotiateServiceCredential="true"<br />
20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; algorithmSuite="Default" establishSecurityContext="true" /&gt;<br />
21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/security&gt;<br />
22&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/binding&gt;<br />
23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/wsHttpBinding&gt;<br />
24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bindings&gt;<br />
25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;client&gt;<br />
26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;endpoint address="<a href="http://localhost:8000/conwcfr">http://localhost:8000/conwcfr</a>" binding="wsHttpBinding"<br />
27&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bindingConfiguration="WSHttpBinding_ICustomerService" contract="ICustomerService"<br />
28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name="WSHttpBinding_ICustomerService"&gt;<br />
29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;identity&gt;<br />
30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;userPrincipalName value="30DA1D0B1D1E4D2\Administrator" /&gt;<br />
31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/identity&gt;<br />
32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/endpoint&gt;<br />
33&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/client&gt;<br />
34&nbsp;&nbsp;&nbsp;&nbsp; &lt;/system.serviceModel&gt;<br />
35 &lt;/configuration&gt;</p>
<p>&nbsp;</p>
<p>6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用WCF客户端</p>
<p>在客户端项目中项目引用节点右键添加System.ServiceModel引用. <br />
添加第四部中创建的客户端代码文件和配置文件。 <br />
客户端调用服务端的服务，只要创建生成客户端类的实例就可调用了，但要确认服务端正在起用状态，如下 <br />
&nbsp;</p>
<p>&nbsp;1using System;<br />
&nbsp;2<br />
&nbsp;3namespace ConWCFCustomerClient<br />
&nbsp;4<br />
&nbsp;5{<br />
&nbsp;6<br />
&nbsp;7&nbsp;&nbsp;&nbsp; class Program<br />
&nbsp;8<br />
&nbsp;9&nbsp;&nbsp;&nbsp; {<br />
10<br />
11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main(string[] args)<br />
12<br />
13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />
14<br />
15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; CustomerServiceClient client = new CustomerServiceClient();<br />
16<br />
17&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string message=client.CustomerInformation();<br />
18<br />
19&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(message);<br />
20<br />
21&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.Read();<br />
22<br />
23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
24<br />
25&nbsp;&nbsp;&nbsp; }<br />
26<br />
27}<br />
28//來自：<font face="Verdana">http://blog.csdn.net/mych/archive/2008/05/15/2448809.aspx</font></p>
 <img src ="http://www.cnblogs.com/Harlan/aggbug/1200920.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41821/" target="_blank">[新闻]死敌VMware变身微软认证计划新成员</a>]]></description></item><item><title>数据查询技术</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/16/1200653.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Fri, 16 May 2008 06:59:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/16/1200653.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1200653.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/16/1200653.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1200653.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1200653.html</trackback:ping><description><![CDATA[摘要: 4.1.2 SQL查询技术最常用的关系数据库系统通过称为SQL的语言对数据库进行查询和更新。SQL的含义是&#8220;结构化查询语言（Structured Query Language）&#8221;。SQL中最简单的查询就是从某个关系中查找满足某种条件的一些元组。这种查询类似于关系代数中的选择。这种简单的查询，同几乎所有的SQL查询一样，使用了具有SQL特性的三个关键字：SELECT、FROM&nbsp;&nbsp;<a href='http://www.cnblogs.com/Harlan/archive/2008/05/16/1200653.html'>阅读全文</a><img src ="http://www.cnblogs.com/Harlan/aggbug/1200653.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41819/" target="_blank">[新闻]英特尔雅虎开发网络计算机频道</a>]]></description></item><item><title>页面刷新特征</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/16/1200589.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Fri, 16 May 2008 06:31:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/16/1200589.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1200589.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/16/1200589.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1200589.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1200589.html</trackback:ping><description><![CDATA[来分析这样一种实际情况，即，在HTTP处理程序处理请求之前对请求进行筛选，这有助于实现一个原本不可能的特征。回发机制有一个严重的缺陷——如果用户刷新当前显示页面，则服务器上所采取的最后一个动作将盲目地重复。例如，如果作为前一次发送的结果添加了一个新记录，则应用程序会在另一次回发时试图插入一个完全相同的记录。当然，这会导致插入完全相同的记录，因而应当产生一个异常。这一缺陷自Web编程最先出现时就已经存在了，ASP.NET无疑不会引入它。要实现非重复的动作，必须采取一些对策，本质上将任何关键的服务器端操作转换为一个幂等性。在代数中，如果一个操作不管对它执行多少次结果都不变，我们就说该操作是幂等的。例如，看一看如下SQL命令：
<p>DELETE FROM employees WHERE employeeid=9</p>
<p>我们可以对该命令连续执行1000次，但是最多只会删掉1个记录，即满足WHERE子句中设定的标准的记录。另请考虑如下命令：</p>
<p>INSERT INTO employees VALUES (...)</p>
<p>每次执行该命令，都有可能把一个新记录添加到employees表中。如果存在自动编码的键列或者非惟一的列，尤其会出现这种情况。如果表设计要求键是惟一的并且明确加以规定，则第2次运行该命令时会抛出一个SQL异常。</p>
<p>虽然刚才考虑的特殊情况通常在数据访问层(data access layer，简称DAL)解决，但是它的基本模式代表了大多数Web应用程序的一个常见方案。因此，待研究的问题是：怎样查明页面是因为一个显式的用户操作被回传，还是因为用户按下了F5键或页面刷新工具栏按钮呢？</p>
<p>1. 页面刷新操作的基本原理</p>
<p>页面刷新操作是一种内部浏览器操作，对此浏览器不会根据事件或回调提供任何外部通知。从技术上讲，页面刷新是由最新请求的&#8220;简单的&#8221;重复组成的。浏览器缓存它所服务的最新请求，并在用户按下页面刷新键或按钮时重新显示。我所知道的浏览器不会为页面刷新事件提供任何类型通知——即使有，无疑也不是一种公认标准。</p>
<p>据此可知，服务器端代码(例如，ASP.NET、经典ASP或ISAPI DLL)无法将刷新请求与一般的提交或回发请求相区分。为了帮助ASP.NET检测和处理页面刷新，我们需要创建外围机制，使两个在其他方面相同的请求看起来不同。所有已知的浏览器都是通过重新发送最后发送的HTTP请求来实现刷新；为了使该副本不同于原始请求，一个额外的服务必须添加其他参数，而ASP.NET页面必须能够捕获它们。</p>
<p>我考虑了一些附加需求。解决方案不应依赖会话状态，而且不应使服务器内存负荷太重。它应该是相对容易部署的，而且应尽量不引人注目。</p>
<p>2. 解决方案的概要描述</p>
<p>本解决方案基于如下思想：每个请求被分配一个标签号，而HTTP模块将跟踪它处理的每个不同页面里最后服务的标签。如果该页面持有的标签号小于该页面的最后服务的标签，则只能表明服务了相同的请求——即，页面刷新。该解决方案由两个构造块组成：一个HTTP模块和一个自定义的页面类，前者对标签号作初步检查，后者自动地将一个渐进的标签号码添加到每个服务过的页面。使该特征起作用涉及两个步骤：首先，注册该HTTP模块；其次，在相关的应用程序中改变每个页面的基本的代码隐藏类以检测浏览器刷新。</p>
<p>HTTP模块位于HTTP运行库环境的中间，登记应用程序中的一个资源的每个请求。页面第一次被请求时(不是回发时)，不分配任何标签。HTTP模块将生成一个新的标签号，并把它存储在HttpContext对象的Items集合中。此外，该模块将最后服务的标签的内部计数器初始化为0。随后该页面每次被请求时，该模块都将最后服务的标签与页面标签进行比较。如果页面标签更新一些，则该请求被认为是一次普通的回发；否则，它将被标记为一次页面刷新。表2.6总结了这两种场景及其相关的操作。</p>
<p align="center">表2.6&nbsp; 场景和动作</p>
<div align="center">
<div align="center">
<table style="width: 411.1pt; border-top-style: none; border-right-style: none; border-left-style: none; border-collapse: collapse; border-bottom-style: none" cellspacing="0" cellpadding="0" width="548" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1.5pt solid; padding-left: 5.4pt; background: #d9d9d9; padding-bottom: 0cm; width: 213.05pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; border-left-style: none" valign="top" width="284">
            <p>场&nbsp;&nbsp;&nbsp; 景</p>
            </td>
            <td style="padding-right: 5.4pt; border-top: windowtext 1.5pt solid; padding-left: 5.4pt; background: #d9d9d9; padding-bottom: 0cm; width: 213.05pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; border-right-style: none; border-left-style: none" valign="top" width="284">
            <p>动&nbsp;&nbsp;&nbsp; 作</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 213.05pt; border-top-style: none; padding-top: 0cm; border-bottom: windowtext 1pt solid; border-left-style: none" valign="top" width="284">
            <p>页面没有相关的标签</p>
            <p>●非刷新</p>
            </td>
            <td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 213.05pt; border-top-style: none; padding-top: 0cm; border-bottom: windowtext 1pt solid; border-right-style: none; border-left-style: none" valign="top" width="284">
            <p>最后服务的标签的计数器设置为0</p>
            <p>生成用于当前页面的下一个请求的标签，并存储在Items集合中</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 213.05pt; border-top-style: none; padding-top: 0cm; border-bottom: windowtext 1.5pt solid; border-left-style: none" valign="top" width="284">
            <p>页面有一个关联的标签</p>
            <p style="margin-left: 6.5pt; text-indent: -6.5pt">●如果页面关联的标签小于最后服务的标签，则发生页面刷新</p>
            </td>
            <td style="padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; width: 213.05pt; border-top-style: none; padding-top: 0cm; border-bottom: windowtext 1.5pt solid; border-right-style: none; border-left-style: none" valign="top" width="284">
            <p>最后服务的标签的计数器设置为页面关联的标签。</p>
            <p>生成用于当前页面的下一个请求的标签，并存储在Items集合中</p>
            </td>
        </tr>
    </tbody>
</table>
</div>
</div>
<p style="text-indent: 21.6pt">为了确保每个请求(除了第一次以外)都有一个合适的标签号，需要得到页面类的一些帮助。这就是为什么需要将每个打算支持该特征的页面的代码隐藏类设置为一个特定类——这是我们稍候将讨论的一个过程。该页面类将从HTTP模块接收两种不同的信息：要存储在随页面一起传送的一个隐藏字段中的下一个标签，以及该请求是否为页面刷新的信息。作为对开发人员的一项增值服务，代码隐藏类将提供一个额外的布尔属性：IsRefreshed，以允许开发人员了解请求是页面刷新还是常规回发。</p>
<p style="margin-left: 72pt; text-indent: -72pt"><img height="18" alt="*" src="http://book.csdn.net/bookfiles/172/02/image008.jpg" width="22" />重要提示 &nbsp;&nbsp; HttpContext类上的Items集合是一个载体集合，是为了让HTTP模块将信息向下传递给实际负责服务请求的页面和HTTP处理程序而特意建立的。我们这里采用的HTTP模块在Items集合中设置两个数据项。一个数据项让页面知道请求是否为页面刷新；另一个数据项让页面知道下一个标签号是什么。让HTTP模块将下一个标签号传递给页面，满足使页面类的行为尽可能地简单和线性的目的，从而将大部分实现和执行负担转移给HTTP模块。</p>
<p>3. 解决方案的实现</p>
<p>我刚刚概述的解决方案有几个问题有待研究。首先，状态是必需的，我们把它保存在哪里？其次，对每个输入请求都将调用一个HTTP模块。如何区分对相同页面的请求呢？如何把信息传递给页面呢？你希望页面有多大的智能呢？</p>
<p>显然，这里所列的每个问题，都可以用不同于此处所介绍的方法进行设计和实现。为了得到一个可行的解决方案，这里作出的所有设计选择应当被认为是任意的，如果需要对该代码进行重新加工以更好地满足自己的目的，可以用等效的策略替换它。下一个实例中给出的代码版本，融入了我一直以来所收集的最宝贵的建议。这些建议之一如前一个重要提示所述，尽量将代码移到HTTP模块中。</p>
<p>如下代码展示了该HTTP模块的实现：</p>
<p>public class RefreshModule : IHttpModule</p>
<p>{</p>
<p style="text-indent: 14.7pt">public void Init(HttpApplication app) {</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">app.BeginRequest += new EventHandler(OnAcquireRequestState);</p>
<p style="text-indent: 14.7pt">}</p>
<p style="text-indent: 14.7pt">public void Dispose() {</p>
<p style="text-indent: 14.7pt">}</p>
<p style="text-indent: 14.7pt">void OnAcquireRequestState(object sender, EventArgs e) {</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">HttpApplication app = (HttpApplication) sender;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">HttpContext ctx = app.Context;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">RefreshAction.Check(ctx);</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">return;</p>
<p style="text-indent: 14.7pt">}</p>
<p>}</p>
<p>该模块监听BeginRequest事件，结束调用RefreshAction辅助类上的Check方法。</p>
<p>public class RefreshAction</p>
<p>{</p>
<p style="text-indent: 14.7pt">static Hashtable requestHistory = null;</p>
<p style="text-indent: 14.7pt">// Other string constants defined here</p>
<p style="text-indent: 14.7pt">M</p>
<p style="text-indent: 14.7pt">public static void Check(HttpContext ctx) {</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">// Initialize the ticket slot</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">EnsureRefreshTicket(ctx);</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">// Read the last ticket served in the session (from Session)</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">int lastTicket = GetLastRefreshTicket(ctx);</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">// Read the ticket of the current request (from a hidden field)</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">int thisTicket = GetCurrentRefreshTicket(ctx, lastTicket);</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">// Compare tickets</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">if (thisTicket &gt; lastTicket ||</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">(thisTicket==lastTicket &amp;&amp; thisTicket==0)) {</p>
<p style="margin-left: 2cm; text-indent: 23.1pt">UpdateLastRefreshTicket(ctx, thisTicket);</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">ctx.Items[PageRefreshEntry] = false;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">}</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">else</p>
<p style="margin-left: 2cm; text-indent: 23.1pt">ctx.Items[PageRefreshEntry] = true;</p>
<p style="text-indent: 14.7pt">}</p>
<p style="text-indent: 14.7pt">// Initialize the internal data store</p>
<p style="text-indent: 14.7pt">static void EnsureRefreshTicket(HttpContext ctx)</p>
<p style="text-indent: 14.7pt">{</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">if (requestHistory == null)</p>
<p style="margin-left: 24.15pt; text-indent: 48.3pt">requestHistory = new Hashtable();</p>
<p style="text-indent: 14.7pt">}</p>
<p style="text-indent: 14.7pt">// Return the last-served ticket for the URL</p>
<p style="text-indent: 14.7pt">static int GetLastRefreshTicket(HttpContext ctx)</p>
<p style="text-indent: 14.7pt">{</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">// Extract and return the last ticket</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">if (!requestHistory.ContainsKey(ctx.Request.Path))</p>
<p style="margin-left: 38.85pt; text-indent: 35.7pt">return 0;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">else</p>
<p style="margin-left: 2cm; text-indent: 18.9pt">return (int) requestHistory[ctx.Request.Path];</p>
<p style="text-indent: 14.7pt">}</p>
<p style="text-indent: 14.7pt">// Return the ticket associated with the page</p>
<p style="text-indent: 14.7pt">static int GetCurrentRefreshTicket(HttpContext ctx, int lastTicket)</p>
<p style="text-indent: 14.7pt">{</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">int ticket;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">object o = ctx.Request[CurrentRefreshTicketEntry];</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">if (o == null)</p>
<p style="text-indent: 50.4pt">ticket = lastTicket;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">else</p>
<p style="text-indent: 50.4pt">ticket = Convert.ToInt32(o);</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">ctx.Items[RefreshAction.NextPageTicketEntry] = ticket + 1;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">return ticket;</p>
<p>}</p>
<p>// Store the last-served ticket for the URL</p>
<p>static void UpdateLastRefreshTicket(HttpContext ctx, int ticket)</p>
<p>{</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">requestHistory[ctx.Request.Path] = ticket;</p>
<p style="text-indent: 14.7pt">}</p>
<p>}</p>
<p>Check方法操作如下：它将最后服务的标签(如果有)与页面提供的标签进行比较。该页面将标签号存储在一个通过Request对象接口读入的隐藏字段中。HTTP模块维护一个散列表，服务的每个不同的URL都有一个表项。该散列表中的值存储该URL的最后服务的标签。</p>
<p><sub><img height="27" src="http://book.csdn.net/bookfiles/172/02/image002.jpg" width="18"  alt="" /></sub>&nbsp;注意&nbsp;&nbsp;&nbsp; Item索引器属性，来设置最后服务的标签，因为Item重写已有的项。如果数据项已经存在，则Add方法只是返回。</p>
<p>除了创建HTTP模块，我们还需要安排一个页面类，以用作需要检测浏览器刷新的页面的基类。下面给出了这个页面类的代码：</p>
<p>// Assume to be in a custom namespace</p>
<p>public class Page : System.Web.UI.Page</p>
<p>{</p>
<p style="text-indent: 14.7pt">public bool IsRefreshed {</p>
<p style="text-indent: 23.1pt">get {</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">HttpContext ctx = HttpContext.Current;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">object o = ctx.Items[RefreshAction.PageRefreshEntry];</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">if (o == null)</p>
<p style="margin-left: 24.15pt; text-indent: 44.1pt">return false;</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">return (bool) o;</p>
<p style="text-indent: 14.7pt">}</p>
<p>}</p>
<p>// Handle the PreRenderComplete event</p>
<p>protected override void OnPreRenderComplete(EventArgs e) {</p>
<p style="text-indent: 8.4pt">base.OnPreRenderComplete(e);</p>
<p style="text-indent: 8.4pt">SaveRefreshState();</p>
<p>}</p>
<p>// Create the hidden field to store the current request ticket</p>
<p>private void SaveRefreshState() {</p>
<p style="text-indent: 8.4pt">HttpContext ctx = HttpContext.Current;</p>
<p style="text-indent: 8.4pt">int ticket = (int) ctx.Items[RefreshAction.NextPageTicketEntry];</p>
<p style="text-indent: 8.4pt">ClientScript.RegisterHiddenField(</p>
<p style="text-indent: 16.8pt">RefreshAction.CurrentRefreshTicketEntry,</p>
<p style="text-indent: 16.8pt">ticket.ToString());</p>
<p style="text-indent: 4.2pt">}</p>
<p>}</p>
<p>该示例页面定义了一个新的公共布尔属性IsRefreshed。我们可以在代码中以使用IsPostBack或IsCallback那样的方法使用该属性。该实例页面重写了OnPreRenderComplete方法，用页面标签添加隐藏字段。如前所述，该页面标签是通过Items集合中的一个特别的(并且是任意命名的)项从HTTP模块中得到的。</p>
<p>图2.8展示了一个正在运行的示例页面。</p>
<p align="center"><img height="237" src="http://book.csdn.net/bookfiles/172/02/image013.jpg" width="418"  alt="" /></p>
<p align="center">图2.8&nbsp; 如果用户刷新浏览器的视图，页面没有重复一个敏感的动作</p>
<p style="text-indent: 21pt">下面是该页面的源代码。</p>
<p>public partial class TestRefresh : ProAspNet20.CS.Components.Page</p>
<p>{</p>
<p style="text-indent: 14.7pt">protected void AddContactButton_Click(object sender, EventArgs e)</p>
<p style="text-indent: 14.7pt">{</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">Msg.InnerText = "Added";</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">if (!this.IsRefreshed)</p>
<p style="margin-left: 2cm; text-indent: 14.7pt">AddRecord(FName.Text, LName.Text);</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">else</p>
<p style="margin-left: 2cm; text-indent: 14.7pt">Msg.InnerText = "Page refreshed";</p>
<p style="margin-left: 38.85pt; text-indent: 14.7pt">BindData();</p>
<p style="text-indent: 14.7pt">}</p>
<p style="text-indent: 14.7pt">M</p>
<p>}</p>
<p>IsRefreshed属性允许我们决定在一个回发动作被请求时要做什么。在上述代码中，如果页面正在刷新，则不调用AddRecord方法。不用说，IsRefreshed仅适用于这里介绍的自定义页面类。自定义页面类并非只是添加该属性，它还要添加隐藏字段，这是该机制起作用所必不可少的。<br />
來自&nbsp; ：&nbsp;&nbsp;&nbsp; <iframe style="margin-top: 0px; float: left" border="0" marginwidth="0" framespacing="0" marginheight="0" src="http://wz.csdn.net/vote.aspx?t=2.3.3%20%u9875%u9762%u5237%u65B0%u7279%u5F81%20-%20%u300AASP.NET%202.0%u9AD8%u7EA7%u7F16%u7A0B%u300B%20-%20%u514D%u8D39%u8BD5%u8BFB%20-%20book.csdn.net&amp;u=http%3A//book.csdn.net/bookfiles/172/1001727755.shtml" frameborder="0" noResize width="54" scrolling="no" height="75"></iframe>ASP.NET 2.0高级编程 一書</p>
<img src ="http://www.cnblogs.com/Harlan/aggbug/1200589.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41819/" target="_blank">[新闻]英特尔雅虎开发网络计算机频道</a>]]></description></item><item><title>利用js方法实现html静态页面间参数传递</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/13/1194875.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Tue, 13 May 2008 03:23:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/13/1194875.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1194875.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/13/1194875.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1194875.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1194875.html</trackback:ping><description><![CDATA[<h2>利用js方法实现html静态页面间参数传递<span class="f">&nbsp;</span></h2>
<div class="entry-body nerr" style="display: block">
<p>aa.htm是参数输入界面<br />
bb.htm是参数接收处理界面<br />
aa.htm<br />
&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;script&gt;<br />
function submit()<br />
{<br />
var input1 = document.getElementById("inputid");<br />
window.open("b.html?inputStr=" + input1.value);//传入参数<br />
}<br />
&lt;/script&gt;<br />
&lt;input type = "text" id = "inputid"&gt;<br />
&lt;input type = "button" onclick = "submit()" value = "提交"&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p>bb.htm:<br />
&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;script&gt;<br />
//获得参数的方法<br />
var request = <br />
{ <br />
QueryString : function(val) <br />
{ <br />
var uri = window.location.search; <br />
var re = new RegExp("" +val+ "=([^&amp;?]*)", "ig"); <br />
return ((uri.match(re))?(uri.match(re)[0].substr(val.length+1)):null); <br />
} <br />
} </p>
<p>&lt;/script&gt;</p>
<p>&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;script&gt;<br />
//调用方法获得参数<br />
var rt = request.QueryString("inputStr");<br />
alert(rt);<br />
&lt;/script&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt; </p>
</div>
<p id="trackback">你可以通过这个链接引用该篇文章:http://ranjunliu.bokee.com/viewdiary.13398085.html </p>
<img src ="http://www.cnblogs.com/Harlan/aggbug/1194875.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41818/" target="_blank">[新闻]Windows Live视频邮件9月9日开始测试</a>]]></description></item><item><title>基于功能更丰富的基础类构建您自己的 ASP.NET 页面</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/13/1194829.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Tue, 13 May 2008 03:06:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/13/1194829.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1194829.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/13/1194829.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1194829.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1194829.html</trackback:ping><description><![CDATA[<p><strong>摘要：</strong>通过继承可以在通用 Microsoft ASP.NET 类（例如 Page 类）中添加功能。这为您提供了一个公共场所，使您可以添加功能并将功能部署到所有页面上。在本文中，Dino 将向您介绍如何添加页面刷新处理、对冗长进程的支持以及使用 Page 类设置焦点控件。（本文包含一些指向英文站点的链接。请注意，在示例文件中，程序员的注释使用的是英文，本文中将其译为中文是为了便于读者理解。）</p>
<p><a id="ctl00_rs1_mainContentContainer_ctl01" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl01',this);" href="http://download.microsoft.com/download/E/2/A/E2AC0B6E-9283-45D0-BBCE-4CA1CE4CB3BF/MSDNBedrock.msi">下载本文的源代码</a>。</p>
<p>所有 Microsoft ASP.NET 页面均来自由 <strong>System.Web.UI.Page</strong> 类表示的通用基础页面。为了处理对 .aspx 资源的请求，ASP.NET 运行库将创建一个动态类，并使该类继承基础 <strong>Page</strong> 类，或继承其他反过来又继承基础 Page 类的类。如果在支持内含代码模型的 Microsoft Visual Studio .NET 2003 项目中创建页面，动态创建的 <strong>Page</strong> 类将继承内含代码类，而内含代码类反过来又继承基础 Page 类。</p>
<p>基础 <strong>Page</strong> 类实现典型的 ASP.NET 页面生命周期（加载-回发-渲染周期），并为衍生页面提供一组预定义的成员和功能，例如，回发检测、脚本插入、渲染和视图状态管理。 </p>
<p>总而言之，<strong>System.Web.UI.Page</strong> 类只是一个基础类，可用来定义一组通用的、最基本的功能和行为。在特定的应用程序中，页面很可能针对更多功能，并提供更强大的编程接口。有两种可能的扩展方式：对页面基础结构进行一般意义上的增强，或者针对应用程序而改进功能。前一种扩展的示例是用来表示页面菜单和菜单项的属性。针对应用程序的页面通常是根据由静态区域、通用区域和可自定义区域组成的逻辑&#8220;母版&#8221;页设计的。这些区域的内容可能因页面而异，它们通常通过模板、占位符和用户控件进行填充。 </p>
<p>请注意，在 Microsoft ASP.NET 2.0 中，母版页的引入大大简化了使用自定义和可编程属性和成员针对应用程序而创建页面的过程。 </p>
<p>但是，如果您需要为页面创建功能更丰富、更复杂的基础结构，应该怎么办？如何指示所有页面提供其他系统级别的功能，例如，检测 F5（刷新）键的功能？实现给定技巧所需的代码始终可以与每个特定页面的操作代码（包含在内含代码类中的代码）合并在一起。但是，即使只实现了两三个功能，生成的代码的质量已经开始类似于大家唾弃的意大利面条式代码了，这是非常危险的。您必须寻找其他方法。</p>
<h3 id="EKAA">构建功能更丰富的基础类</h3>
<p>一种更好的方法是创建新的基础 Page 类，用它来代替标准 System.Web.UI.Page 类。在本文中，我将介绍几项通用功能以及它们的一般实现，并将这些功能装入一个新的、功能更丰富的 Page 类中。我要介绍的功能包括： </p>
<ul>
    <li>
    <p>检测 F5（刷新）键。 </p>
    <li>
    <p>启动并控制一个需要立即向用户发送反馈页面的冗长操作。 </p>
    <li>
    <p>在加载页面时设置输入焦点。 </p>
    </li>
</ul>
<p>如果您经常光顾专门介绍 ASP.NET 的新闻组和社区站点，而且阅读了大量文章、书籍和新闻稿，那么您可能已经知道如何在 ASP.NET 1.x 应用程序上下文中分别实现上述各项功能。这里的问题是，如何通过一个组件和一个入口点同时提供所有这些功能。</p>
<p>通过定义自定义 Page 类，您只需付出最少的努力便可在新的 .aspx 页面上提供所有其他功能和服务并获得最大回报。使用 Visual Studio .NET 2003 创建的内含代码页面的声明方式如下：</p>
<pre>public class WebForm1 :System.Web.UI.Page
{
:
}
</pre>
<p>要使 Web 窗体类继承非默认的 Page 类，只需按照如下所示更改基础类型。</p>
<pre>public class WebForm1 :Msdn.Page
{
:
}
</pre>
<p>如果页面不是在 Visual Studio .NET 2003 中创建的或者使用了内嵌代码，那么可以通过 <strong>@Page</strong> 指令中的 <strong>Inherits</strong> 属性为该页面设置基础类型。</p>
<pre>&lt;% @Page Inherits="Msdn.Page" ... %&gt;
</pre>
<p>您可以按照此处所述逐个页面地更改 ASP.NET 页面的基础类型，也可以使用配置文件中的<strong> &lt;pages&gt; </strong>节点。</p>
<pre>&lt;pages pageBaseType="Msdn.Page" /&gt;
</pre>
<p>&lt;<strong>pages</strong>&gt; 节点的 <strong>pageBaseType</strong> 属性指示要用作所有动态创建的 Page 类的基础类型的类的名称和程序集。默认情况下，该属性在 machine.config 文件中被设置为 <strong>System.Web.UI.Page</strong>。您可以在应用程序的 web.config 文件中覆盖该设置。</p>
<p>下面让我们看看如何在实际应用中实现上述各项功能，以及如何将这些功能封装到一个无所不包的类中。<br />
</p>
<h3 id="EJAA">检测浏览器刷新</h3>
<p>概括介绍了当用户按下浏览器中的 F5 键刷新当前页面时，对这一过程进行检测所需的操作步骤。页面刷新是浏览器对特定用户操作（按 F5 键或单击&#8220;刷新&#8221;工具栏按钮）的响应。页面刷新操作是浏览器内部的一种操作，因为浏览器不会为事件或回调发出任何外部通知。从技术上讲，页面刷新是通过&#8220;简单&#8221;重复最新请求来实现的。换句话说，浏览器将缓存已处理的最新请求，并在用户单击页面刷新键时重新发布已处理的请求。 </p>
<p>正是因为所有浏览器（据我所知）不会为页面刷新事件提供任何类型的通知，所以服务器端的代码（例如，ASP.NET、典型 ASP 或 ISAPI DLL）根本无法区分<em>刷新</em>请求与一般的<em>提交</em>或<em>回发</em>请求。为了帮助 ASP.NET 检测和处理页面刷新，您需要构建能够使两个完全相同的请求看起来不同的环境机制。 </p>
<p>浏览器通过重新发送上次发送的 HTTP 有效负载来实现刷新，并使副本看起来与原始版本不同（这是一项额外服务，需要添加额外的参数并且 ASP.NET 页面必须能够缓存这些参数）。下图提供了我要构建的子系统的详细视图。</p>
<p><img alt="" src="http://msdn.microsoft.com/zh-cn/library/ms379557.bedrock_fig01(zh-cn,VS.80).gif" /> </p>
<div><strong>图</strong> <strong>1</strong> <strong>：</strong>为使刷新请求看起来与回发/提交请求不同而设置的机制</div>
<p>会话上下文中处理的每个请求获得一个唯一且递增的票证号码。ASP.NET 页面在生成响应之前生成票证，并将其存储在一个自定义的隐藏字段中发送给浏览器。当用户提交新请求（从而导致回发显示的页面）时，隐藏字段（如果有）将自动附着到服务器请求中。 </p>
<p>在 Web 服务器上，新的 HTTP 模块将截取 <strong>AcquireSessionState</strong> 事件，从隐藏字段中检索当前票证，并将其与内部缓存的上次处理的票证 ID 进行比较。（上次处理的票证存储在会话状态中。）如果当前票证大于上次处理的 ID，或者如果这两个值都为零，则说明请求是一般的提交或回发。除此之外，刷新 HTTP 模块不会执行其他操作，并原封不动地传递请求。 </p>
<p>如果上次处理的票证大于或等于当前票证，则将请求标识为页面刷新。在这种情况下，HTTP 模块将只在该请求的 HTTP 上下文的 <strong>Items</strong> 集合中创建一个新条目。在 ASP.NET 中，<strong>HttpContext</strong> 对象表示请求的上下文，并在请求的整个生命周期中始终存在。<strong>HttpContext</strong> 对象的 Items 属性是一个集合，可由 HTTP 模块、工厂处理程序和处理程序使用，用于将自定义信息转发给实际的页面对象。Items 集合中存储的所有内容对处理当前请求的过程中涉及到的所有组件均可见。这些信息的生命周期与请求的生命周期相同，因此，一旦生成响应，所有数据都将被销毁。通过使用<strong> HttpContext.Current</strong> 静态属性，可以从该过程中涉及到的任何类访问当前请求的 HTTP 上下文。</p>
<p>刷新 HTTP 模块将在 <strong>Items</strong> 集合中创建名为 <strong>IsPageRefreshed</strong> 的新条目。该条目的布尔值表明是通过一般的提交/回发请求页面还是通过刷新请求页面。下面的列表显示了刷新 HTTP 模块的实现。</p>
<pre>using System;
using System.Web;
using System.Web.SessionState;
namespace Msdn
{
public class RefreshModule :IHttpModule {
// IHttpModule::Init
public void Init(HttpApplication app)
{
// 注册管道事件
app.AcquireRequestState +=
new EventHandler(OnAcquireRequestState);
}
// IHttpModule::Dispose
public void Dispose() {}
// 确定是否正在处理 F5 或后退/前进操作
private void OnAcquireRequestState(object sender, EventArgs e) {
// 访问 HTTP 上下文
HttpApplication app = (HttpApplication) sender;
HttpContext ctx = app.Context;
// 检查 F5 操作
RefreshAction.Check(ctx);
return;
}
}
}
</pre>
<p><strong>RefreshAction</strong> 类包含用来确定当前请求是否是页面刷新的逻辑。如果确定为页面刷新，<strong>HttpContext</strong> 的 <strong>Items</strong> 集合中将包含一个新条目：<strong>IsPageRefreshed</strong> 设置为 <strong>true</strong>。</p>
<pre>public static void Check(HttpContext ctx)
{
// 初始化票证字段
EnsureRefreshTicket(ctx);
// 读取会话中上次处理的票证（从会话中）
int lastTicket = GetLastRefreshTicket(ctx);
// 读取当前请求的票证（从隐藏字段中）
int thisTicket = GetCurrentRefreshTicket(ctx);
// 比较两个票证
if (thisTicket &gt; lastTicket ||
(thisTicket==lastTicket &amp;&amp; thisTicket==0))
{
UpdateLastRefreshTicket(ctx, thisTicket);
ctx.Items[PageRefreshEntry] = false;
}
else
ctx.Items[PageRefreshEntry] = true;
}
</pre>
<p>隐藏字段和会话字段的名称在 <strong>RefreshAction</strong> 类中被设置为公共常量，并且可以在该类的外部使用。</p>
<p>应用程序页面如何利用此机制？什么时候检测页面刷新真正有用？HTTP 模块并不阻止任何请求，它只为最终 ASP.NET 页面添加更多信息以便处理请求。添加的信息包括表示页面刷新的布尔值。</p>
<h3 id="EIAA">使用页面刷新事件</h3>
<p>Web 页的用户通常只执行几个操作，而且从某种程度上讲，执行这些操作时心情都很愉快。这些操作包括&#8220;后退&#8221;、&#8220;前进&#8221;、&#8220;停止&#8221;和&#8220;刷新&#8221;。但这些操作构成了一种 Internet 浏览器的标准工具包。截取以及细分这些操作可能会对普遍认可的 Internet 操作带来某种&#8220;局限性&#8221;。对用户可能产生负面影响。 </p>
<p>另一方面，当用户刷新当前页面或退回到先前访问的页面时，会向服务器提交已处理过的请求，这有可能会打断应用程序状态的一致性。在这种情况下，也可能对应用程序产生负面影响。 </p>
<p>请设想以下情况：</p>
<p>您通过 <strong>DataGrid</strong> 显示数据，并在每一行中提供一个按钮，供用户删除所表示的数据行。尽管这是很常见的做法（轻轻点击，即可删除当前应用程序中实现的数据），但这种做法极其危险。用户很容易由于失误而单击了错误的按钮，从而破坏数据的一致性，而且如果他们在删除（不管是有意还是无意）之后刷新页面，则很可能会删除第二个行。 </p>
<p>当您刷新页面时，浏览器只重复上次发布的内容。从 ASP.NET 运行库的角度来看，只有一个新请求要处理。ASP.NET 运行库无法区分一般的请求和意外重复的请求。如果采取脱机工作的方式，并按内存中存储的 <strong>DataSet</strong> 中的位置删除记录，则很可能会多删除一条记录。如果上一个操作以 INSERT 结束，刷新页面更有可能会添加一条记录。 </p>
<p>这些示例清楚地暴露出某些有争议的设计问题，但它们反映了完全可能的情况。那么，阻止页面刷新最好的方式是什么呢？</p>
<p>本文前面讨论的机制可以预处理请求，并确定是否正在刷新页面。这些信息通过 <strong>HttpContext</strong> 对象传递给页面处理程序。在页面中，开发人员可以使用以下代码检索这些数据。</p>
<pre>bool isRefresh = (bool) HttpContext.Current.Items["IsPageRefreshed"];
</pre>
<p>但更好的做法是，如果使用自定义的、更有针对性的 <strong>Page</strong> 类，则可以将数据封装到一个更易于使用的属性中，即封装到 <strong>IsPageRefresh</strong> 属性中。</p>
<pre>public bool IsPageRefresh {
get {
object o =
HttpContext.Current.Items[RefreshAction.PageRefreshEntry];
if (o == null)
return false;
return (bool) o;
}
}
</pre>
<p>通过使 <strong>Page</strong> 类继承新的、功能更丰富的基础类（本例中为 Msdn.Page），可以通过新属性了解发出请求的真正原因。以下示例显示了如何实现不应在页面刷新时重复的某个关键操作。</p>
<pre>void AddContactButton_Click(object sender, EventArgs e) {
if (!IsPageRefresh)
AddContact(FName.Text, LName.Text);
BindData();
TrackRefreshState();
}
</pre>
<p>仅当在不刷新页面时才添加新联系人，换句话说，仅当用户按照常规方式单击&#8220;<strong>Add-Contact</strong>&#8221;（添加联系人）按钮时才会添加联系人。上述代码片断中有一个很奇怪的 <strong>TrackRefreshState</strong> 方法，它的作用是什么呢？</p>
<p>该方法更新票证计数器，并确保新页面响应包含带有最新票证的隐藏字段。在本例中，通过将会话状态中存储的值递增一来获取下一个票证。（这里只是随便使用了会话状态，最好不要使用会话状态，而使用更具扩展性的提供程序模型，就像在 ASP.NET 2.0 中一样。）</p>
<p>但是，关于 <strong>TrackRefreshState</strong> 方法（这是有意命名的，以便于大家回想起更熟悉的 <strong>TrackViewState</strong> 方法），主要有一点要说明。通过调用该方法，除了可以添加其他信息外，还可以将带有当前请求票证的隐藏字段添加到页面响应中。如果没有隐藏字段（参见图 1），刷新机制将无法检测下一个回发是刷新还是提交。换句话说，通过在回发事件处理程序中调用 <strong>TrackRefreshState</strong>，使得系统知道您要跟踪该操作（而且只跟踪该操作），以确定是否为页面刷新。这样，您只跟踪可能会出错的页面刷新，而且并不是所有页面刷新都会在会话生命周期内发生。</p>
<p>要利用页面刷新功能，只需在 Microsoft Visual Studio .NET 项目中添加一个新页面，然后打开内含代码文件并将页面的基础类更改为 Msdn.Page。接下来，在您执行不应刷新的操作时调用 <strong>TrackRefreshState</strong>（Msdn.Page 类的新的公共方法）。使用新的布尔属性 <strong>IsPageRefresh</strong> 检查刷新状态。</p>
<h3 id="EHAA">使用户在冗长操作过程中获得愉快体验</h3>
<p>有关如何在 Web 上跟踪特别耗时的操作这个问题，已经通过多篇文章和多次演讲为大家提供了各种解决方案。我所说的&#8220;耗时的操作&#8221;是指 Windows 窗体方案中通常需要进度栏的所有操作。在 Web 页上显示进度栏很容易出现问题。进度栏应该能够与服务器通信，以获取有助于更新进度的信息。此外，此操作不应通过回发或刷新元标记来完成，以免完全刷新页面。在任何情况下，均需要具备强大的动态 HTML 支持。 </p>
<p>要使用户在冗长操作过程中获得愉快体验，相对简单的方法就是显示一个中间反馈页面，为用户显示一些等待消息，最好是带点动画。此页面完全与上下文无关，但无疑要比加载新页面之前在空白页面上长时间显示一个沙漏更有用。 </p>
<p>要在冗长操作过程中显示一些反馈，有一种简单而有效的方法，它可以概括成以下几个步骤： </p>
<ul>
    <li>
    <p>一旦用户通过单击开始该任务，便将用户重定向到反馈页面。反馈页面必须知道实际执行任务的页面的 URL。此 URL（包括会话状态）可以通过查询字符串进行传递，也可以放置在可访问的数据存储中。 </p>
    <li>
    <p>开始加载反馈页面后，再重定向到工作页面。这种情况下，重定向是由页面的 onload Javascript 事件中的脚本完成的。浏览器加载并显示反馈页面，然后指向工作页面。页面开始执行冗长的任务，同时为用户显示反馈页面。 </p>
    <li>
    <p>根据需要，反馈页面可以很复杂并包括许多 UI 元素。它可以包含&#8220;请稍候...&#8221;消息或显示动画 GIF，或者借助某些动态 HTML 功能，显示某些看起来像是一个真正进度栏的内容。 </p>
    </li>
</ul>
<p>我特意创建了一个 <strong>LengthyAction</strong> 类来帮助管理冗长任务的开始。</p>
<pre>private const string UrlFormatString = "{0}?target={1}";
public static void Start(string feedbackPageUrl,
string targetPageUrl)
{
// 准备反馈页面的 URL
string url = String.Format(UrlFormatString,
feedbackPageUrl, targetPageUrl);
// 将调用重定向到反馈页面
HttpContext.Current.Response.Redirect(url);
}
</pre>
<p>该类的特点是只有一个静态方法，即 <strong>Start</strong>。<strong>Start</strong> 方法获取反馈页面和目标页面（即执行任务的页面）的 URL。该方法将两个参数合并成一个 URL 并进行重定向。</p>
<p>反馈页面可以包含您希望的任何用户界面，但必须满足几个关键的要求。该页面必须能够检索工作页面的名称，并提供一个可能的自动机制，以便通过脚本重定向到工作页面。我定义了一个自定义的基础 <strong>Page</strong> 类，并将这些功能内置在该类中。这样做时，我必须进行一些假定。特别是，我的实现假定工作页面的名称使用大家熟知的属性名称 <strong>target</strong> 通过查询字符串进行传递。目标页面的名称存储在名为 <strong>TargetURL</strong> 的公共属性中。此外，反馈页面提供名为 <strong>GetAutoRedirectScript</strong> 的函数。此函数的目的是返回通过脚本实现重定向所需的脚本代码。</p>
<pre>public string GetAutoRedirectScript() {
return String.Format("location.href='{0}';", TargetUrl);
}
</pre>
<p>为了使问题尽可能地简单，<strong>FeedbackBasePage</strong> 类还查找名为 <strong>Body</strong> 的通用 HTML 控件。这与您从以下标记中获取的完全一样。</p>
<pre>&lt;body runat="server" id="Body"&gt;
</pre>
<p>如果可以通过简单的方法为页面的正文标记编程，<strong>FeedbackBasePage</strong> 类将找到这种方法并自动添加 <strong>onload</strong> 属性；否则，您必须手动添加 <strong>onload</strong> 属性。要使反馈页面正常工作，此属性是必需的。</p>
<pre>HtmlGenericControl body = FindControl(BodyId) as HtmlGenericControl;
if (body != null)
body.Attributes["onload"] = GetAutoRedirectScript();
</pre>
<p>最后提供给浏览器的标记代码如下所示。</p>
<pre>&lt;body onload="location.href='lengthyop.aspx'"&gt;
</pre>
<p>让我们看看使用本文中讨论的类实现冗长操作需要执行哪些步骤。</p>
<p>首先引用所需的程序集，然后为触发操作的单击按钮编写以下事件处理程序。</p>
<pre>void ButtonLengthyOp_Click(object sender, EventArgs e) {
LengthyAction.Start("feedback.aspx", "work.aspx");
}
</pre>
<p>接下来，在项目中添加反馈页面。这是一个常规 Web 窗体页，您可以按照上文所述修改其 &lt;<strong>body</strong>&gt; 标记，并将基础类更改为 <strong>FeedbackBasePage</strong>。在您单击按钮开始进程之后以及显示结果之前，将显示反馈页面的用户界面，如下图所示。</p>
<p><img alt="" src="http://msdn.microsoft.com/zh-cn/library/ms379557.bedrock_fig02(zh-cn,VS.80).gif" /> </p>
<div><strong>图</strong> <strong>2</strong> <strong>：</strong>冗长操作的顺序</div>
<p>在本例中，我使用了一种跨页回发，这对特别冗长的操作来说是一种更普遍的方案。但是，这引发了传递视图状态以及工作页面完成其任务通常所需的参数的问题。您可以使用工作页面的查询字符串将序列化的对象版本连接起来，或者将所有内容都存储在 ASP.NET 缓存或 <strong>Session</strong> 对象中。这种情况下不能使用 HTTP 上下文，因为该操作涉及多个 HTTP 请求，每个请求都有一个不同的项目集。</p>
<p>请注意，反馈页面的 URL 包含调用的某些细节，并且可能如下所示。</p>
<pre>feedback.aspx?target=work.aspx?param1=123&amp;param2=hello
</pre>
<p>要隐藏这些细节，您可以定义一个自定义 HTTP 处理程序，并将其绑定到您认为更合适的虚拟 URL。该 HTTP 处理程序可以从缓存或会话状态中检索所需的信息（包括反馈页面和工作页面的名称）。<br />
</p>
<h3 id="EGAA">设置焦点控件</h3>
<p>ASP.NET 2.0 提供了一个非常好的新功能，允许您指定首次显示页面时将哪个输入控件设置为焦点。这是一种灵活的功能，可以减少用户通过单击开始操作的负担，例如，在文本框中单击开始输入数据。 </p>
<p>要将 HTML 组件指定为输入焦点，您需要一小段 Javascript 代码。首先声明一点：这不是尖端的火箭科学，您可以轻松地将这段 Javascript 代码作为内嵌代码添加到 &lt;<strong>body</strong>&gt; 标记的 <strong>onload</strong> 属性中。但是，在 Page 类上使用 <strong>SetFocus</strong> 方法确定服务器上的焦点控件的名称确实是前进了一大步。实际上，您可以在 ASP.NET 2.0 中使用以下代码。</p>
<pre>void Page_Load(object sender, System.EventArgs e) {
SetFocus("TheFirstName");
}
</pre>
<p>当显示页面时，名为 <strong>TheFirstName</strong> 的输入控件将成为焦点。此方法便捷有效，但如何在 ASP.NET 1.x 中对其进行编码？ </p>
<p>同样，实现此功能的技巧已为业界人士所熟知，也可以从 Google 中毫不费力地搜索到。但问题是，如何将其集成到基础 <strong>Page</strong> 类中以便重复使用。</p>
<p>让我们使用以下声明来扩展 Msdn.Page 基础类。</p>
<pre>private string m_focusedControl;
public void SetFocus(string ctlId) {
m_focusedControl = ctlId;
}
</pre>
<p><strong>SetFocus</strong> 方法收集控件的 ID 并将其存储在内部成员中。在页面的 <strong>PreRender</strong> 事件中，调用另一个帮助程序函数以构建和插入 Javascript 代码。</p>
<pre>private void AddSetFocusScript()
{
if (m_focusedControl == "")
return;
// 添加脚本以声明函数
StringBuilder sb = new StringBuilder("");
sb.Append("&lt;script language=javascript&gt;");
sb.Append("function ");
sb.Append(SetFocusFunctionName);
sb.Append("(ctl) {");
sb.Append("  if (document.forms[0][ctl] != null)");
sb.Append("  {document.forms[0][ctl].focus();}");
sb.Append("}");
// 添加脚本以调用函数
sb.Append(SetFocusFunctionName);
sb.Append("('");
sb.Append(m_focusedControl);
sb.Append("');&lt;");
sb.Append("/");   // 按照这种方式断开，以避免误解...
sb.Append("script&gt;");
// 注册脚本（名称区分大小写）
if (!IsStartupScriptRegistered(SetFocusScriptName))
RegisterStartupScript(SetFocusScriptName, sb.ToString());
}
</pre>
<p>Javascript 代码可以像动态字符串一样构建，并累积存储在 <strong>StringBuilder</strong> 对象中。下一步是将该字符串添加到页面输出中。在 ASP.NET 中，要在页面中添加一些客户端脚本代码，必须先在特定页面级别的集合中注册该代码。为此，<strong>Page</strong> 类提供了几个 <strong>RegisterXxx</strong> 方法。每个 <strong>RegisterXxx</strong> 方法将 Javascript 代码块添加到不同的集合中，以便插入到最终页面标记中的不同位置。例如，<strong>RegisterStartupScript</strong> 在窗体的关闭标记之前插入代码。而 <strong>RegisterClientScriptBlock</strong> 在窗体的打开标记之后插入脚本代码。重要的是，必须在脚本中包括 &lt;<strong>script</strong>&gt; 元素的两个标记。每个脚本块都由一个关键字标识，这样多个服务器控件可以使用同一个脚本块，而不会将它发送给输出流两次或多次。 </p>
<p>在页面中，以下 Javascript 代码块被插入到窗体的关闭标记之前。这样，它将在初始化后启动时立即开始运行。</p>
<pre>&lt;form&gt;
:
&lt;script language=javascript&gt;
function __setFocus(ctl) {
if (document.forms[0][ctl] != null) {
document.forms[0][ctl].focus();
}
}
__setFocus('TheFirstName');
&lt;/script&gt;
&lt;/form&gt;
</pre>
<p>通过在 Msdn.Page 类上使用 <strong>SetFocus</strong> 公共方法，您可以在页面代码的任何位置决定在浏览器中显示页面时将哪个控件作为输入焦点。更重要的是，您可以根据运行时条件和/或回发事件作出此决定。</p>
<h3 id="EFAA">结论</h3>
<p>在面向对象的技术（例如 ASP.NET）中，主要优点之一是您可以广泛使用继承。通过继承和改进现有控件的公共接口，您可以很轻松地创建新的自定义服务器控件。在衍生类中，您可以替代虚拟方法，从而改变组件的内部行为。将这些面向对象的编程 (OOP) 原则应用于控件似乎非常自然，非常普遍，但对于表示 ASP.NET 页的类，情况则不尽然。</p>
<p>不过，页面继承广泛用于构建所请求的每个 .ASPX 页面的可执行表示。内含代码页面是指从基础 <strong>System.Web.UI.Page</strong> 类继承的页面。为什么不定义一个中间 <strong>Page</strong> 类，为应用程序特定的页面提供功能更丰富的基础呢？</p>
<p>这正是本文所阐述的问题。我在本文中介绍了许多开发人员或多或少都能成功实现的三个常见功能，即检测刷新键、控制冗长操作以及将控件指定为输入焦点，还介绍了如何将这三个功能全部封装到一个无所不包的 <strong>Page</strong> 类的上下文中。</p>
<p>内含代码和内嵌代码应用程序中使用了新的 <strong>Page</strong> 类（Msdn.Page 类）来取代基础 <strong>Page</strong> 类，这个新类以方便且可重复使用的方式为开发人员提供了更多基本功能。功能更丰富的基础 <strong>Page</strong> 类是为 ASP.NET 应用程序构建更可靠平台的一个里程碑。实际应用程序的所有页面都应从自定义类开始构建，以此来验证 <strong>Page</strong> 类的功能。</p>
<p><strong>参考资料</strong> </p>
<ul>
    <li>
    <p><a id="ctl00_rs1_mainContentContainer_ctl03" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl03',this);" href="http://shopping.msn.com/search/detail.aspx?pcId=4650&amp;prodId=1627167&amp;ptnrid=141&amp;ptnrdata=0">Programming Microsoft ASP.NET </a></p>
    <li>
    <p><a id="ctl00_rs1_mainContentContainer_ctl04" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl04',this);" href="http://shopping.msn.com/search/detail.aspx?pcId=12237&amp;prodId=465101&amp;ptnrid=141&amp;ptnrdata=0">Building Web Solutions with ASP.NET and ADO.NET </a></p>
    <li>
    <p><a id="ctl00_rs1_mainContentContainer_ctl05" onclick="javascript:Track('ctl00_rs1_mainContentContainer_ctl00|ctl00_rs1_mainContentContainer_ctl05',this);" href="http://shopping.msn.com/search/detail.aspx?pcId=4650&amp;prodId=2163685&amp;ptnrid=141&amp;ptnrdata=0">Introducing ASP.NET 2.0 </a></p>
    </li>
</ul>
<img src ="http://www.cnblogs.com/Harlan/aggbug/1194829.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41818/" target="_blank">[新闻]Windows Live视频邮件9月9日开始测试</a>]]></description></item><item><title>奥运火炬成功登顶珠峰</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/08/1188197.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Thu, 08 May 2008 03:57:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/08/1188197.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1188197.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/08/1188197.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1188197.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1188197.html</trackback:ping><description><![CDATA[<img height="375" alt="" src="http://www.cnblogs.com/images/cnblogs_com/harlan/20080508093731886691050810.jpg" width="500" border="0" />&nbsp;<br />
5月8日，北京奥运圣火珠峰传递登山队成功登顶珠峰。这是罗布占堆（左）点燃第一棒火炬手吉吉手中的&#8220;祥云&#8221;火炬。...
<img src ="http://www.cnblogs.com/Harlan/aggbug/1188197.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41817/" target="_blank">[新闻]Intel首次公开展示Nehalem架构迅驰3平台</a>]]></description></item><item><title>用反射来解决字段多带来的烦恼（转自论坛）</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/03/1177766.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Sat, 03 May 2008 05:19:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/03/1177766.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1177766.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/03/1177766.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1177766.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1177766.html</trackback:ping><description><![CDATA[做项目开发的时候,大家应该经常都会遇到一个表里面的很多个字段的情况吧.在之前我接触的一个项目,有一个表有20多个字段.要向表中添加记录,和将一条数据绑定到页面上都要写很多代码.如: <br />
<br />
下面是一个用户表的添加 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;user&nbsp;=&nbsp;new&nbsp;User(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.Name&nbsp;=&nbsp;this.txt_Name.Text;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.Remark&nbsp;=&nbsp;this.txt_Remark.Text; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.Age&nbsp;=&nbsp;int.Parse(this.txt_Age.Text); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.Type=this.txt_Type.SelectedValue;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.Time=DateTime.Parse(this.txt_Time.Text); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new&nbsp;Test().SaveOrUpdate(user); <br />
将表里面的数据绑定到控件里面如下 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;user=(User)&nbsp;new&nbsp;test().Get(typeof(User),"1"); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txt_Name.Text=user.Name; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txt_Remark.Text=user.Remark; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txt_Age.Text=user.Age.ToString(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txt_Type.SelectedValue=txt_Type.Items.FindByValue(user.Type); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;txt_Time.Text=User.Time.ToString("yyyy-MM-dd"); <br />
上面的列子,数据类型不对我们得进行转换,下拉列表还要进行绑定.当然字段比较少,还不容易怎么出错,如果字段多了,这样一个一个的写太老火了,而且还容易忘记一些,或者把一些数据绑定错,或者忘了ToString(). <br />
<br />
思路是这样的:&nbsp; <br />
一、对于网页中控件的命名规为&nbsp;"txt_实体类的字段名"; <br />
二、遍历页面中的所有控件，使用反射将控件的值赋给对象。和将对象的属性值绑定到控件上。 <br />
<br />
下面是要用到的一些方法 <br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**////&nbsp; &lt;summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;字符串首字母大写 <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp; &lt;/summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp; &lt;param&nbsp;name="s"&gt; &lt;/param&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp; &lt;returns&gt; &lt;/returns&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;string&nbsp;ToProperCase(string&nbsp;s) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;revised&nbsp;=&nbsp;""; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(s.Length&nbsp;&gt;&nbsp;0) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;revised&nbsp;=&nbsp;s.Trim(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;revised&nbsp;=&nbsp;revised.Substring(0,&nbsp;1).ToUpper()&nbsp;+&nbsp;revised.Substring(1).ToLower(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;revised; <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**////&nbsp; &lt;summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;设置对象属性的值 <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp; &lt;/summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;void&nbsp;SetProperty(object&nbsp;obj,&nbsp;string&nbsp;name,&nbsp;object&nbsp;value) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropertyInfo&nbsp;propertyInfo&nbsp;=&nbsp;obj.GetType().GetProperty(name); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;object&nbsp;objValue&nbsp;=&nbsp;Convert.ChangeType(value,&nbsp;propertyInfo.PropertyType); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;propertyInfo.SetValue(obj,&nbsp;objValue,&nbsp;null); <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;/**////&nbsp; &lt;summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;获取对象属性的值 <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp; &lt;/summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;object&nbsp;GetProperty(object&nbsp;obj,&nbsp;string&nbsp;name) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//bindingFlags <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PropertyInfo&nbsp;propertyInfo&nbsp;=&nbsp;obj.GetType().GetProperty(name); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;propertyInfo.GetValue(obj,&nbsp;null); <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
将控件的值绑定到对象上面。 <br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp; &lt;&nbsp;Page.Controls.Count;&nbsp;i++) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetControlValue(Controls[i],&nbsp;"txt_",ref&nbsp;user);&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;/**////&nbsp; &lt;summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;设置对象的值 <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp; &lt;/summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;void&nbsp;SetObjectValue(Control&nbsp;page,&nbsp;string&nbsp;str,ref&nbsp;object&nbsp;obj) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(Control&nbsp;content&nbsp;in&nbsp;page.Controls) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(content.Controls.Count&nbsp;&gt;&nbsp;0) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetObjectValue(content,&nbsp;str,ref&nbsp;obj); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(content.ID&nbsp;!=&nbsp;null) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;contentID&nbsp;=&nbsp;content.ID.ToLower(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(contentID.Replace(str,&nbsp;"")&nbsp;!=&nbsp;contentID.ToLower()) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetProperty(obj,&nbsp;ToProperCase(contentID.Replace(str,&nbsp;"")), <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetProperty(content,"Text") <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
（上面的Text是TextBox控件的属性，对于下拉列表框也可以使用这个属性获取选定项的值，所以就不用去判断了，最开始我还去判断类型:） <br />
<br />
将对象的值绑定到控件上面 <br />
<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp; &lt;&nbsp;Page.Controls.Count;&nbsp;i++) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetControlValue(Controls[i],&nbsp;"txt_",&nbsp;user); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
<br />
/**////&nbsp; &lt;summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp;设置控件的值 <br />
&nbsp;&nbsp;&nbsp;&nbsp;///&nbsp; &lt;/summary&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;void&nbsp;SetControlValue(Control&nbsp;page,&nbsp;string&nbsp;str,&nbsp;object&nbsp;obj) <br />
&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(Control&nbsp;content&nbsp;in&nbsp;page.Controls) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(content.Controls.Count&nbsp;&gt;&nbsp;0) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetControlValue(content,&nbsp;str,&nbsp;obj); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(content.ID&nbsp;!=&nbsp;null) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;contentID&nbsp;=&nbsp;content.ID.ToLower(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(contentID.Replace(str,&nbsp;"")&nbsp;!=&nbsp;contentID.ToLower()) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(content.GetType()&nbsp;!=&nbsp;typeof(DropDownList)) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetProperty(content,&nbsp;"Text", <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GetProperty(obj,&nbsp;ToProperCase(contentID.Replace(str,&nbsp;""))) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetDropDownListItem((DropDownList)content,&nbsp;(string)ReflectionUtil.GetProperty(obj,&nbsp;ToProperCase(contentID.Replace(str,&nbsp;"")))); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;} <br />
<br />
主要的代码就上面这些，你可以将这些放到公用的类库里，以后遇到字段多的表我们也就不用怕了. <br />
我的博客人气太差了,放在上面都没有什么人看的,个人感觉做项目时这种方法很方便,特别是一个表字段太多的情况.只是要遍历一下页面控件,速度可能会慢一点.你们可以再加一些判断,对像DataGrid里面的就不需要再遍历了().复制过来代码颜色都没有了,给你们个地址:http://www.cnblogs.com/snryang/archive/2008/03/22/1117974.html
 <img src ="http://www.cnblogs.com/Harlan/aggbug/1177766.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41816/" target="_blank">[新闻]Pogo浏览器</a>]]></description></item><item><title>海量存储过程(500w数据,分页只需2秒)</title><link>http://www.cnblogs.com/Harlan/archive/2008/05/03/1177760.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Sat, 03 May 2008 05:14:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/05/03/1177760.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1177760.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/05/03/1177760.html#Feedback</comments><slash:comments>38</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1177760.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1177760.html</trackback:ping><description><![CDATA[摘要: 这个存储过程执行的速度还不错.500W速度分页只要2秒,任何页数 可是有点问题就是,如果排序不是主键,ID,那么分页就会出错,不知道各位有什么好个意见,修改一下 ------------------------------------------------------- SQL codecreate procedure SqlDataPaging@tbName varchar(255), --表&nbsp;&nbsp;<a href='http://www.cnblogs.com/Harlan/archive/2008/05/03/1177760.html'>阅读全文</a><img src ="http://www.cnblogs.com/Harlan/aggbug/1177760.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41816/" target="_blank">[新闻]Pogo浏览器</a>]]></description></item><item><title> 學習利用vsnet快速开发windows服务</title><link>http://www.cnblogs.com/Harlan/archive/2008/04/30/1177661.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Wed, 30 Apr 2008 14:41:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/04/30/1177661.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1177661.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/04/30/1177661.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1177661.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1177661.html</trackback:ping><description><![CDATA[<p>在很多应用中需要做windows服务来操作数据库等操作，比如<br />
（1）一些非常慢的数据库操作，不想一次性去做，想慢慢的通过服务定时去做，比如定时为数据库备份等<br />
（2）在.net Remoting中利用windows服务来做Host</p>
<p>利用vs.net我们可以在几分钟之内建立其windows服务，非常简单</p>
<p>下面说一下步骤<br />
1. 新建一个项目<br />
2. 从一个可用的项目模板列表当中选择Windows服务<br />
3. 设计器会以设计模式打开<br />
4. 从工具箱的组件表当中拖动一个Timer对象到这个设计表面上 (注意: 要确保是从组件列表而不是从Windows窗体列表当中使用Timer) <br />
5. 设置Timer属性，Interval属性200毫秒（1秒进行5次数据库操作）<br />
6. 然后为这个服务填加功能<br />
7.双击这个Timer，然后在里面写一些数据库操作的代码，比如<br />
&nbsp;SqlConnection conn=new SqlConnection("server=127.0.0.1;database=test;uid=sa;pwd=275280");<br />
&nbsp;&nbsp; SqlCommand comm=-new SqlCommand("insert into tb1 ('111',11)",conn);<br />
&nbsp;&nbsp; conn.Open();<br />
&nbsp;&nbsp; comm.ExecuteNonQuery();<br />
&nbsp;&nbsp; conn.Close();<br />
8. 将这个服务程序切换到设计视图<br />
9. 右击设计视图选择&#8220;添加安装程序&#8221;<br />
10. 切换到刚被添加的ProjectInstaller的设计视图<br />
11. 设置serviceInstaller1组件的属性： <br />
&nbsp;&nbsp;&nbsp; 1) ServiceName = My Sample Service<br />
&nbsp;&nbsp;&nbsp; 2) StartType = Automatic (开机自动运行)<br />
12. 设置serviceProcessInstaller1组件的属性&nbsp; Account = LocalSystem<br />
13. 改变路径到你项目所在的bin\Debug文件夹位置(如果你以Release模式编译则在bin\Release文件夹)<br />
14. 执行命令&#8220;InstallUtil.exe MyWindowsService.exe&#8221;注册这个服务，使它建立一个合适的注册项。(InstallUtil这个程序在WINDOWS文件夹\Microsoft.NET\Framework\v1.1.4322下面)<br />
15. 右击桌面上&#8220;我的电脑&#8221;，选择&#8220;管理&#8221;就可以打计算机管理控制台<br />
16. 在&#8220;服务和应用程序&#8221;里面的&#8220;服务&#8221;部分里，你可以发现你的Windows服务已经包含在服务列表当中了<br />
17. 右击你的服务选择启动就可以启动你的服务了<br />
看看数据库是不是一秒多了5个记录啊</p>
<p>需要注意的是:<br />
如果你修改了这个服务，路径没有变化的话是不需要重新注册服务的，如果路径发生了变化，需要先卸载这个服务InstallUtil.exe /u参数，然后再重新安装这个服务，不能直接安装。还有就是windows服务是没有界面的，不要企图用控制的输出方式来输出一些信息，你只能添加一个EventLog，通过WriteEntry()来写日志。</p>
<p>关于怎么用windows服务来做一个远程服务可以看一下<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT15.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT15.asp</a><br />
<br />
來自：<font face="Verdana">http://blog.csdn.net/mych/archive/2008/04/29/2341663.aspx</font></p>
 <img src ="http://www.cnblogs.com/Harlan/aggbug/1177661.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41807/" target="_blank">[新闻]洪磊口述:番茄花园如何捆绑流氓软件月入十万</a>]]></description></item><item><title>博客营销的七个秘诀</title><link>http://www.cnblogs.com/Harlan/archive/2008/04/30/1177675.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Wed, 30 Apr 2008 06:12:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/04/30/1177675.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1177675.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/04/30/1177675.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1177675.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1177675.html</trackback:ping><description><![CDATA[這是來自CSDN博客中的一篇文章。<br />
來自：<font face="Verdana">http://blog.csdn.net/sejie/archive/2008/04/30/2347334.aspx</font><br />
<br />
秘诀一：博客上线前的准备<br />
<br />
在博客上线之前，你应该准备好一些能够吸引人的资源，比如有用的工具，精彩的文章等。在Blogstorm正式上线之前，我准备了一个链接跟踪工具，这个工具可以让站长查找链接到网站的反向链接。因为这个工具，我的博客从众同相同类型的博客中脱颖而出，吸引了大量的访问者。<br />
<br />
当然，我还有其他一些有用的工具正在测试中，在以后的几个月中，我会陆续推出。前面提到的链接跟踪工具是我专门设计的，其目的吸引大家对Blogstorm的注意，希望Blogstorm成为大家了解链接诱饵以及社会化媒体营销的地方。<br />
<br />
另外，我精心地设计了网站的外观，尽量减少广告的数量，让浏览者获得最佳的体验。对网站的模板，我针对性地做了SEO工作，保持Title、Tag的唯一性，并认真检查自己的每一篇文章，确认没有重复的内容或低价值的页面。<br />
<br />
我还仔细的检查了网页的源代码，让源代码尽量精简。这一点十分重要，你必须保证你的网站上每一个功能都工作正常，比如能够能够正常地出现在Digg的首页，能够正常订阅RSS等。<br />
<br />
秘诀二：内容<br />
<br />
我的Blogstorm博客的前四篇文章分别是：<br />
<br />
欢迎来到Blogstorm<br />
我们怎样提高服务水平？<br />
如何使用hotlinkers和Google图片建立网站的自然链接<br />
Google Analytics（分析）和Google新界面的高级使用技巧<br />
<br />
对于一个新开的博客，开始的几篇博文将决定这个博客的未来。如果浏览者来到你的博客，读到的都是一些毫无实际意义的文章，他再也不会来第二次。我本人也是经常这样想的，如果一个博客站长经常写的都是一些意义不大的文章，那么也不要期望哪天奇迹出现，他会突然写出一篇高质量的文章。<br />
<br />
《Google Analytics（分析）使用指南》是一篇有深度的文章，对大多数站长都十分有用。这篇文章是我很久以前写的，这一次Google启用新的使用界面之后，我对这篇文章进行了修改并重新发表。令我感到欣慰的是，由于这是Google启用新的使用界面之后，出现得最早的一篇全面介绍Google新界面的实用性文章，在社会化媒体网站上获得了许多网友的推荐。<br />
<br />
秘诀三：网站上线<br />
<br />
网站上线第一件事就是发邮件给你的朋友，让他们在各自的博客上评论你的网站。首先从你认为会帮助你的人开始，列一个清单，发邮件给他们，让他们评论你的博客。我的Blogstorm上线时，我还给网络上一些知名的博客发了邮件，结果是有几个比较知名的博客上出现了对我的博客评价的文章，利用这种方法，我在第一个星期就轻松获得了30000个浏览者。<br />
<br />
实际上一个新的网站上线是没有任何秘密，你需要的只是市场的时机，一个好产品和辛勤工作。<br />
<br />
主要的步骤是：<br />
<br />
发邮件给你的朋友。<br />
发邮件给那些可能对你的博客有兴趣的人<br />
使用社会化媒体<br />
积累你的个人声誉<br />
<br />
秘诀四：取悦你的访客<br />
<br />
新站上线之后，许多人急着制造链接诱饵以吸引更多的访客，但大部分访客并不喜欢包含大量链接及广告的文章。我通常的做法是，将含有链接诱饵的文章数量限制在每周一篇，保证其他文章都是对浏览者有用的。当然，有时候高质量的文章本身就是一个非常好的链接诱饵，这样对站长及访客来说，是一个双赢的局面。<br />
<br />
秘诀五：链接诱饵<br />
<br />
如果你能够花心思每个星期创造一个真正吸引人的链接诱饵，久而久之，你的访客将开始期待它，有些访客还会自发在其他社会化媒体网站上宣传你的链接诱饵。<br />
<br />
我在推广Blogstorm博客上的链接诱饵时，用得最多的是社会化媒体网站，如stumbleupon ， reddit ， digg等。<br />
<br />
除此之外，我还用其他的一些链接诱饵来增加网站流量以及外部链接，John Chow的博客能够获得大量的流量，因为他利用博客赚了很多钱，Blogstorm博客能够获得流量，因为我告诉人们通过链接诱饵我获得了多少流量，以及每个链接诱饵为我带来了多少流量。<br />
<br />
秘诀六：声誉建设<br />
<br />
对每一个写博客的人来说，时刻关注别人对你的评价是十分重要的，这一点对一个新上线的博客尤其重要。当发现一些批评性的建议或负面信息时，要迅速回复，并采取相应的行动。<br />
<br />
秘诀七：高质量的内容<br />
<br />
人们常说，内容为王。要想在网络上建立一个成功的博客，高质量、不断更新的内容是必不可少的。我希望任何来blogstorm的人，都有机会学到一些新的网络营销技巧，这将有助于他们推广他们的博客。<br />
<br />
没有良好的营销，没有人发现你的博客。没有良好的内容，没有人会坚持阅读你的博客。<br />
<img src ="http://www.cnblogs.com/Harlan/aggbug/1177675.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41807/" target="_blank">[新闻]洪磊口述:番茄花园如何捆绑流氓软件月入十万</a>]]></description></item><item><title>MaxMind中的數據文件地址</title><link>http://www.cnblogs.com/Harlan/archive/2008/04/30/1176299.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Wed, 30 Apr 2008 02:46:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/04/30/1176299.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1176299.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/04/30/1176299.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1176299.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1176299.html</trackback:ping><description><![CDATA[MaxMind中的GeoIP數據文件請到下面網站下載安裝，<br />
<br />
http://www.maxmind.com/app/geoip_country <br />
<br />
安裝方法就不在這里詳說了，請大家自己？？？？？？？
 <img src ="http://www.cnblogs.com/Harlan/aggbug/1176299.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41807/" target="_blank">[新闻]洪磊口述:番茄花园如何捆绑流氓软件月入十万</a>]]></description></item><item><title>MaxMind的GeoIP應用</title><link>http://www.cnblogs.com/Harlan/archive/2008/04/30/1176271.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Wed, 30 Apr 2008 02:45:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/04/30/1176271.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1176271.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/04/30/1176271.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1176271.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1176271.html</trackback:ping><description><![CDATA[摘要: 在 學習能定位访客位置的地图 (一) 一文中，有人問MaxMind中的GeoIP怎么用，現在做個樣例出來，以方便大家學習：一：先來設計一個DataBaseInfo類來，using System;using System.IO;public class DatabaseInfo { public static int COUNTRY_EDITION = 1; public static int RE&nbsp;&nbsp;<a href='http://www.cnblogs.com/Harlan/archive/2008/04/30/1176271.html'>阅读全文</a><img src ="http://www.cnblogs.com/Harlan/aggbug/1176271.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41807/" target="_blank">[新闻]洪磊口述:番茄花园如何捆绑流氓软件月入十万</a>]]></description></item><item><title>學習能定位访客位置的地图 (三)</title><link>http://www.cnblogs.com/Harlan/archive/2008/04/29/1174647.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Tue, 29 Apr 2008 06:28:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/04/29/1174647.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1174647.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/04/29/1174647.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1174647.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1174647.html</trackback:ping><description><![CDATA[三&nbsp;&nbsp;&nbsp; 嵌入地图到常见的BLOG
<p style="text-indent: 20.6pt">上面已经成功创建了具备定位访客功能的Google地图，下面将简单介绍如何将该地图嵌入到常见的BLOG中。</p>
<p style="text-indent: 21pt">目前，为了满足博客用户体现自己个性的需求，博客提供商（BSP）提供的BLOG服务通常都具有模板编辑功能。区别只是有些BSP对模板限制更多一些，而另一些则让用户具有更多的自定义功能。</p>
<p style="text-indent: 21pt">常见的BLOG中，自定义程度最高的应该是Google的Blogger.com和博客中国Blogcn.com。这两个BLOG允许完全的自定义，支持用户自行编写HTML，甚至支持直接往BLOG里加入JavaScript代码。因此使用这类BLOG的读者可以完全自己整理模板，把上述地图嵌入进去（当然如果觉得麻烦，也可以参照下面介绍的方法）。</p>
<p style="text-indent: 21pt">除了上述自定义程度很高的BLOG外，还有些BLOG不允许在模板中使用JavaScript，比如新浪等门户网站提供的BLOG。对于这类有很好的模板编辑器，支持编辑HTML的BSP来说，最好的办法就是以IFrame的方式嵌入网页了。</p>
<p style="text-indent: 21pt">首先必须找一个免费的无广告网页空间上传。这里推荐Google提供的Page Creator，可去http://pages.google.com申请开通服务（需要Google账号，没有的可在http://mail.google.com申请注册，具体过程在此省略，注册时有详细说明）。注册后无须创建任何主页，直接在图4.2所示界面右侧的&#8220;Upload Stuff&#8221;区域上传Blog地图文件&#8220;blogmap.html&#8221;即可。该文件的地址应为http://your-site-name.googlepages.com/blogmap.html，可用于网页引用（your-site- name是Page Creator中创建的站点名称）。</p>
<p style="margin: 9.35pt 0cm 4.65pt"><img height="220" alt="" src="http://book.csdn.net/BookFiles/685/img/image029.jpg" width="386" /></p>
<p style="margin-bottom: 7.8pt">图4.2&nbsp; 右侧&#8220;Upload Stuff&#8221;区域可以用于上传文件</p>
<p style="text-indent: 20.6pt">然后就需要把该网页嵌入相应的BLOG模板网站中，下面以新浪的BLOG为例给出相应的嵌入方法。</p>
<p style="margin-bottom: 7.8pt; text-indent: 21pt">登录新浪BLOG，进入管理界面，依次打开&#8220;自定义设置&#8221;|&#8220;首页内容维护&#8221;|&#8220;自定义空白面板&#8221;|&#8220;进入编辑&#8221;。进入&#8220;自定义空白面板&#8221;管理界面后，单击&#8220;新增&#8221;按钮，进入&#8220;自定义空白面板&#8221;编辑界面。在&#8220;面板标题&#8221;输入框填写适当的标题，例如&#8220;访客位置&#8221;等。在&#8220;面板简介&#8221;文本域里选定&#8220;显示源代码&#8221;，并将以下代码复制到该文本域，并单击&#8220;保存&#8221;按钮，保存当前设置。</p>
<p>&lt;div style="text-align:center"&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;iframe marginWidth="0" marginHeight="0" frameBorder="0" scrolling="no" border="0" style="overflow:hidden; width:200px; height:150px" src="http://your-site-name.googlepages.com/blogmap.html"&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;/iframe&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;noframes&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 本页面用于显示访客位置，若你看到此文本，说明你的浏览器不支持Frames</p>
<p>&nbsp;&nbsp;&nbsp; &lt;/noframes&gt;</p>
<p>&lt;/div&gt;</p>
<p style="margin: 7.8pt 0cm 12.45pt 21pt">★ 注意 ★</p>
<p>当嵌入IFrame页面时，需要把&#8220;http://your-site-name.googlepages.com/blogmap.html&#8221;更换成真实的网页。另外，该地图的大小可在&#8220;style="overflow:hidden; width:200px; height: 150px"&#8221;中设定合适的&#8220;width&#8221;和&#8220;height&#8221;值解决（可能需要多次尝试才能找到适合当前模板的尺寸）。取消选定&#8220;显示源代码&#8221;可进行预览，但编辑的时候一定要处于直接编辑HTML代码的模式）。</p>
<p style="margin-top: 7.8pt; text-indent: 20pt">成功添加地图后的BLOG如图4.3所示。</p>
<p style="margin: 9.35pt 0cm 4.65pt"><img height="209" alt="" src="http://book.csdn.net/BookFiles/685/img/image032.jpg" width="233" /></p>
<p style="margin-bottom: 7.8pt">图4.3&nbsp; 左侧为可定位访客位置的小地图</p>
<p style="text-indent: 21pt">这样，一个简单的、可以定位访客位置的Google地图就完成了。<img alt="" src="http://www.cnblogs.com/Emoticons/msn/regular_smile.gif" /></p>
 <img src ="http://www.cnblogs.com/Harlan/aggbug/1174647.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41813/" target="_blank">[新闻]2008年8月21日IT博客精选：盖茨复出？</a>]]></description></item><item><title>學習能定位访客位置的地图 (二)</title><link>http://www.cnblogs.com/Harlan/archive/2008/04/28/1174646.html</link><dc:creator>Harlan---</dc:creator><author>Harlan---</author><pubDate>Mon, 28 Apr 2008 09:19:00 GMT</pubDate><guid>http://www.cnblogs.com/Harlan/archive/2008/04/28/1174646.html</guid><wfw:comment>http://www.cnblogs.com/Harlan/comments/1174646.html</wfw:comment><comments>http://www.cnblogs.com/Harlan/archive/2008/04/28/1174646.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnblogs.com/Harlan/comments/commentRss/1174646.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/Harlan/services/trackbacks/1174646.html</trackback:ping><description><![CDATA[<div style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; margin-left: 21pt; border-top-style: none; margin-right: 210pt; padding-top: 0cm; border-bottom: silver 1.5pt solid; border-right-style: none; border-left-style: none">
<h4 style="margin: 12.45pt 0cm 4.65pt">3．调用微软的IP定位接口</h4>
</div>
<p style="margin-bottom: 7.8pt; text-indent: 21pt">调用該接口的办法和调用自定义接口的方法不同。原因是出于浏览器安全性考虑，一般禁止了跨域的Ajax调用，因此GDownloadUrl()无法取得<a href="http://maps.live.com">http://maps.live.com</a>上的数据。解决这个问题的办法是动态地在网页的DOM里添加Script脚本。具体做法是在网页加载的onload事件函数里添加如下代码。</p>
<p>//动态创建DOM节点</p>
<p>var ss = document.createElement("script");</p>
<p>//设定脚本的src</p>
<p>ss.src = "http://maps.live.com/WiFiIPService/locate.ashx";</p>
<p>//设定脚本的type</p>
<p>ss.type="text/javascript";</p>
<p>//附加脚本到网页的DOM</p>
<p>//除了往下面document.documentElement元素appendChild外</p>
<p>//也可以在document.body或其他DOM元素中添加新的节点</p>
<p>document.documentElement.appendChild(ss);</p>
<p style="margin: 7.8pt 0cm; text-indent: 21pt">此例完整代码如下（blogmap.html）：</p>
<p>&lt;!--此为完整的blogmap.html代码--&gt;</p>
<p>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"&nbsp;&nbsp; "http://www.w3.org/TR/ xhtml1/DTD/xhtml1-strict.dtd"&gt;</p>
<p>&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;</p>
<p>&nbsp; &lt;head&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;meta http-equiv="content-type" content="text/html; charset=utf-8"/&gt;</p>
<p>&lt;title&gt;Google Maps JavaScript API Example&lt;/title&gt;</p>
<p>&lt;style type="text/css"&gt;</p>
<p>body, html, #map{</p>
<p>&nbsp;&nbsp;&nbsp; margin:0px;</p>
<p>&nbsp;&nbsp;&nbsp; width: 100%;</p>
<p>&nbsp;&nbsp;&nbsp; height: 100%;</p>
<p>}</p>
<p>&lt;/style&gt;</p>
<p>&lt;!--导入Google Maps API库文件。注意将本代码中的API Key替换为前文申请到的API Key--&gt;</p>
<p>&lt;script src="http://maps.google.com/maps?file=api&amp;amp;v=2&amp;amp;key=ABQIAAAA1j 86tnUDFv8OAtC8dZVtKRT2yXp_ZAY8_ufjIAnGkUAnvwkxSzmwrQ90SNUILzGRpsBiaa860gfQ" type="text/javascript"&gt;&lt;/script&gt;</p>
<p>&lt;script type="text/javascript"&gt;</p>
<p>//&lt;![CDATA[</p>
<p>&nbsp;&nbsp;&nbsp; var map;&nbsp; //全局GMap</p>
<p>&nbsp;&nbsp;&nbsp; //网页加载时用于初始化Google地图</p>
<p>&nbsp;&nbsp;&nbsp; function load()</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (GBrowserIsCompatible())</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //创建GMap2对象</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map = new GMap2(document.getElementById("map"));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //缩放级别设得比较小，如不合适可自行设定合适的级别</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; map.setCenter(new GLatLng(37.4419, -122.1419), 1);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //动态创建DOM节点</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var ss = document.createElement("script");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设定脚本的src</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ss.src = "http://maps.live.com/WiFiIPService/locate.ashx";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设定脚本的type</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ss.type="text/javascript";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //附加脚本到网页的DOM</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //除了往下面document.documentElement元素appendChild外</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //也可以在document.body或其他DOM元素中添加新的节点</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.documentElement.appendChild(ss);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; //SetAutoLocateViewport()接口，移动到当前访客的位置</p>
<p>&nbsp;&nbsp;&nbsp; //第一个参数latitude——当前IP所在的纬度</p>
<p>&nbsp;&nbsp;&nbsp; //第二个参数longitude——当前IP所在的经度</p>
<p>&nbsp;&nbsp;&nbsp; //第三个参数zoomlevel——当前适合于微软Virtual Earth显示的缩放级别（对Google Maps API&nbsp;&nbsp; //程序基本无用）</p>
<p>&nbsp;&nbsp;&nbsp; //第4个参数unknown——该接口无相应信息，可能为是否开启Virtual Earth地图的Virtual 3D功//能（对Google Maps API程序无用）</p>
<p>&nbsp;&nbsp;&nbsp; //第5个参数message——应该显示消息（对Google Maps API程序无用）</p>
<p>&nbsp;&nbsp;&nbsp; function SetAutoLocateViewport(latitude, longitude, zoomlevel, unknown, message)</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //访客所处位置</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var point = new GLatLng(latitude, longitude);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //创建一个自定义的GIcon</p>
<p>&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;var myIcon= new GIcon();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myIcon.image = "http://labs.google.com/ridefinder/images/mm_20_green.png";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myIcon.shadow = "http://labs.google.com/ridefinder/images/mm_20_shadow.png";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myIcon.iconSize = new GSize(12, 20);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myIcon.shadowSize = new GSize(22, 20);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myIcon.iconAnchor = new GPoint(6, 20);</p>
<p>&nb