﻿<?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>BlogJava-★Daniel's Blog★-文章分类-ASP,ASP.NET </title><link>http://www.blogjava.net/Daniel2005/category/4908.html</link><description>URL:http://www.blogjava.net/Daniel2005</description><language>zh-cn</language><lastBuildDate>Thu, 16 Aug 2007 07:51:24 GMT</lastBuildDate><pubDate>Thu, 16 Aug 2007 07:51:24 GMT</pubDate><ttl>60</ttl><item><title>WEB打印方式!</title><link>http://www.blogjava.net/Daniel2005/articles/125849.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Fri, 22 Jun 2007 07:21:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/125849.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/125849.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/125849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/125849.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/125849.html</trackback:ping><description><![CDATA[<p><span style="COLOR: red">1).NET &nbsp; Framework &nbsp; 类库</span> &nbsp; &nbsp; &nbsp; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; PrinterSettings &nbsp; 成员请参见 &nbsp; <br>&nbsp; PrinterSettings &nbsp; 类 &nbsp; | &nbsp; System.Drawing.Printing &nbsp; 命名空间 &nbsp; | &nbsp; C++ &nbsp; 托管扩展编程 &nbsp; &nbsp; <br>&nbsp; PrinterSettings &nbsp; 概述 &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 公共构造函数 &nbsp; <br>&nbsp; PrinterSettings &nbsp; 构造函数 &nbsp; 初始化 &nbsp; PrinterSettings &nbsp; 类的新实例。 &nbsp; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 公共属性 &nbsp; <br>&nbsp; CanDuplex &nbsp; 获取指示打印机是否支持双面打印的值。 &nbsp; &nbsp; <br>&nbsp; Collate &nbsp; 获取或设置一个值，该值指示打印文档是否逐份打印。 &nbsp; &nbsp; <br>&nbsp; Copies &nbsp; 获取或设置要打印的文档份数。 &nbsp; &nbsp; <br>&nbsp; DefaultPageSettings &nbsp; 获取此打印机的默认页设置。 &nbsp; &nbsp; <br>&nbsp; Duplex &nbsp; 获取或设置双面打印的打印机设置。 &nbsp; &nbsp; <br>&nbsp; FromPage &nbsp; 获取或设置要打印的第一页的页码。 &nbsp; &nbsp; <br>&nbsp; InstalledPrinters &nbsp; 获取安装在计算机上所有打印机的名称。 &nbsp; &nbsp; <br>&nbsp; IsDefaultPrinter &nbsp; 获取一个值，该值指示 &nbsp; PrinterName &nbsp; 属性是否指定默认打印机（用户显式设置 &nbsp; PrinterName &nbsp; 的情况除外）。 &nbsp; &nbsp; <br>&nbsp; IsPlotter &nbsp; 获取指示该打印机是否是绘图仪的值。 &nbsp; &nbsp; <br>&nbsp; IsValid &nbsp; 获取一个值，该值指示 &nbsp; PrinterName &nbsp; 属性是否指定了有效的打印机。 &nbsp; &nbsp; <br>&nbsp; LandscapeAngle &nbsp; 获取旋转纵向方向以生成横向方向的角度，以度为单位。 &nbsp; &nbsp; <br>&nbsp; MaximumCopies &nbsp; 获取打印机允许一次打印的最多份数。 &nbsp; &nbsp; <br>&nbsp; MaximumPage &nbsp; 获取或设置可以在 &nbsp; PrintDialog &nbsp; 中选定的最大的 &nbsp; FromPage &nbsp; 或 &nbsp; ToPage。 &nbsp; &nbsp; <br>&nbsp; MinimumPage &nbsp; 获取或设置可以在 &nbsp; PrintDialog &nbsp; 中选定的最小的 &nbsp; FromPage &nbsp; 或 &nbsp; ToPage。 &nbsp; &nbsp; <br>&nbsp; PaperSizes &nbsp; 获取该打印机支持的纸张大小。 &nbsp; &nbsp; <br>&nbsp; PaperSources &nbsp; 获取打印机上可用的纸张来源纸盒。 &nbsp; &nbsp; <br>&nbsp; PrinterName &nbsp; 获取或设置要使用的打印机的名称。 &nbsp; &nbsp; <br>&nbsp; PrinterResolutions &nbsp; 获取该打印机支持的所有分辨率。 &nbsp; &nbsp; <br>&nbsp; PrintRange &nbsp; 获取或设置用户已指定要打印的页码。 &nbsp; &nbsp; <br>&nbsp; PrintToFile &nbsp; 获取或设置一个值，该值指示打印输出是否发送到文件，而不发送到端口。 &nbsp; &nbsp; <br>&nbsp; SupportsColor &nbsp; 获取指示该打印机是否支持彩色打印的值。 &nbsp; &nbsp; <br>&nbsp; ToPage &nbsp; 获取或设置要打印的最后一页的页码。 &nbsp; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 公共方法 &nbsp; <br>&nbsp; Clone &nbsp; 创建此 &nbsp; PrinterSettings &nbsp; 对象的一个副本。 &nbsp; &nbsp; <br>&nbsp; CreateMeasurementGraphics &nbsp; 返回 &nbsp; Graphics &nbsp; 对象，该对象包含创建 &nbsp; PrintDocument &nbsp; 时有用的打印机信息，例如，打印机的 &nbsp; TextMetric &nbsp; 对象。 &nbsp; &nbsp; <br>&nbsp; Equals（从 &nbsp; Object &nbsp; 继承） &nbsp; 已重载。确定两个 &nbsp; Object &nbsp; 实例是否相等。 &nbsp; &nbsp; <br>&nbsp; GetHashCode（从 &nbsp; Object &nbsp; 继承） &nbsp; 用作特定类型的哈希函数，适合在哈希算法和数据结构（如哈希表）中使用。 &nbsp; &nbsp; <br>&nbsp; GetHdevmode &nbsp; 已重载。创建与打印机设置相对应的 &nbsp; DEVMODE &nbsp; 结构的句柄。 &nbsp; &nbsp; <br>&nbsp; GetHdevnames &nbsp; 创建与打印机设置相对应的 &nbsp; DEVNAMES &nbsp; 结构的句柄。 &nbsp; &nbsp; <br>&nbsp; GetType（从 &nbsp; Object &nbsp; 继承） &nbsp; 获取当前实例的 &nbsp; Type。 &nbsp; &nbsp; <br>&nbsp; SetHdevmode &nbsp; 将相关信息从给定句柄复制到 &nbsp; PrinterSettings &nbsp; 中。 &nbsp; &nbsp; <br>&nbsp; SetHdevnames &nbsp; 将相关信息从给定句柄复制到 &nbsp; PrinterSettings &nbsp; 中。 &nbsp; &nbsp; <br>&nbsp; ToString &nbsp; 已重写。参见 &nbsp; Object.ToString。 &nbsp; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 受保护的方法 &nbsp; <br>&nbsp; Finalize（从 &nbsp; Object &nbsp; 继承） &nbsp; 已重写。允许 &nbsp; Object &nbsp; 在&#8220;垃圾回收&#8221;回收 &nbsp; Object &nbsp; 之前尝试释放资源并执行其他清理操作。 &nbsp; &nbsp; <br>&nbsp; 在 &nbsp; C# &nbsp; 和 &nbsp; C++ &nbsp; 中，使用析构函数语法来表示终结程序。 &nbsp; <br>&nbsp; &nbsp; &nbsp; <br>&nbsp; MemberwiseClone（从 &nbsp; Object &nbsp; 继承） &nbsp; 创建当前 &nbsp; Object &nbsp; 的浅表副本。 &nbsp; &nbsp; <br>&nbsp; &nbsp; <br>&nbsp; 请参见 &nbsp; <br>&nbsp; PrinterSettings &nbsp; 类 &nbsp; | &nbsp; System.Drawing.Printing &nbsp; 命名空间 &nbsp; | &nbsp; C++ &nbsp; 托管扩展编程</p>
<span style="COLOR: red">2)1、控制"纵打"、 横打&#8221;和&#8220;页面的边距。 <br>（1）<font color=#000000>&lt;OBJECT id="factory" codeBase="smsx.cab" classid="clsid:1663ed61-23eb-11d2-b92f-008048fdd814" viewastext&gt;&lt;/OBJECT&gt; </font><br><span style="COLOR: #000000">&lt;</span></span>script defer&gt; <br>function SetPrintSettings() { <br>　// -- advanced features <br>　factory.printing.SetMarginMeasure(2) // measure margins in inches <br>　factory.SetPageRange(false, 1, 3) // need pages from 1 to 3 <br>　factory.printing.printer = "HP DeskJet 870C" <br>　factory.printing.copies = 2 <br>　factory.printing.collate = true <br>　factory.printing.paperSize = "A4" <br>　factory.printing.paperSource = "Manual feed" <br><br>　// -- basic features <br>　factory.printing.header = "This is MeadCo" <br>　factory.printing.footer = "Advanced Printing by ScriptX" <br>　factory.printing.portrait = false <br>　factory.printing.leftMargin = 1.0 <br>　factory.printing.topMargin = 1.0 <br>　factory.printing.rightMargin = 1.0 <br>　factory.printing.bottomMargin = 1.0 <br>} <br>&lt;/script&gt; <br><br><span style="COLOR: red">（3）</span> <br>&lt;script language="javascript"&gt; <br>　　function printsetup(){ <br>　　// 打印页面设置 <br>　　wb.execwb(8,1); <br>　　} <br>　　function printpreview(){ <br>　　// 打印页面预览 <br>　　　　 <br>　　wb.execwb(7,1); <br>　　　　　 <br>　　　　 <br>　　} <br><br>　　function printit() <br>　　{ <br>　　if (confirm('确定打印吗？')) { <br>　　wb.execwb(6,6) <br>　　} <br>　　} <br>　　&lt;/script&gt; <br>&lt;/head&gt; <br>&lt;body&gt; <br>&lt;OBJECT classid="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2" height=0 id=wb name=wb width=0&gt;&lt;/OBJECT&gt; <br>&lt;input type=button name=button_print value="打印" onclick="javascript:printit()"&gt; <br>&lt;input type=button　name=button_setup value="打印页面设置" onclick="javascript:printsetup();"&gt; <br>&lt;input type=button　name=button_show value="打印预览" onclick="javascript:printpreview();"&gt; <br>&lt;input type=button name=button_fh value="关闭" onclick="javascript:window.close();"&gt; <br><br>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/125849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2007-06-22 15:21 <a href="http://www.blogjava.net/Daniel2005/articles/125849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Error while trying to run project: Unable to start debugging on the web server. You do not have permission to debug the application. The URL for this project is in the Internet zone. Click Help for more information.</title><link>http://www.blogjava.net/Daniel2005/articles/125539.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Thu, 21 Jun 2007 05:35:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/125539.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/125539.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/125539.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/125539.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/125539.html</trackback:ping><description><![CDATA[<h2><a id=viewpost_ascx_TitleUrl title="Title of this entry." href="http://geekswithblogs.net/ranganh/archive/2005/12/30/64446.aspx"><u><font color=#810081>"Unable to start debugging on the web server. You do not have permission to debug the application. The URL for this project is in the Internet zone." </font></u></a></h2>
<font face=Tahoma><font size=2><font color=#000080><span style="FONT-FAMILY: trebuchet ms">You may receive the error "Error while trying to run project: Unable to start debugging on the web server. You do not have permission to debug the application. The URL for this project is in the Internet zone. Click Help for more information."</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br><span style="FONT-FAMILY: trebuchet ms">This is one of the various errors that appear when you are debugging and may haunt you until you do the following fix:-</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br></font></font></font><font face=Tahoma><font size=2><font color=#000080><strong><span style="FONT-FAMILY: trebuchet ms">1. In the Internet Explorer, "Tools" Menu, select "Internet Options".</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br><span style="FONT-FAMILY: trebuchet ms">2. Switch to "Security" Tab.</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br><span style="FONT-FAMILY: trebuchet ms">3. Click on "Internet" (The Globe Icon. Its actually the default selected).</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br><span style="FONT-FAMILY: trebuchet ms">4. Click on "Custom Level" in the bottom.</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br><span style="FONT-FAMILY: trebuchet ms">5. Scroll down to find the "User Authentication" section.</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br><span style="FONT-FAMILY: trebuchet ms">6. Select "Automatic logon with current username and password".</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br><span style="FONT-FAMILY: trebuchet ms">7. Click "Ok" twice to exit.</span><br><span style="FONT-FAMILY: trebuchet ms"></span><br></strong><span style="FONT-FAMILY: trebuchet ms">This should solve the issue.</span><br><span style="FONT-FAMILY: Trebuchet MS"></span><br><span style="FONT-FAMILY: Trebuchet MS">Please note that this resolution is specific only if you get the exact error message as mentioned in the beginning of this article. </span><span style="FONT-FAMILY: Trebuchet MS">There are various reasons you get the "Unable to start debugging on the webserver". For a complete list of solutions, please check <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vsdebug.asp"><u><font color=#0000ff>http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dv_vstechart/html/vsdebug.asp</font></u></a></span></font></font></font>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/125539.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2007-06-21 13:35 <a href="http://www.blogjava.net/Daniel2005/articles/125539.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MSSQLServer查询分页 </title><link>http://www.blogjava.net/Daniel2005/articles/120798.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Wed, 30 May 2007 01:19:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/120798.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/120798.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/120798.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/120798.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/120798.html</trackback:ping><description><![CDATA[<p>select top 10 * from yc_module where (block_id not in (select top 0 block_id from yc_module order by block_id)) order by block_id;<br></p>
<p>&nbsp;</p>
<p>分页方案一：(利用Not In和SELECT TOP分页)<br>语句形式：<br>SELECT TOP 10 *<br>FROM TestTable<br>WHERE (ID NOT IN<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (SELECT TOP 20 id<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM TestTable<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ORDER BY id))<br>ORDER BY ID</p>
<p><br>SELECT TOP 页大小 *<br>FROM TestTable<br>WHERE (ID NOT IN<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (SELECT TOP 页大小*页数 id<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM 表<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ORDER BY id))<br>ORDER BY ID</p>
<p>-------------------------------------</p>
<p>分页方案二：(利用ID大于多少和SELECT TOP分页）<br>语句形式：<br>SELECT TOP 10 *<br>FROM TestTable<br>WHERE (ID &gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (SELECT MAX(id)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM (SELECT TOP 20 id<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM TestTable<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ORDER BY id) AS T))<br>ORDER BY ID</p>
<p><br>SELECT TOP 页大小 *<br>FROM TestTable<br>WHERE (ID &gt;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (SELECT MAX(id)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM (SELECT TOP 页大小*页数 id<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FROM 表<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ORDER BY id) AS T))<br>ORDER BY ID</p>
<p><br>-------------------------------------</p>
<p>分页方案三：(利用SQL的游标存储过程分页)<br>create&nbsp; procedure XiaoZhengGe<br>@sqlstr nvarchar(4000), --查询字符串<br>@currentpage int,&nbsp;--第N页<br>@pagesize int&nbsp;--每页行数<br>as<br>set nocount on<br>declare @P1 int,&nbsp;--P1是游标的id<br>&nbsp;@rowcount int<br>exec sp_cursoropen @P1 output,@sqlstr,@scrollopt=1,@ccopt=1,@rowcount=@rowcount output<br>select ceiling(<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#49;&#46;&#48;&#42;&#64;&#114;&#111;&#119;&#99;&#111;&#117;&#110;&#116;&#47;&#64;&#112;&#97;&#103;&#101;&#115;&#105;&#122;&#101;"><u><font color=#0000ff>1.0*@rowcount/@pagesize</font></u></a>) as 总页数--,@rowcount as 总行数,@currentpage as 当前页&nbsp;<br>set @currentpage=(@currentpage-1)*@pagesize+1<br>exec sp_cursorfetch @P1,16,@currentpage,@pagesize <br>exec sp_cursorclose @P1<br>set nocount off</p>
<p>其它的方案：如果没有主键，可以用临时表，也可以用方案三做，但是效率会低。<br>建议优化的时候，加上主键和索引，查询效率会提高。</p>
<p>通过SQL 查询分析器，显示比较：我的结论是:<br>分页方案二：(利用ID大于多少和SELECT TOP分页）效率最高，需要拼接SQL语句<br>分页方案一：(利用Not In和SELECT TOP分页)&nbsp;&nbsp; 效率次之，需要拼接SQL语句<br>分页方案三：(利用SQL的游标存储过程分页)&nbsp;&nbsp;&nbsp; 效率最差，但是最为通用</p>
<p>在实际情况中，要具体分析。</p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/120798.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2007-05-30 09:19 <a href="http://www.blogjava.net/Daniel2005/articles/120798.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何避免被破解!</title><link>http://www.blogjava.net/Daniel2005/articles/111351.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 17 Apr 2007 09:04:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/111351.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/111351.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/111351.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/111351.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/111351.html</trackback:ping><description><![CDATA[&nbsp;btw, If you RUN IIS 6.0, just disable access to root directory using &amp;quote;..\&amp;quote; and also, disable &amp;quote;Detailed Error Message&amp;quote; and replace it with &amp;quote;Sorry, and error has occured&amp;quote; this way, there is no way for the attempting hacker to get any info back. Also in your ASP code or ASP.NET either use stored procedures, or make addition check statements to look at your Request.QueryString(&amp;quote;&amp;quote;) or Request.Form(&amp;quote;&amp;quote;)... like.. do a instr(stringname,&amp;quote;;&amp;quote;) test and see if &amp;quote;;&amp;quote; is found, if so throw exception. because if you enter data into a vulnerable form this will happen: <br>Lets say you input &amp;quote;test' ; &lt;any SQL Command&gt;;&amp;quote; into the form, then for the following SQL Query <br>SQLString = &amp;quote;Select * From Table1 where Username='&amp;quote; &amp; userName &amp; &amp;quote;'&amp;quote;... <br>It would look like : <br>Select * From Table1 where Username='test'; &lt;any SQL Command&gt;; <br>Which would then execute whatever comes after. <br><br>And you should test for other similar things, such as comamnds to Delete records and so forth. :) 
<img src ="http://www.blogjava.net/Daniel2005/aggbug/111351.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2007-04-17 17:04 <a href="http://www.blogjava.net/Daniel2005/articles/111351.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ajax+javascript滚动条</title><link>http://www.blogjava.net/Daniel2005/articles/107255.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Thu, 29 Mar 2007 08:42:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/107255.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/107255.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/107255.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/107255.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/107255.html</trackback:ping><description><![CDATA[
		<p>// <br />var DIV_BG_COLOR = "#FFFFFF";<br />// <br />var DIV_HIGHLIGHT_COLOR = "#a5e0f5";<br />// <br />var DIV_FONT = "Arial";<br />// <br />var DIV_PADDING = "1px";<br />// <br />var DIV_BORDER = "0px solid #a5e0f5";</p>
		<p>var queryFieldWidth; //add by daniel save control width; 28/03/2007<br />// <br />var queryField;<br />// <br />var divName;<br />// <br />var ifName;<br />// <br />var lastVal = "";<br />// <br />var val = "";<br />// <br />var globalDiv;<br />// <br />var divFormatted = false;<br />/*add by daniel for save iframe width, height*/<br />//var iFrameDivWidth=0;<br />var iFrameDivHeight=0;<br />var iFrameDivTop=0;<br />var iFrameDivLeft=0;<br />var iFrameDivZindex=0;<br />/**<br />InitQueryCode&lt;body onload&gt;:<br />queryFieldNameid,<br />hiddenDivNamedivid<br />*/<br />function InitQueryCode (queryFieldName, hiddenDivName,queryTextName)<br />{<br /> // <br /> if (queryTextName!="" &amp;&amp; queryTextName!=undefined){<br />  queryField = document.getElementById(queryTextName);<br /> }else{<br />  queryField = document.getElementById(queryFieldName);<br /> } <br /> queryFieldWidth=document.getElementById(queryField.id).offsetWidth;<br /> //queryField = document.getElementById(queryTextName);<br /> //queryField.onblur = hideDiv;<br /> queryField.onmouseover =  hideDiv;<br /> queryField.onkeydown = keypressHandler;</p>
		<p> // 设置queryField的autocomplete属性为"off"<br /> queryField.autocomplete = "off";</p>
		<p> //<br /> if (hiddenDivName)<br /> {<br />  divName = hiddenDivName;<br /> }<br /> else<br /> {<br />  divName = "querydiv";<br /> }<br /> <br /> // IFramename<br /> ifName = "queryiframe";<br /> <br /> // <br /> setTimeout("mainLoop()", 100);<br />}</p>
		<p>/**</p>
		<p>*/<br />function getDiv (divID)<br />{<br /> //if (!globalDiv)<br /> //{<br />  // <br />  <br />  if (!document.getElementById(divID))<br />  {<br />   var newNode = document.createElement("div");<br />   newNode.setAttribute("id", divID);<br />   document.body.appendChild(newNode);<br />  }</p>
		<p>  //   <br />  globalDiv = document.getElementById(divID);</p>
		<p>  //   <br />  var x = queryField.offsetLeft;<br />  var y = queryField.offsetTop + queryField.offsetHeight;<br />  var parent = queryField;<br />  while (parent.offsetParent)<br />  {<br />   parent = parent.offsetParent;<br />   x += parent.offsetLeft;<br />   y += parent.offsetTop;<br />  }</p>
		<p>  //   <br />  //if (!divFormatted)<br />  //{<br />   globalDiv.style.backgroundColor = DIV_BG_COLOR;<br />   globalDiv.style.fontFamily = DIV_FONT;<br />   globalDiv.style.padding = DIV_PADDING;<br />   globalDiv.style.border = DIV_BORDER;<br />   //globalDiv.style.width = "100px";<br />   globalDiv.style.width = queryFieldWidth;<br />   globalDiv.style.height="300px";<br />   <br />   globalDiv.style.fontSize = "90%";<br />   //globalDiv.style.overflow = "scroll";<br />   globalDiv.style.overflowY = "scroll";<br />   //globalDiv.style.overflowX = "hidden";<br />   globalDiv.style.border="black 1px solid";<br />   //globalDiv.style.BORDER-TOP="black 1px solid";<br />   globalDiv.style.overflow = "auto";<br />   //globalDiv.style.BORDER-LEFT="black 1px solid";<br />   //globalDiv.style.BORDER-BOTTOM="black 1px solid";</p>
		<p>   globalDiv.style.position = "absolute";<br />   globalDiv.style.left = x + "px";<br />   globalDiv.style.top = y + "px";<br />   globalDiv.style.visibility = "hidden";<br />   globalDiv.style.zIndex = 10000;</p>
		<p>   //add by daniel for iFrame 12/25<br />   //iFrameDivWidth = globalDiv.offsetWidth;<br />   iFrameDivHeight = globalDiv.offsetHeight;<br />   iFrameDivTop = globalDiv.style.top;<br />   iFrameDivLeft = globalDiv.style.left;<br />   iFrameDivZindex = globalDiv.style.zIndex - 1;<br />   <br />   divFormatted = true;<br />  //}<br /> //}</p>
		<p> return globalDiv;<br />}</p>
		<p>/**</p>
		<p>*/<br />function showQueryDiv(resultArray)<br />{<br /> // <br /> var div = getDiv(divName);<br /> <br /> // <br /> while (div.childNodes.length &gt; 0)<br />  div.removeChild(div.childNodes[0]);<br />  <br /> document.all['hidselectcounty'].value="";<br /> document.all['hidselectname'].value="";<br /> document.all['hidselectlandmark_name'].value="";<br /> document.all['hidselectst_name'].value="";<br /> document.all['hidselectst_no'].value="";<br /> document.all['hidselectx_st'].value="";<br /> document.all['hidselectzip_code'].value="";</p>
		<p> // <br /> for (var i = 0; i &lt; resultArray.length; i++)<br /> {<br />  // <br />  var result = document.createElement("div");<br />  // <br />  result.style.cursor = "pointer";<br />  result.style.padding = "2px 0px 2px 0px";<br />  // <br />  _unhighlightResult(result);<br />  // <br />  result.onmousedown = selectResult;<br />  result.onmouseover = highlightResult;<br />  result.onmouseout = unhighlightResult;  //modify by william 2007/03/29</p>
		<p>  // <br />  /*var result1 = document.createElement("span");<br />  //<br />  result1.className = "result1";<br />  result1.style.textAlign = "left";<br />  result1.style.fontWeight = "bold";<br />  result1.innerHTML = resultArray[i];*/<br />  var result1 = document.createElement("span");</p>
		<p>  result1.className = "result1";<br />  result1.style.textAlign = "left";<br />  <br />  var strresultArray=resultArray[i].split('/');<br />  //declare some value to some text<br />  var strresultcounty=strresultArray[0];<br />  var strresultvalue=strresultArray[1];  <br />  var strresultlandmark=strresultArray[2];<br />  var strresultst_name=strresultArray[3];<br />  var strresultst_no=strresultArray[4];<br />  var strresultx_st=strresultArray[5];<br />  var strresultzip_code=strresultArray[6];<br />  //set all values<br />  document.all['hidselectcounty'].value=document.all['hidselectcounty'].value+'/'+strresultcounty;<br />  document.all['hidselectname'].value=document.all['hidselectname'].value+'/'+strresultvalue;<br />  document.all['hidselectlandmark_name'].value=document.all['hidselectlandmark_name'].value+'/'+strresultlandmark;<br />  document.all['hidselectst_name'].value=document.all['hidselectst_name'].value+'/'+strresultst_name;<br />  document.all['hidselectst_no'].value=document.all['hidselectst_no'].value+'/'+strresultst_no;<br />  document.all['hidselectx_st'].value=document.all['hidselectx_st'].value+'/'+strresultx_st;<br />  document.all['hidselectzip_code'].value=document.all['hidselectzip_code'].value+'/'+strresultzip_code;  <br />//  result1.innerHTML = resultArray[i];<br />  result1.innerHTML = strresultvalue;<br />  // <br />  result.appendChild(result1);<br />  <br />  // <br />  div.appendChild(result);<br /> }</p>
		<p> // <br /> showDiv(resultArray.length &gt; 0);<br />}</p>
		<p>/**</p>
		<p>*/<br />function selectResult()<br />{<br /> _selectResult(this);<br />}</p>
		<p>// <br />function _selectResult(item)<br />{<br /> //InitQueryCode('txtpu_street','','txtdest_street');<br /> var spans = item.getElementsByTagName("span");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   if (spans[i].className == "result1")<br />   {<br />    queryField.value = spans[i].innerHTML;<br />    lastVal = val = escape(queryField.value);<br />    mainLoop();<br />    queryField.focus();<br />    showDiv(false);<br />    //document.getElementById("hidonkeyormouse").value="Y";<br />    if (queryField.id.indexOf("pu") &gt; 0){<br />     select_result_all_value('p',queryField.value,queryField.id);<br />    }else if (queryField.id.indexOf("dest") &gt; 0){<br />     select_result_all_value('d',queryField.value,queryField.id);<br />    }<br />    return;<br />   }<br />  }<br /> }<br />}</p>
		<p>/**<br />*/<br />function highlightResult()<br />{<br /> _highlightResult(this);<br />}</p>
		<p>function _highlightResult(item)<br />{<br /> item.style.backgroundColor = DIV_HIGHLIGHT_COLOR;<br />}</p>
		<p>/**<br />*/<br />function unhighlightResult()<br />{<br /> _unhighlightResult(this);<br />}</p>
		<p>function _unhighlightResult(item)<br />{<br /> item.style.backgroundColor = DIV_BG_COLOR;<br />}</p>
		<p>/**<br />*/<br />function showDiv (show)<br />{<br /> var div = getDiv(divName);<br /> if (show)<br /> {<br />  div.style.visibility = "visible";<br /> }<br /> else<br /> {<br />  div.style.visibility = "hidden";<br /> }<br /> var Version=document.getElementById("hidVersion").value;<br /> <br /> if (Version=="6.0"){ <br />  adjustiFrame(show);<br /> }<br />}</p>
		<p>/**<br />*/<br />function hideDiv ()<br />{<br /> showDiv(false);<br />}</p>
		<p>/**<br />*/<br />function adjustiFrame(show)<br />{<br /> <br /> if (!document.getElementById(ifName))<br /> {<br />  var newNode = document.createElement("iFrame");<br />  newNode.setAttribute("id", ifName);<br />  newNode.setAttribute("src", "javascript:false;");<br />  newNode.setAttribute("scrolling", "no");<br />  newNode.setAttribute("frameborder", "0");  <br />  document.body.appendChild(newNode);<br /> }</p>
		<p> iFrameDiv = document.getElementById(ifName);<br /> //var div = getDiv(divName);</p>
		<p> try<br /> {  <br />  var Version=document.getElementById("hidVersion").value;<br />  if (Version=="7.0"){<br />   iFrameDiv.style.position = "absolute";<br />   iFrameDiv.style.width = queryFieldWidth;   <br />   iFrameDiv.style.height="300px"; //add by daniel 27/03/2007  <br />   iFrameDiv.style.overflow = "scroll"; //add by daniel 27/03/2007 <br />  <br />   iFrameDiv.outerText = "No results";<br />  <br />   iFrameDiv.style.top = iFrameDivTop;<br />   iFrameDiv.style.left = iFrameDivLeft;<br />   iFrameDiv.style.zIndex = iFrameDivZindex;<br />   //if (show==true){<br />   iFrameDiv.style.visibility = "visible";<br />   //}else{<br />   // iFrameDiv.style.visibility = "hidden";<br />   //}<br />  }else if(Version=="6.0"){<br />   //alert(Version);<br />   iFrameDiv.style.position = "absolute";<br />   /*iFrameDiv.style.width = div.offsetWidth;<br />   iFrameDiv.style.height = div.offsetHeight;<br />   iFrameDiv.style.top = div.style.top;<br />   iFrameDiv.style.left = div.style.left;<br />   iFrameDiv.style.zIndex = div.style.zIndex - 1;<br />   //iFrameDiv.style.visibility = div.style.visibility;*/<br />   iFrameDiv.style.width = queryFieldWidth;   // modify some code by william 2007/03/29<br />   //iFrameDiv.style.height = iFrameDivHeight;  <br />   iFrameDiv.style.height="300px"; //add by daniel 27/03/2007  <br />   iFrameDiv.style.overflow = "scroll"; //add by daniel 27/03/2007<br />  <br />   iFrameDiv.style.top = iFrameDivTop;<br />   iFrameDiv.style.left = iFrameDivLeft;<br />   iFrameDiv.style.zIndex = iFrameDivZindex;<br />   if (show==true){<br />    iFrameDiv.style.visibility = "visible";<br />   }else{<br />    iFrameDiv.style.visibility = "hidden";<br />   }<br />  }<br />  <br /> }<br /> catch (e)<br /> {   <br />  iFrameDiv.style.visibility = "visible";<br /> }<br />}</p>
		<p>/**<br />*/<br />function keypressHandler (evt)<br />{<br /> //   <br /> var div = getDiv(divName);<br /> <br /> //   <br /> if (div.style.visibility == "hidden")<br /> {<br />  return true;<br /> }</p>
		<p> //  <br /> if (!evt &amp;&amp; window.event)<br /> {<br />  evt = window.event;<br /> }<br /> var key = evt.keyCode;</p>
		<p> var KEYUP = 38;<br /> var KEYDOWN = 40;<br /> var KEYENTER = 13;<br /> var KEYTAB = 9;<br /> var KEYBACK = 8;<br /> //   <br /> if ((key != KEYUP) &amp;&amp; (key != KEYDOWN) &amp;&amp; (key != KEYENTER) &amp;&amp; (key != KEYTAB) &amp;&amp; (key != KEYBACK))<br /> {<br />  return true;<br /> }</p>
		<p> var selNum = getSelectedSpanNum(div);<br /> var selSpan = setSelectedSpan(div, selNum);<br /> <br /> //  <br /> if ((key == KEYENTER) || (key == KEYTAB))<br /> {<br />  if (selSpan)<br />  {<br />   _selectResult(selSpan);<br />  }<br />  evt.cancelBubble = true;<br />  return false;<br /> }<br /> else //<br /> {<br />  if (key == KEYUP)<br />  {<br />   selSpan = setSelectedSpan(div, selNum - 1);<br />  }<br />  if (key == KEYDOWN)<br />  {<br />   selSpan = setSelectedSpan(div, selNum + 1);<br />  }<br />  if (selSpan)<br />  {<br />   _highlightResult(selSpan);<br />  }<br /> }</p>
		<p> // <br /> showDiv(true);<br /> return true;<br />}</p>
		<p>/**<br />*/<br />function getSelectedSpanNum(div)<br />{<br /> var count = -1;<br /> var spans = div.getElementsByTagName("div");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   count++;<br />   if (spans[i].style.backgroundColor != div.style.backgroundColor)<br />   {<br />    return count;<br />   }<br />  }<br /> }</p>
		<p> return -1;<br />}</p>
		<p>/**<br />*/<br />function setSelectedSpan(div, spanNum)<br />{<br /> var count = -1;<br /> var thisSpan;<br /> var spans = div.getElementsByTagName("div");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   if (++count == spanNum)<br />   {<br />    _highlightResult(spans[i]);<br />    thisSpan = spans[i];<br />   }<br />   else<br />   {<br />    _unhighlightResult(spans[i]);<br />   }<br />  }<br /> }</p>
		<p> return thisSpan;<br />}<br /><br /><br />目前在IE7测试下通过，如果是IE6可能会出现false下拉。。</p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/107255.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2007-03-29 16:42 <a href="http://www.blogjava.net/Daniel2005/articles/107255.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AJAx+ javascript.</title><link>http://www.blogjava.net/Daniel2005/articles/105279.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Wed, 21 Mar 2007 07:34:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/105279.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/105279.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/105279.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/105279.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/105279.html</trackback:ping><description><![CDATA[
		<p>// <br />var DIV_BG_COLOR = "#FFFFFF";<br />// <br />var DIV_HIGHLIGHT_COLOR = "#a5e0f5";<br />// <br />var DIV_FONT = "Arial";<br />// <br />var DIV_PADDING = "1px";<br />// <br />var DIV_BORDER = "0px solid #a5e0f5";</p>
		<p>
				<br />// <br />var queryField;<br />//add by daniel <br />/*var queryText;<br />var queryPuLandmark;<br />var queryDestLandmark;*/<br />// <br />var divName;<br />// <br />var ifName;<br />// <br />var lastVal = "";<br />// <br />var val = "";<br />// <br />var globalDiv;<br />// <br />var divFormatted = false;</p>
		<p>/*add by daniel for save iframe width, height*/<br />var iFrameDivWidth=0;<br />var iFrameDivHeight=0;<br />var iFrameDivTop=0;<br />var iFrameDivLeft=0;<br />var iFrameDivZindex=0;<br />var ShowDivBoolean=false; //control div show or not<br />/**<br />*/<br />//function InitQueryCode (queryFieldName, hiddenDivName,queryTextName,queryPuLandmarkName,queryDestLandmarkName)<br />function InitQueryCode (queryFieldName, hiddenDivName,queryTextName)<br />{<br /> // <br /> /*if (document.all['hidpu_landmarkonkey'].value=="N" &amp;&amp; document.all['hiddest_landmarkonkey'].value=="N"){<br />  if (document.all['hidpu_streetonkey'].value=="Y"){<br />   queryField = document.getElementById(queryFieldName);<br />  }else if (document.all['hiddest_streetonkey'].value=="Y"){<br />   queryField = document.getElementById(queryTextName);<br />  }else{<br />   queryField = document.getElementById(queryFieldName);<br />  }<br /> }else if(document.all['hidpu_landmarkonkey'].value=="Y" &amp;&amp; document.all['hiddest_landmarkonkey'].value=="N"){<br />  queryField = document.getElementById(queryPuLandmarkName);<br /> }else if(document.all['hidpu_landmarkonkey'].value=="N" &amp;&amp; document.all['hiddest_landmarkonkey'].value=="Y"){<br />  queryField = document.getElementById(queryDestLandmarkName);<br /> }*/<br /> if (queryTextName!="" &amp;&amp; queryTextName!=undefined){<br />  queryField = document.getElementById(queryTextName);<br /> }else{<br />  queryField = document.getElementById(queryFieldName);<br /> } <br /> //queryField = document.getElementById(queryTextName);<br /> queryField.onblur = hideDiv;<br /> queryField.onkeydown = keypressHandler;<br /> // <br /> queryField.autocomplete = "off";</p>
		<p> //<br /> if (hiddenDivName)<br /> {<br />  divName = hiddenDivName;<br /> }<br /> else<br /> {<br />  divName = "querydiv";<br /> }<br /> <br /> // IFramename<br /> ifName = "queryiframe";<br /> <br /> // <br /> setTimeout("mainLoop()", 100);<br />}</p>
		<p>
				<br />function getDiv (divID)<br />{</p>
		<p>// if (!globalDiv)<br />// {</p>
		<p>  <br />  if (!document.getElementById(divID))<br />  {<br />   var newNode = document.createElement("div");<br />   newNode.setAttribute("id", divID);<br />   document.body.appendChild(newNode);<br />  }<br /> <br />  globalDiv = document.getElementById(divID);<br />  //InitQueryCode('txtpu_street','','txtdest_street',);<br />  <br />  var x = queryField.offsetLeft;<br />  var y = queryField.offsetTop + queryField.offsetHeight;<br />  var parent = queryField;<br />  while (parent.offsetParent)<br />  {<br />   parent = parent.offsetParent;<br />   x += parent.offsetLeft;<br />   y += parent.offsetTop;<br />  }<br />  //divFormatted=false;<br />  //if (!divFormatted)<br />  //{<br />  try{<br />   if (div.style.visibility == "visible"){<br />   /*var resultText=globalDiv.outerText.split('/');<br />   var resultValue=resultText[1];<br />   <br />   globalDiv.outerText=resultValue;*/<br />     <br />   globalDiv.style.backgroundColor = DIV_BG_COLOR;<br />   globalDiv.style.fontFamily = DIV_FONT;<br />   globalDiv.style.padding = DIV_PADDING;<br />   //globalDiv.style.border = DIV_BORDER;<br />   globalDiv.style.width = "100px";<br />   globalDiv.style.height="150px";<br />   globalDiv.style.fontSize = "90%";<br />   globalDiv.style.overflow = "auto";</p>
		<p>   globalDiv.style.position = "absolute";<br />   globalDiv.style.left = x + "px";<br />   globalDiv.style.top = y + "px";<br />   globalDiv.style.visibility = "hidden";<br />   globalDiv.style.zIndex = 10000;<br />   //add by daniel for iFrame 12/25<br />   iFrameDivWidth = globalDiv.offsetWidth;<br />   iFrameDivHeight = globalDiv.offsetHeight;<br />   iFrameDivTop = globalDiv.style.top;<br />   iFrameDivLeft = globalDiv.style.left;<br />   iFrameDivZindex = globalDiv.style.zIndex - 1;<br />  <br />   divFormatted = true;<br />   div.style.visibility == "visible"<br />   }   <br />  }<br />  catch(e){<br />   /*var resultText=globalDiv.outerText.split('/');<br />   var resultValue=resultText[1];<br />   <br />   globalDiv.outerText=resultValue;*/<br />   globalDiv.style.backgroundColor = DIV_BG_COLOR;<br />   globalDiv.style.fontFamily = DIV_FONT;<br />   globalDiv.style.padding = DIV_PADDING;<br />   //globalDiv.style.border = DIV_BORDER;<br />   globalDiv.style.width = "100px";<br />   <strong><font style="BACKGROUND-COLOR: #ff0000">globalDiv.style.height="150px";<br /></font></strong>   globalDiv.style.fontSize = "90%";<br />   <font style="BACKGROUND-COLOR: #ff0000"><strong>globalDiv.style.overflow = "auto";               //会出现下拉选择.</strong></font></p>
		<p>   globalDiv.style.position = "absolute";<br />   globalDiv.style.left = x + "px";<br />   globalDiv.style.top = y + "px";<br />   globalDiv.style.visibility = "hidden";<br />   globalDiv.style.zIndex = 10000;<br />   //add by daniel for iFrame 12/25<br />   iFrameDivWidth = globalDiv.offsetWidth;<br />   iFrameDivHeight = globalDiv.offsetHeight;<br />   iFrameDivTop = globalDiv.style.top;<br />   iFrameDivLeft = globalDiv.style.left;<br />   iFrameDivZindex = globalDiv.style.zIndex - 1;<br />   <br />   divFormatted = true;  <br />  }<br />  //}<br />// }</p>
		<p> return globalDiv;<br />}</p>
		<p>
				<br />function showQueryDiv(resultArray)<br />{</p>
		<p> var div = getDiv(divName);<br /> <br /> while (div.childNodes.length &gt; 0) <br /> div.removeChild(div.childNodes[0]);<br /> document.all['hidselectcounty'].value="";<br /> document.all['hidselectname'].value="";<br /> document.all['hidselectlandmark_name'].value="";<br /> document.all['hidselectst_name'].value="";<br /> document.all['hidselectst_no'].value="";<br /> document.all['hidselectx_st'].value="";<br /> document.all['hidselectzip_code'].value="";</p>
		<p>    //InitQueryCode('txtpu_street','','txtdest_street','txtpu_landmark','txtdest_landmark'); <br />    try{<br /> for (var i = 0; i &lt; resultArray.length; i++)<br /> {</p>
		<p>  var result = document.createElement("div");</p>
		<p>  result.style.cursor = "pointer";<br />  result.style.padding = "2px 0px 2px 0px";</p>
		<p>  _unhighlightResult(result);<br /> <br />  result.onmousedown = selectResult;<br />  result.onmouseover = highlightResult;<br />  result.onmouseout = unhighlightResult;</p>
		<p>  var result1 = document.createElement("span");</p>
		<p>  result1.className = "result1";<br />  result1.style.textAlign = "left";<br />  //result1.style.fontWeight = "bold";<br />  var strresultArray=resultArray[i].split('/');<br />  //declare some value to some text<br />  var strresultcounty=strresultArray[0];<br />  var strresultvalue=strresultArray[1];  <br />  var strresultlandmark=strresultArray[2];<br />  var strresultst_name=strresultArray[3];<br />  var strresultst_no=strresultArray[4];<br />  var strresultx_st=strresultArray[5];<br />  var strresultzip_code=strresultArray[6];<br />  //set all values<br />  document.all['hidselectcounty'].value=document.all['hidselectcounty'].value+'/'+strresultcounty;<br />  document.all['hidselectname'].value=document.all['hidselectname'].value+'/'+strresultvalue;<br />  document.all['hidselectlandmark_name'].value=document.all['hidselectlandmark_name'].value+'/'+strresultlandmark;<br />  document.all['hidselectst_name'].value=document.all['hidselectst_name'].value+'/'+strresultst_name;<br />  document.all['hidselectst_no'].value=document.all['hidselectst_no'].value+'/'+strresultst_no;<br />  document.all['hidselectx_st'].value=document.all['hidselectx_st'].value+'/'+strresultx_st;<br />  document.all['hidselectzip_code'].value=document.all['hidselectzip_code'].value+'/'+strresultzip_code;  <br />//  result1.innerHTML = resultArray[i];<br />  result1.innerHTML = strresultvalue;<br />  <br />  result.appendChild(result1);  <br />  <br />  div.appendChild(result);<br /> }</p>
		<p> showDiv(resultArray.length &gt; 0);<br /> }<br /> catch(ex){}<br />}</p>
		<p>function selectResult()<br />{<br /> _selectResult(this);<br />}</p>
		<p>function _selectResult(item)<br />{</p>
		<p> //InitQueryCode('txtpu_street','','txtdest_street');<br /> var spans = item.getElementsByTagName("span");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   if (spans[i].className == "result1")<br />   {<br />    queryField.value = spans[i].innerHTML;<br />    lastVal = val = escape(queryField.value);<br />    mainLoop();<br />    queryField.focus();<br />    showDiv(false);<br />    //document.getElementById("hidonkeyormouse").value="Y";<br />    if (queryField.id.indexOf("pu") &gt; 0){<br />     select_result_all_value('p',queryField.value,queryField.id);<br />    }else if (queryField.id.indexOf("dest") &gt; 0){<br />     select_result_all_value('d',queryField.value,queryField.id);<br />    }<br />    return;<br />   }<br />  }<br /> }<br />}</p>
		<p>function highlightResult()<br />{<br /> _highlightResult(this);<br />}</p>
		<p>function _highlightResult(item)<br />{<br /> item.style.backgroundColor = DIV_HIGHLIGHT_COLOR;<br />}</p>
		<p>function unhighlightResult()<br />{<br /> _unhighlightResult(this);<br />}</p>
		<p>function _unhighlightResult(item)<br />{<br /> item.style.backgroundColor = DIV_BG_COLOR;<br />}</p>
		<p>
				<br />function showDiv (show)<br />{<br /> var div = getDiv(divName);<br /> if (show)<br /> {<br />  div.style.visibility = "visible";<br />  ShowDivBoolean=true;<br /> }<br /> else<br /> {<br />  div.style.visibility = "hidden";<br />  ShowDivBoolean=false;<br /> }<br /> //adjustiFrame();<br />}</p>
		<p>
				<br />function hideDiv ()<br />{<br /> showDiv(false);<br />}</p>
		<p>
				<br />function adjustiFrame()<br />{<br /> <br /> if (!document.getElementById(ifName))<br /> {<br />  var newNode = document.createElement("iFrame");<br />  newNode.setAttribute("id", ifName);<br />  newNode.setAttribute("src", "javascript:false;");<br />  newNode.setAttribute("scrolling", "no");<br />  newNode.setAttribute("frameborder", "0");<br />  document.body.appendChild(newNode);<br /> }</p>
		<p> iFrameDiv = document.getElementById(ifName);<br /> //var div = getDiv(divName);</p>
		<p> try<br /> {  <br />  iFrameDiv.style.position = "absolute";<br />  /*iFrameDiv.style.width = div.offsetWidth;<br />  iFrameDiv.style.height = div.offsetHeight;<br />  iFrameDiv.style.top = div.style.top;<br />  iFrameDiv.style.left = div.style.left;<br />  iFrameDiv.style.zIndex = div.style.zIndex - 1;<br />  //iFrameDiv.style.visibility = div.style.visibility;*/<br />  iFrameDiv.style.width = iFrameDivWidth;<br />  iFrameDiv.style.height = iFrameDivHeight;<br />  iFrameDiv.style.top = iFrameDivTop;<br />  iFrameDiv.style.left = iFrameDivLeft;<br />  iFrameDiv.style.zIndex = iFrameDivZindex;<br />  if (ShowDivBoolean==true){<br />   iFrameDiv.style.visibility = "visible";<br />  }else{<br />   iFrameDiv.style.visibility = "hidden";<br />  }<br />  <br /> }<br /> catch (e)<br /> {<br /> }<br />}</p>
		<p>function keypressHandler (evt)<br />{<br /> //InitQueryCode('txtpu_street','',controlname);<br /> <br /> var div = getDiv(divName);<br />  <br /> /*if (div.style.visibility == "hidden")<br /> {<br />  return true;  <br /> }*/</p>
		<p> if (!evt &amp;&amp; window.event)<br /> {<br />  evt = window.event;<br /> }<br /> var key = evt.keyCode;</p>
		<p> var KEYUP = 38;<br /> var KEYDOWN = 40;<br /> var KEYENTER = 13;<br /> var KEYTAB = 9;<br />  <br /> if ((key != KEYUP) &amp;&amp; (key != KEYDOWN) &amp;&amp; (key != KEYENTER) &amp;&amp; (key != KEYTAB))<br /> {<br />  return true;<br /> }</p>
		<p> var selNum = getSelectedSpanNum(div);<br /> var selSpan = setSelectedSpan(div, selNum);<br /> <br /> if ((key == KEYENTER) || (key == KEYTAB))<br /> {<br />  if (selSpan)<br />  {<br />   _selectResult(selSpan);<br />  }<br />  evt.cancelBubble = true;<br />  return false;<br /> }<br /> else //<br /> {<br />  if (key == KEYUP)<br />  {<br />   selSpan = setSelectedSpan(div, selNum - 1);<br />  }<br />  if (key == KEYDOWN)<br />  {<br />   selSpan = setSelectedSpan(div, selNum + 1);<br />  }<br />  if (selSpan)<br />  {<br />   _highlightResult(selSpan);<br />  }<br /> }</p>
		<p> // <br /> showDiv(true);<br /> return true;<br />}</p>
		<p>/**</p>
		<p>*/<br />function getSelectedSpanNum(div)<br />{<br /> //InitQueryCode('txtpu_street','','txtdest_street','txtpu_landmark','txtdest_landmark'); <br /> var count = -1;<br /> var spans = div.getElementsByTagName("div");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   count++;<br />   if (spans[i].style.backgroundColor != div.style.backgroundColor)<br />   {<br />    return count;<br />   }<br />  }<br /> }</p>
		<p> return -1;<br />}</p>
		<p>/**<br />*/<br />function setSelectedSpan(div, spanNum)<br />{<br /> //InitQueryCode('txtpu_street','','txtdest_street','txtpu_landmark','txtdest_landmark'); <br /> var count = -1;<br /> var thisSpan;<br /> var spans = div.getElementsByTagName("div");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   if (++count == spanNum)<br />   {<br />    _highlightResult(spans[i]);<br />    thisSpan = spans[i];<br />   }<br />   else<br />   {<br />    _unhighlightResult(spans[i]);<br />   }<br />  }<br /> }</p>
		<p> return thisSpan;<br />}</p>
		<p> </p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/105279.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2007-03-21 15:34 <a href="http://www.blogjava.net/Daniel2005/articles/105279.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>AJAX+asp.net 1.0不刷新页技术！</title><link>http://www.blogjava.net/Daniel2005/articles/89823.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Mon, 25 Dec 2006 01:46:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/89823.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/89823.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/89823.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/89823.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/89823.html</trackback:ping><description><![CDATA[
		<p>已经好长时间没有写日志了！前些日子在网上一直找asp.net 1.0不刷新页技术！我总结了一下。给出了一个例子！<br /><font color="#ff0000"><strong>First step: Create a new page name is AutoComplete.</strong></font><br /><br />&lt;%@ Page Language="vb" AutoEventWireup="false" Codebehind="AutoComplete.aspx.vb" Inherits="VB_AJAXTEST.VB_AJAXTEST.AutoComplete"%&gt;<br />&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"&gt;<br />&lt;HTML&gt;<br /> &lt;HEAD&gt;<br />  &lt;title&gt;AutoComplete&lt;/title&gt;<br />  &lt;meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1"&gt;<br />  &lt;meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1"&gt;<br />  &lt;meta name="vs_defaultClientScript" content="JavaScript"&gt;<br />  &lt;meta name="vs_targetSchema" content="<a href="http://schemas.microsoft.com/intellisense/ie5">http://schemas.microsoft.com/intellisense/ie5</a>"&gt;<br />  &lt;script language="javascript" src="lookup.js"&gt;&lt;/script&gt;<br />  &lt;script language="jscript"&gt;<br />  <br />  mainLoop = function()<br />  {<br />   val = escape(queryField.value);    <br />   if (lastVal != val)<br />   {    <br />    var response = VB_AJAXTEST.VB_AJAXTEST.AutoComplete.GetSearchItems(val);<br />    showQueryDiv(response.value);<br />    lastVal = val;<br />   }    <br />   setTimeout('mainLoop()', 100);<br />   return true;<br />  }<br />  &lt;/script&gt;<br /> &lt;/HEAD&gt;<br /> &lt;body onload="javascript:InitQueryCode('search')"&gt;<br />  &lt;form id="Form1" method="post" runat="server"&gt;<br />   &lt;asp:Label id="Label1" runat="server" Font-Names="黑体,Arial Black" Font-Bold="True" Font-Size="X-Large"&gt;基于AJAX的自动完成功能&lt;/asp:Label&gt;<br />   &lt;hr&gt;<br />   &lt;asp:Label id="Label2" runat="server"&gt;请输入员工姓名：&lt;/asp:Label&gt;<br />   &lt;input name="search" type="text" id="search" autocomplete="off" runat="server"&gt;<br />   &lt;asp:Button id="btnSearch" runat="server" Text="查看"&gt;&lt;/asp:Button&gt;<br />   &lt;br&gt;<br />   &lt;asp:DataList id="dlEmployee" runat="server" BorderColor="#DEDFDE" BorderStyle="None" ForeColor="Black"<br />    BackColor="White" CellPadding="4" GridLines="Vertical" BorderWidth="1px"&gt;<br />    &lt;SelectedItemStyle Font-Bold="True" ForeColor="White" BackColor="#CE5D5A"&gt;&lt;/SelectedItemStyle&gt;<br />    &lt;AlternatingItemStyle BackColor="White"&gt;&lt;/AlternatingItemStyle&gt;<br />    &lt;ItemStyle BackColor="#F7F7DE"&gt;&lt;/ItemStyle&gt;<br />    &lt;ItemTemplate&gt;<br />     &lt;table cellSpacing="1" cellPadding="1" border="0"&gt;<br />      &lt;tr&gt;<br />       &lt;td&gt;员工编号：&lt;/td&gt;<br />       &lt;td&gt;&lt;%# DataBinder.Eval(Container, "DataItem.emp_id") %&gt;&lt;/td&gt;<br />      &lt;/tr&gt;<br />      &lt;tr&gt;<br />       &lt;td&gt;姓名：&lt;/td&gt;<br />       &lt;td&gt;&lt;%# DataBinder.Eval(Container, "DataItem.fname") %&gt;&amp;nbsp;&lt;%# DataBinder.Eval(Container, "DataItem.lname") %&gt;&lt;/td&gt;<br />      &lt;/tr&gt;<br />      &lt;tr&gt;<br />       &lt;td&gt;入司时间：&lt;/td&gt;<br />       &lt;td&gt;&lt;%# DataBinder.Eval(Container, "DataItem.hire_date", "{0:yyyy-MM-dd}") %&gt;&lt;/td&gt;<br />      &lt;/tr&gt;<br />      &lt;tr&gt;<br />       &lt;td&gt;职位：&lt;/td&gt;<br />       &lt;td&gt;&lt;%# DataBinder.Eval(Container, "DataItem.job_desc") %&gt;&lt;/td&gt;<br />      &lt;/tr&gt;<br />     &lt;/table&gt;<br />    &lt;/ItemTemplate&gt;<br />    &lt;FooterStyle BackColor="#CCCC99"&gt;&lt;/FooterStyle&gt;<br />    &lt;HeaderStyle Font-Bold="True" ForeColor="White" BackColor="#6B696B"&gt;&lt;/HeaderStyle&gt;<br />   &lt;/asp:DataList&gt;<br />   &lt;asp:Label id="lblMessage" runat="server" ForeColor="Red"&gt;&lt;/asp:Label&gt;<br />  &lt;/form&gt;<br /> &lt;/body&gt;<br />&lt;/HTML&gt;<br /><br />AutoComplete.aspx.vb<br />Imports System<br />Imports System.Collections<br />Imports System.ComponentModel<br />Imports System.Data<br />Imports System.Drawing<br />Imports System.Web<br />Imports System.Web.SessionState<br />Imports System.Web.UI<br />Imports System.Web.UI.WebControls<br />Imports System.Web.UI.HtmlControls<br />Imports System.Data.SqlClient<br />Imports AjaxPro</p>
		<p>Namespace VB_AJAXTEST</p>
		<p>    Public Class AutoComplete<br />        Inherits System.Web.UI.Page</p>
		<p>        Protected tbSearch As System.Web.UI.WebControls.TextBox<br />        Protected Label2 As System.Web.UI.WebControls.Label<br />        Protected btnSearch As System.Web.UI.WebControls.Button<br />        Protected dlEmployee As System.Web.UI.WebControls.DataList<br />        Protected search As System.Web.UI.HtmlControls.HtmlInputText<br />        Protected lblMessage As System.Web.UI.WebControls.Label<br />        Protected Label1 As System.Web.UI.WebControls.Label</p>
		<p>        Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)<br />            Utility.RegisterTypeForAjax(GetType(AutoComplete))<br />        End Sub</p>
		<p>        &lt;AjaxMethod()&gt; _<br />        Public Function GetSearchItems(ByVal query As String) As ArrayList<br />            Dim items As ArrayList = New ArrayList<br />            Dim myConnectionString As String = "SERVER=192.168.0.244;DATABASE=pubs;uid=sa;pwd=;Connect Timeout=30"<br />            Dim mySelectQuery As String = String.Format("select fname from employee where fname like '{0}%'", query)<br />            Dim myConnection As SqlConnection = New SqlConnection(myConnectionString)<br />            Dim myCommand As SqlCommand = New SqlCommand(mySelectQuery, myConnection)<br />            myConnection.Open()<br />            Dim myReader As SqlDataReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection)<br />            While myReader.Read<br />                items.Add(myReader.GetString(0))<br />            End While<br />            myReader.Close()<br />            Return items<br />        End Function</p>
		<p>        Protected Overloads Overrides Sub OnInit(ByVal e As EventArgs)<br />            InitializeComponent()<br />            MyBase.OnInit(e)<br />        End Sub</p>
		<p>        Private Sub InitializeComponent()<br />            AddHandler Me.btnSearch.Click, AddressOf Me.btnSearch_Click<br />            AddHandler Me.Load, AddressOf Me.Page_Load<br />        End Sub</p>
		<p>        Private Sub btnSearch_Click(ByVal sender As Object, ByVal e As System.EventArgs)<br />            BindList()<br />        End Sub</p>
		<p>        Private Sub BindList()<br />            Dim myConnectionString As String = "SERVER=192.168.0.244;DATABASE=pubs;uid=sa;pwd=;Connect Timeout=30"<br />            Dim mySelectQuery As String = String.Format("select a.*,b.job_desc from employee a, jobs b where fname like '{0}%' and a.job_id=b.job_id", search.Value)<br />            Dim myConnection As SqlConnection = New SqlConnection(myConnectionString)<br />            Dim myCommand As SqlCommand = New SqlCommand(mySelectQuery, myConnection)<br />            Dim da As SqlDataAdapter = New SqlDataAdapter(myCommand)<br />            Dim ds As DataSet = New DataSet<br />            Try<br />                myConnection.Open()<br />                da.Fill(ds)<br />                dlEmployee.DataSource = ds.Tables(0).DefaultView<br />                dlEmployee.DataBind()<br />            Catch ex As SqlException<br />                Response.Write(ex.Message)<br />            Finally<br />                myConnection.Close()<br />            End Try<br />            If ds.Tables(0).Rows.Count = 0 Then<br />                lblMessage.Text = "没有您要查找的员工信息！"<br />            Else<br />                lblMessage.Text = ""<br />            End If<br />        End Sub</p>
		<p>    End Class</p>
		<p>End Namespace<br /><br /><font color="#ff66ff"><font color="#ff0000"><strong>Second Step: Create a AjaxTextBox.vb.</strong></font><br /></font>Imports System<br />Imports System.Web.UI<br />Imports System.Web.UI.WebControls<br />Imports System.Web.UI.WebControls.TextBox</p>
		<p>Public Class AjaxTextBox<br />    Inherits System.Web.UI.WebControls.TextBox</p>
		<p>#Region "Private Property"</p>
		<p>    Private scriptFile_value As String = ""<br />    Private callBackFunction_value As String = ""<br />    Private backgroundColor_value As String = "#EEE"<br />    Private highlightColor_value As String = "#CCC"<br />    Private font_value As String = "Verdana"<br />    Private divPadding_value As String = "2px"<br />    Private divBorder_value As String = "1px solid #CCC"</p>
		<p>#End Region</p>
		<p>#Region "Public Property"</p>
		<p>    Public Property ScriptFile() As String<br />        Get<br />            Return scriptFile_value<br />        End Get<br />        Set(ByVal Value As String)<br />            scriptFile_value = Value<br />        End Set<br />    End Property</p>
		<p>    Public Property CallBackFunction() As String<br />        Get<br />            Return callBackFunction_value<br />        End Get<br />        Set(ByVal Value As String)<br />            callBackFunction_value = Value<br />        End Set<br />    End Property</p>
		<p>    Public Property BackgroundColor() As String<br />        Get<br />            Return backgroundColor_value<br />        End Get<br />        Set(ByVal Value As String)<br />            backgroundColor_value = Value<br />        End Set<br />    End Property</p>
		<p>    Public Property HighlightColor() As String<br />        Get<br />            Return highlightColor_value<br />        End Get<br />        Set(ByVal Value As String)<br />            highlightColor_value = Value<br />        End Set<br />    End Property</p>
		<p>    Public Property DivFont() As String<br />        Get<br />            Return font_value<br />        End Get<br />        Set(ByVal Value As String)<br />            font_value = Value<br />        End Set<br />    End Property</p>
		<p>    Public Property DivPadding() As String<br />        Get<br />            Return divPadding_value<br />        End Get<br />        Set(ByVal Value As String)<br />            divPadding_value = Value<br />        End Set<br />    End Property</p>
		<p>    Public Property DivBorder() As String<br />        Get<br />            Return divBorder_value<br />        End Get<br />        Set(ByVal Value As String)<br />            divPadding_value = Value<br />        End Set<br />    End Property</p>
		<p>#End Region</p>
		<p>#Region "Public AjaxTextBox"</p>
		<p>    Public Sub New()<br />        Me.Attributes.Add("AutoComplete", "off")<br />    End Sub</p>
		<p>    Protected Overloads Overrides Sub Render(ByVal writer As HtmlTextWriter)<br />        MyBase.Render(writer)<br />        Page.RegisterStartupScript("LoadScript", "&lt;script language='JavaScript' src='" + ScriptFile + "'&gt;&lt;/script&gt;")<br />        Dim styles As String = String.Format("&lt;script language='JavaScript'&gt;var DIV_BG_COLOR = '{0}';var DIV_HIGHLIGHT_COLOR = '{1}';var DIV_FONT = '{2}';var DIV_PADDING = '{3}';var DIV_BORDER = '{4}';&lt;/script&gt;", BackgroundColor, HighlightColor, DivFont, DivPadding, DivBorder)<br />        Page.RegisterStartupScript("LookupStyles", styles)<br />        Page.RegisterStartupScript("RegisterScript", "&lt;script language='JavaScript'&gt;InitQueryCode('" + Me.ClientID + "')&lt;/script&gt;")<br />        Page.RegisterStartupScript("RegisterCallBack", "&lt;script language='JavaScript'&gt;mainLoop = function() {val = escape(queryField.value);if(lastVal != val){var response = " + CallBackFunction + "(val);showQueryDiv(response.value); lastVal = val;}setTimeout('mainLoop()', 100);return true;};&lt;/script&gt;")<br />    End Sub</p>
		<p>#End Region</p>
		<p>End Class<br /><br /><font color="#ff0000"><strong>Third step: Create a lookup.js</strong></font><br />// 下拉区背景色<br />var DIV_BG_COLOR = "#EEE";<br />// 高亮显示条目颜色<br />var DIV_HIGHLIGHT_COLOR = "#C30";<br />// 字体<br />var DIV_FONT = "Arial";<br />// 下拉区内补丁大小<br />var DIV_PADDING = "2px";<br />// 下拉区边框样式<br />var DIV_BORDER = "1px solid #CCC";</p>
		<p>
				<br />// 文本输入框<br />var queryField;<br />// 下拉区id<br />var divName;<br />// IFrame名称<br />var ifName;<br />// 记录上次选择的值<br />var lastVal = "";<br />// 当前选择的值<br />var val = "";<br />// 显示结果的下拉区<br />var globalDiv;<br />// 下拉区是否设置格式的标记<br />var divFormatted = false;</p>
		<p>/**<br />InitQueryCode函数必须在&lt;body onload&gt;事件的响应函数中调用,其中:<br />queryFieldName为文本框控件的id,<br />hiddenDivName为显示下拉区div的id<br />*/<br />function InitQueryCode (queryFieldName, hiddenDivName)<br />{<br /> // 指定文本输入框的onblur和onkeydown响应函数<br /> queryField = document.getElementById(queryFieldName);<br /> queryField.onblur = hideDiv;<br /> queryField.onkeydown = keypressHandler;</p>
		<p> // 设置queryField的autocomplete属性为"off"<br /> queryField.autocomplete = "off";</p>
		<p> // 如果没有指定hiddenDivName,取默认值"querydiv"<br /> if (hiddenDivName)<br /> {<br />  divName = hiddenDivName;<br /> }<br /> else<br /> {<br />  divName = "querydiv";<br /> }<br /> <br /> // IFrame的name<br /> ifName = "queryiframe";<br /> <br /> // 100ms后调用mainLoop函数<br /> setTimeout("mainLoop()", 100);<br />}</p>
		<p>/**<br />获取下拉区的div,如果没有则创建之<br />*/<br />function getDiv (divID)<br />{<br /> if (!globalDiv)<br /> {<br />  // 如果div在页面中不存在,创建一个新的div<br />  <br />  if (!document.getElementById(divID))<br />  {<br />   var newNode = document.createElement("div");<br />   newNode.setAttribute("id", divID);<br />   document.body.appendChild(newNode);<br />  }</p>
		<p>  // globalDiv设置为div的引用  <br />  globalDiv = document.getElementById(divID);</p>
		<p>  // 计算div左上角的位置  <br />  var x = queryField.offsetLeft;<br />  var y = queryField.offsetTop + queryField.offsetHeight;<br />  var parent = queryField;<br />  while (parent.offsetParent)<br />  {<br />   parent = parent.offsetParent;<br />   x += parent.offsetLeft;<br />   y += parent.offsetTop;<br />  }</p>
		<p>  // 如果没有对div设置格式,则为其设置相应的显示样式  <br />  if (!divFormatted)<br />  {<br />   globalDiv.style.backgroundColor = DIV_BG_COLOR;<br />   globalDiv.style.fontFamily = DIV_FONT;<br />   globalDiv.style.padding = DIV_PADDING;<br />   globalDiv.style.border = DIV_BORDER;<br />   globalDiv.style.width = "100px";<br />   globalDiv.style.fontSize = "90%";</p>
		<p>   globalDiv.style.position = "absolute";<br />   globalDiv.style.left = x + "px";<br />   globalDiv.style.top = y + "px";<br />   globalDiv.style.visibility = "hidden";<br />   globalDiv.style.zIndex = 10000;</p>
		<p>   divFormatted = true;<br />  }<br /> }</p>
		<p> return globalDiv;<br />}</p>
		<p>/**<br />根据返回的结果集显示下拉区<br />*/<br />function showQueryDiv(resultArray)<br />{<br /> // 获取div的引用<br /> var div = getDiv(divName);<br /> <br /> // 如果div中有内容,则删除之<br /> while (div.childNodes.length &gt; 0)<br />  div.removeChild(div.childNodes[0]);</p>
		<p> // 依次添加结果<br /> for (var i = 0; i &lt; resultArray.length; i++)<br /> {<br />  // 每一个结果也是一个div<br />  var result = document.createElement("div");<br />  // 设置结果div的显示样式<br />  result.style.cursor = "pointer";<br />  result.style.padding = "2px 0px 2px 0px";<br />  // 设置为未选中<br />  _unhighlightResult(result);<br />  // 设置鼠标移进、移出等事件响应函数<br />  result.onmousedown = selectResult;<br />  result.onmouseover = highlightResult;<br />  result.onmouseout = unhighlightResult;</p>
		<p>  // 结果的文本是一个span<br />  var result1 = document.createElement("span");<br />  // 设置文本span的显示样式<br />  result1.className = "result1";<br />  result1.style.textAlign = "left";<br />  result1.style.fontWeight = "bold";<br />  result1.innerHTML = resultArray[i];<br />  <br />  // 将span添加为结果div的子节点<br />  result.appendChild(result1);<br />  <br />  // 将结果div添加为下拉区的子节点<br />  div.appendChild(result);<br /> }</p>
		<p> // 如果结果集不为空,则显示,否则不显示<br /> showDiv(resultArray.length &gt; 0);<br />}</p>
		<p>/**<br />用户点击某个结果时,将文本框的内容替换为结果的文本,<br />并隐藏下拉区<br />*/<br />function selectResult()<br />{<br /> _selectResult(this);<br />}</p>
		<p>// 选择一个条目<br />function _selectResult(item)<br />{<br /> var spans = item.getElementsByTagName("span");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   if (spans[i].className == "result1")<br />   {<br />    queryField.value = spans[i].innerHTML;<br />    lastVal = val = escape(queryField.value);<br />    mainLoop();<br />    queryField.focus();<br />    showDiv(false);<br />    return;<br />   }<br />  }<br /> }<br />}</p>
		<p>/**<br />当鼠标移到某个条目之上时,高亮显示该条目<br />*/<br />function highlightResult()<br />{<br /> _highlightResult(this);<br />}</p>
		<p>function _highlightResult(item)<br />{<br /> item.style.backgroundColor = DIV_HIGHLIGHT_COLOR;<br />}</p>
		<p>/**<br />当鼠标移出某个条目时,正常显示该条目<br />*/<br />function unhighlightResult()<br />{<br /> _unhighlightResult(this);<br />}</p>
		<p>function _unhighlightResult(item)<br />{<br /> item.style.backgroundColor = DIV_BG_COLOR;<br />}</p>
		<p>/**<br />显示/不显示下拉区<br />*/<br />function showDiv (show)<br />{<br /> var div = getDiv(divName);<br /> if (show)<br /> {<br />  div.style.visibility = "visible";<br /> }<br /> else<br /> {<br />  div.style.visibility = "hidden";<br /> }<br /> //adjustiFrame();<br />}</p>
		<p>/**<br />隐藏下拉区<br />*/<br />function hideDiv ()<br />{<br /> showDiv(false);<br />}</p>
		<p>/**<br />调整IFrame的位置,这是为了解决div可能会显示在输入框后面的问题<br />*/<br />function adjustiFrame()<br />{<br /> // 如果没有IFrame,则创建之<br /> if (!document.getElementById(ifName))<br /> {<br />  var newNode = document.createElement("iFrame");<br />  newNode.setAttribute("id", ifName);<br />  newNode.setAttribute("src", "javascript:false;");<br />  newNode.setAttribute("scrolling", "no");<br />  newNode.setAttribute("frameborder", "0");<br />  document.body.appendChild(newNode);<br /> }</p>
		<p> iFrameDiv = document.getElementById(ifName);<br /> var div = getDiv(divName);</p>
		<p> // 调整IFrame的位置与div重合,并在div的下一层  <br /> try<br /> {<br />  iFrameDiv.style.position = "absolute";<br />  iFrameDiv.style.width = div.offsetWidth;<br />  iFrameDiv.style.height = div.offsetHeight;<br />  iFrameDiv.style.top = div.style.top;<br />  iFrameDiv.style.left = div.style.left;<br />  iFrameDiv.style.zIndex = div.style.zIndex - 1;<br />  iFrameDiv.style.visibility = div.style.visibility;<br /> }<br /> catch (e)<br /> {<br /> }<br />}</p>
		<p>/**<br />文本输入框的onkeydown响应函数<br />*/<br />function keypressHandler (evt)<br />{<br /> // 获取对下拉区的引用  <br /> var div = getDiv(divName);<br /> <br /> // 如果下拉区不显示,则什么也不做  <br /> if (div.style.visibility == "hidden")<br /> {<br />  return true;<br /> }</p>
		<p> // 确保evt是一个有效的事件 <br /> if (!evt &amp;&amp; window.event)<br /> {<br />  evt = window.event;<br /> }<br /> var key = evt.keyCode;</p>
		<p> var KEYUP = 38;<br /> var KEYDOWN = 40;<br /> var KEYENTER = 13;<br /> var KEYTAB = 9;<br /> <br /> // 只处理上下键、回车键和Tab键的响应  <br /> if ((key != KEYUP) &amp;&amp; (key != KEYDOWN) &amp;&amp; (key != KEYENTER) &amp;&amp; (key != KEYTAB))<br /> {<br />  return true;<br /> }</p>
		<p> var selNum = getSelectedSpanNum(div);<br /> var selSpan = setSelectedSpan(div, selNum);<br /> <br /> // 如果键入回车和Tab,则选择当前选择条目 <br /> if ((key == KEYENTER) || (key == KEYTAB))<br /> {<br />  if (selSpan)<br />  {<br />   _selectResult(selSpan);<br />  }<br />  evt.cancelBubble = true;<br />  return false;<br /> }<br /> else //如果键入上下键,则上下移动选中条目<br /> {<br />  if (key == KEYUP)<br />  {<br />   selSpan = setSelectedSpan(div, selNum - 1);<br />  }<br />  if (key == KEYDOWN)<br />  {<br />   selSpan = setSelectedSpan(div, selNum + 1);<br />  }<br />  if (selSpan)<br />  {<br />   _highlightResult(selSpan);<br />  }<br /> }</p>
		<p> // 显示下拉区<br /> showDiv(true);<br /> return true;<br />}</p>
		<p>/**<br />获取当前选中的条目的序号<br />*/<br />function getSelectedSpanNum(div)<br />{<br /> var count = -1;<br /> var spans = div.getElementsByTagName("div");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   count++;<br />   if (spans[i].style.backgroundColor != div.style.backgroundColor)<br />   {<br />    return count;<br />   }<br />  }<br /> }</p>
		<p> return -1;<br />}</p>
		<p>/**<br />选择指定序号的结果条目<br />*/<br />function setSelectedSpan(div, spanNum)<br />{<br /> var count = -1;<br /> var thisSpan;<br /> var spans = div.getElementsByTagName("div");<br /> if (spans)<br /> {<br />  for (var i = 0; i &lt; spans.length; i++)<br />  {<br />   if (++count == spanNum)<br />   {<br />    _highlightResult(spans[i]);<br />    thisSpan = spans[i];<br />   }<br />   else<br />   {<br />    _unhighlightResult(spans[i]);<br />   }<br />  }<br /> }</p>
		<p> return thisSpan;<br />}<br /><br /><font color="#ff0000"><strong>Fourthly: Add httpHandlers request in web.config.<br /></strong></font>  &lt;httpHandlers&gt;<br />   &lt;add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro" /&gt;<br />  &lt;/httpHandlers&gt;<br /><br />Dont' forget download a AjaxPro.dll then add the dll to the project.<br /></p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/89823.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-12-25 09:46 <a href="http://www.blogjava.net/Daniel2005/articles/89823.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Easy SMTP Mail Using ASP.NET 2.0</title><link>http://www.blogjava.net/Daniel2005/articles/87128.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 12 Dec 2006 01:20:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/87128.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/87128.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/87128.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/87128.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/87128.html</trackback:ping><description><![CDATA[
		<p nd="1">The article addresses two topics: sending an email message to a standard email account, and sending an SMS message to a cell phone or pager. The approach uses the SMTP client contained in <code nd="2">System.Net</code> to accomplish both types of message submittal, and all messages are sent from ASP.NET 2.0 ASPX pages.</p>
		<p nd="3">The SMTP email portion application will demonstrate the following:</p>
		<ul>
				<li nd="4">Using SMTP to configure and send email messages 
</li>
				<li nd="5">Adding ‘CC’ addresses as message recipients 
</li>
				<li nd="6">Adding attachments to a message </li>
		</ul>
		<p nd="7">The SMS portion of the email application will demonstrate the following:</p>
		<ul>
				<li nd="8">Passing standard email messages through the carrier to deliver SMS messages to the target.</li>
		</ul>
		<p nd="9">In addition to discussing the small bit of code necessary to send these messages, the document will address the primary configuration requirements needed to successfully send messages through an ASP.NET 2.0 based website on an IIS <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/EasySMTP_package.asp#" target="_blank" itxtdid="2865581">server</a>.</p>
		<p nd="10">In order to use this demonstration, you should have an instance of IIS installed on your <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/EasySMTP_package.asp#" target="_blank" itxtdid="3151433">development</a> machine, you should have Visual Studio 2005 installed, and you should have the optional SMTP mail server installed in your local IIS instance.</p>
		<p>
				<img height="491" src="http://www.codeproject.com/aspnet/EasySMTP_package/screenshot.jpg" width="600" />
		</p>
		<p nd="11">
				<b>Figure 1</b>: The main page of the demonstration application</p>
		<h2>Getting Started</h2>
		<p nd="12">Unzip the attached file; in it, you will find a solution containing a web site project entitled, “RealMail”. Store the unzipped file onto your system, and create a virtual directory pointing to the web application from IIS. Then, open the solution in Visual Studio 2005. Looking at the Solution Explorer, you will see the files indicated in figure 2.</p>
		<p>
				<img height="389" src="http://www.codeproject.com/aspnet/EasySMTP_package/1.jpg" width="475" />
		</p>
		<p nd="13">
				<b>Figure 2</b>: RealMail web application in the Solution Explorer</p>
		<p nd="14">There are two ASPX pages in the solution, the first (<i>default.aspx</i>) is used to send a standard message to a recipient using the .NET 2.0 SMTP class library; the second page is used to send an SMS message to a cellular telephone or messaging pager through SMTP.</p>
		<h2>IIS Configuration</h2>
		<p nd="15">Your local IIS instance has to be properly configured in order to successfully send an email message through its SMTP <a class="iAs" style="FONT-WEIGHT: normal; FONT-SIZE: 100%; PADDING-BOTTOM: 1px; COLOR: darkgreen; BORDER-BOTTOM: darkgreen 0.07em solid; BACKGROUND-COLOR: transparent; TEXT-DECORATION: underline" href="http://www.codeproject.com/aspnet/EasySMTP_package.asp#" target="_blank" itxtdid="3059971">mail server</a>. Even if you install IIS, the SMTP mail server installation is optional, and must be explicitly added to the installation. If you are not sure whether or not the SMTP mail server is installed, open up the IIS control panel and check for the installation; if it is installed, you will see a reference to the Default SMTP Virtual Server in the tree view (Figure 3):</p>
		<p>
				<img height="480" src="http://www.codeproject.com/aspnet/EasySMTP_package/2.jpg" width="568" />
		</p>
		<p nd="16">
				<b>Figure 3</b>: Default SMTP Virtual Server installed</p>
		<p nd="17">If the server is not installed, you will need to use the “Add and Remove Windows Components” function in the “Add and Remove Programs” control panel to add the SMTP server to your IIS installation. If you need to do this additional installation, once you’ve opened “Add and Remove Windows Components”, click on “Internet Information Services (IIS)” to highlight it, and then click on the “Details” button (Figure 4). This will open an IIS dialog; examine this dialog to locate “SMTP Service”, and click on it to place a check mark on the box (Figure 5). Once this item has been checked, click on the “OK” button to install the SMTP server.</p>
		<p>
				<img height="419" src="http://www.codeproject.com/aspnet/EasySMTP_package/3.jpg" width="506" />
		</p>
		<p nd="18">
				<b>Figure 4</b>: Windows Components Wizard</p>
		<p>
				<img height="377" src="http://www.codeproject.com/aspnet/EasySMTP_package/4.jpg" width="451" />
		</p>
		<p nd="19">
				<b>Figure 5</b>: Adding the SMTP Service to IIS</p>
		<p nd="20">Once the default SMTP server has been installed or verified, you can now configure it to send email. In order to configure the SMTP server, open the IIS control panel, locate the default SMTP server icon in the tree view, and select and right click the icon. Once the context menu has been displayed, locate “Properties”, and click on it to open the Properties menu. Once the Default SMTP Virtual Server Properties dialog is displayed, click on the “Access” tab (Figure 6):</p>
		<p>
				<img height="486" src="http://www.codeproject.com/aspnet/EasySMTP_package/5.jpg" width="405" />
		</p>
		<p nd="21">
				<b>Figure 6</b>: SMTP Properties dialog</p>
		<p nd="22">Select the “Authentication” button to display the authentication options (Figure 7):</p>
		<p>
				<img height="418" src="http://www.codeproject.com/aspnet/EasySMTP_package/6.jpg" width="387" />
		</p>
		<p nd="23">
				<b>Figure 7</b>: Authentication options</p>
		<p nd="24">Make sure that the Anonymous access option is checked, and that all other options are unchecked; in some instances, you may wish to use the other options, but in most cases involving a public website, this is the option you’d want. Once you have verified this setting, click “OK” to close this dialog.</p>
		<p nd="25">Back to the “Access” tab, locate and click on the “Relay” button to display the relay options. Note that the radio button for “Only the list below” is selected, and that the local host IP address has been added to the list of computers permitted to relay through the SMTP server. Naturally, this is OK for a development machine, but in deployment, you would use the actual IP address of the web server. If no IP addresses are shown in the list, click on the “Add” button and add the IP address. Once finished, click on the “OK” button to accept the changes and to dismiss the dialog (Figure 8).</p>
		<p>
				<img height="410" src="http://www.codeproject.com/aspnet/EasySMTP_package/7.jpg" width="387" />
		</p>
		<p nd="26">
				<b>Figure 8</b>: Relay Restrictions dialog</p>
		<p nd="27">Next, select the “Delivery” tab from the SMTP Server Properties dialog (Figure 9):</p>
		<p>
				<img height="484" src="http://www.codeproject.com/aspnet/EasySMTP_package/8.jpg" width="404" />
		</p>
		<p nd="28">
				<b>Figure 9</b>: Delivery Options dialog</p>
		<p nd="29">From this dialog, select the “Advanced” button to reveal the advanced options dialog (Figure 10):</p>
		<p>
				<img height="410" src="http://www.codeproject.com/aspnet/EasySMTP_package/9.jpg" width="387" />
		</p>
		<p nd="30">
				<b>Figure 10</b>: Advanced Delivery dialog</p>
		<p nd="31">From this dialog, there are two points to make: first, the “Fully qualified domain name” property should be pre-populated, you may click on the “Check DNS” button to validate the setting. The next option is probably the most critical item for the whole shooting match; the Smart Host property has to be set to point to a valid SMTP mail server that will permit you to relay mail. For most cases, you will key in the name of your internet provider’s default SMTP mail server; the address is likely to be in the format of “mail.something.com” where “something” is the internet provider’s domain name. There are two easy ways to get this: one is, if you are using Outlook, open up Outlook and pull up the information on your email account; the mail server will be listed there. The second option is to guess, and you can qualify your guess by pinging the server.</p>
		<p nd="32">If your internet provider’s name is “foxtrox”, try pinging mail.foxtrot.com; if you get a response there, that is probably the one to use. If that does not work, contact your administrator and ask them for the information on the SMTP mail server; don’t try to plug in an Exchange server, there will likely be an SMTP mail server out there even if your company is using an Exchange server. The only other hurdle is to make sure that the SMTP mail server will allow you to relay, and again, you may need to talk to the administrator if the server bounces your mail. Once these settings are made, click on the “OK” button to save the settings and close the dialog.</p>
		<p nd="33">The last thing to do is to check the security tab to make sure the accounts are properly configured; once done, your security settings should look something like this (Figure 11):</p>
		<p>
				<img height="484" src="http://www.codeproject.com/aspnet/EasySMTP_package/10.jpg" width="404" />
		</p>
		<p nd="34">
				<b>Figure 11</b>: Security settings for the SMTP server</p>
		<p nd="35">Once everything is setup, click on the “OK” button to save the settings and to close the Default SMTP Virtual Server Properties dialog.</p>
		<h2>The Code: Sending an Email From an ASP.NET 2.0 Web Page</h2>
		<p nd="36">Open up the <i>default.aspx</i> code window from the included example project, and examine the code used to send an email.</p>
		<h3>Imports</h3>
		<p nd="37">Note that the project includes only three imports:</p>
		<pre lang="vbnet" nd="39">
				<span class="vb-keyword" nd="38">Imports</span> System
<span class="vb-keyword" nd="40">Imports</span> System.Net
<span class="vb-keyword" nd="41">Imports</span> System.Net.Mail</pre>
		<p nd="42">The application uses the <code nd="43">System.NET.Mail</code> libraries to format and send SMTP based email messages; these imports are required to run the project, and to send the email messages. This is also new to ASP.NET 2.0 and Visual Studio 2005.</p>
		<h3>Declarations</h3>
		<p nd="44">Within the declarations section at the beginning of the project, you will note a standard class declaration followed by a region called “Declarations”; within the <i>Declarations</i> region is a collection of variables used to contain information used in sending the mail:</p>
		<pre lang="vbnet" nd="45">Partial <span class="vb-keyword" nd="46">Class</span> _Default_
        <span class="vb-keyword" nd="47">Inherits</span> System.Web.UI.Page

#<span class="vb-keyword" nd="48">Region</span><span class="vb-string" nd="49">"Declarations"</span><span class="vb-comment" nd="50">' message elements</span><span class="vb-keyword" nd="51">Private</span> mMailServer <span class="vb-keyword" nd="52">As</span><span class="vb-keyword" nd="53">String</span><span class="vb-keyword" nd="54">Private</span> mTo <span class="vb-keyword" nd="55">As</span><span class="vb-keyword" nd="56">String</span><span class="vb-keyword" nd="57">Private</span> mFrom <span class="vb-keyword" nd="58">As</span><span class="vb-keyword" nd="59">String</span><span class="vb-keyword" nd="60">Private</span> mMsg <span class="vb-keyword" nd="61">As</span><span class="vb-keyword" nd="62">String</span><span class="vb-keyword" nd="63">Private</span> mSubject <span class="vb-keyword" nd="64">As</span><span class="vb-keyword" nd="65">String</span><span class="vb-keyword" nd="66">Private</span> mCC <span class="vb-keyword" nd="67">As</span><span class="vb-keyword" nd="68">String</span><span class="vb-keyword" nd="69">Private</span> mPort <span class="vb-keyword" nd="70">As</span><span class="vb-keyword" nd="71">Integer</span>

#<span class="vb-keyword" nd="72">End</span><span class="vb-keyword" nd="73">Region</span></pre>
		<h3>The Code</h3>
		<p nd="74">The first bit of code is a subroutine used to generate alerts; it has no bearing on the topic of sending messages, but I frequently use this code block whenever I want to generate an alert from a web page. The code is pretty simple. It merely places the JavaScript code necessary to define and display an alert box into the text field of a <code nd="75">Label</code> control, and then adds the control to the current page; since the <code nd="76">Label</code> will fire any JavaScript passed to it, as soon as the control is added to the page, the alert box will fire.</p>
		<pre lang="vbnet" nd="79">
				<span class="vb-keyword" nd="77">Private</span>
				<span class="vb-keyword" nd="78">Sub</span> MessageBox(<span class="vb-keyword" nd="80">ByVal</span> strMsg <span class="vb-keyword" nd="81">As</span><span class="vb-keyword" nd="82">String</span>)

    <span class="vb-comment" nd="83">' generate a popup message using javascript alert function</span><span class="vb-comment" nd="84">' dumped into a label with the string argument passed in</span><span class="vb-comment" nd="85">' to supply the alert box text</span><span class="vb-keyword" nd="86">Dim</span> lbl <span class="vb-keyword" nd="87">As</span><span class="vb-keyword" nd="88">New</span> Label
    lbl.Text = <span class="vb-string" nd="89">"&lt;script language='javascript'&gt;"</span> &amp; Environment.NewLine _
                &amp; <span class="vb-string" nd="90">"window.alert("</span> &amp; <span class="vb-string" nd="91">"'"</span> &amp; strMsg &amp; <span class="vb-string" nd="92">"'"</span> &amp; <span class="vb-string" nd="93">")&lt;/script&gt;"</span><span class="vb-comment" nd="94">' add the label to the page to display the alert</span>
    Page.Controls.Add(lbl)

<span class="vb-keyword" nd="95">End</span><span class="vb-keyword" nd="96">Sub</span></pre>
		<p nd="97">The only other bit of code in the application is the Send button’s <code nd="98">Click</code> event handler; this handler captures the user’s inputs from the page, uses those inputs to populate the message related variables, and then formats a message using the variable content. You may note that the server and port settings are extracted from the AppSettings contained in the <i>web.config</i> file.</p>
		<p nd="99">When examining the code, note how the file attachment and the CC list is handled by the code contained in the <code lang="vbnet" nd="101"><span class="vb-keyword" nd="100">Try</span>-<span class="vb-keyword" nd="102">Catch</span></code> block. If you wanted to add blind carbon copies (BCC recipients), you could add them in a manner similar to that applied to processing the standard CC list.</p>
		<p nd="103">Here is the entire block of code:</p>
		<div class="precollapse" id="premain3" style="WIDTH: 100%">
				<img id="preimg3" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="3" />
				<span id="precollapse3" style="MARGIN-BOTTOM: 0px; CURSOR: hand" nd="104" preid="3"> Collapse</span>
		</div>
		<pre lang="vbnet" id="pre3" style="MARGIN-TOP: 0px" nd="107">
				<span class="vb-keyword" nd="105">Protected</span>
				<span class="vb-keyword" nd="106">Sub</span> btnSend_Click(<span class="vb-keyword" nd="108">ByVal</span> sender <span class="vb-keyword" nd="109">As</span><span class="vb-keyword" nd="110">Object</span>, _
          <span class="vb-keyword" nd="111">ByVal</span> e <span class="vb-keyword" nd="112">As</span> System.EventArgs) <span class="vb-keyword" nd="113">Handles</span> btnSend.Click

    <span class="vb-comment" nd="114">'send message</span><span class="vb-keyword" nd="115">Dim</span> strMsg <span class="vb-keyword" nd="116">As</span><span class="vb-keyword" nd="117">String</span>
    strMsg = txtMessage.Text

    mTo = Trim(txtTo.Text)
    mFrom = Trim(txtFrom.Text)
    mSubject = Trim(txtSubject.Text)
    mMsg = Trim(txtMessage.Text)
    mMailServer = ConfigurationManager.AppSettings.<span class="vb-keyword" nd="118">Get</span>(<span class="vb-string" nd="119">"MyMailServer"</span>)
    mPort = ConfigurationManager.AppSettings.<span class="vb-keyword" nd="120">Get</span>(<span class="vb-string" nd="121">"MyMailServerPort"</span>)
    mCC = Trim(txtCC.Text)

    <span class="vb-keyword" nd="122">Try</span><span class="vb-keyword" nd="123">Dim</span> message <span class="vb-keyword" nd="124">As</span><span class="vb-keyword" nd="125">New</span> MailMessage(mFrom, mTo, mSubject, mMsg)

        <span class="vb-keyword" nd="126">If</span> fileAttachments.HasFile <span class="vb-keyword" nd="127">Then</span><span class="vb-keyword" nd="128">Dim</span> attached <span class="vb-keyword" nd="129">As</span><span class="vb-keyword" nd="130">New</span> 
            Attachment(Trim(fileAttachments.PostedFile.FileName.ToString()))
            message.Attachments.Add(attached)
        <span class="vb-keyword" nd="131">End</span><span class="vb-keyword" nd="132">If</span><span class="vb-keyword" nd="133">If</span> mCC &lt;&gt; <span class="vb-string" nd="134">""</span><span class="vb-keyword" nd="135">Or</span> mCC &lt;&gt; <span class="vb-keyword" nd="136">String</span>.Empty <span class="vb-keyword" nd="137">Then</span><span class="vb-keyword" nd="138">Dim</span> strCC() <span class="vb-keyword" nd="139">As</span><span class="vb-keyword" nd="140">String</span> = Split(mCC, <span class="vb-string" nd="141">";"</span>)
            <span class="vb-keyword" nd="142">Dim</span> strThisCC <span class="vb-keyword" nd="143">As</span><span class="vb-keyword" nd="144">String</span><span class="vb-keyword" nd="145">For</span><span class="vb-keyword" nd="146">Each</span> strThisCC <span class="vb-keyword" nd="147">In</span> strCC
                message.CC.Add(Trim(strThisCC))
            <span class="vb-keyword" nd="148">Next</span><span class="vb-keyword" nd="149">End</span><span class="vb-keyword" nd="150">If</span><span class="vb-keyword" nd="151">Dim</span> mySmtpClient <span class="vb-keyword" nd="152">As</span><span class="vb-keyword" nd="153">New</span> SmtpClient(mMailServer, mPort)
        mySmtpClient.UseDefaultCredentials = <span class="vb-keyword" nd="154">True</span>
        mySmtpClient.Send(message)

        MessageBox(<span class="vb-string" nd="155">"The mail message has been sent to "</span> &amp; message.<span class="vb-keyword" nd="156">To</span>.ToString())

    <span class="vb-keyword" nd="157">Catch</span> ex <span class="vb-keyword" nd="158">As</span> FormatException

        MessageBox(<span class="vb-string" nd="159">"Format Exception: "</span> &amp; ex.Message)

    <span class="vb-keyword" nd="160">Catch</span> ex <span class="vb-keyword" nd="161">As</span> SmtpException

        MessageBox(<span class="vb-string" nd="162">"SMTP Exception:  "</span> &amp; ex.Message)

    <span class="vb-keyword" nd="163">Catch</span> ex <span class="vb-keyword" nd="164">As</span> Exception

        MessageBox(<span class="vb-string" nd="165">"General Exception:  "</span> &amp; ex.Message)

    <span class="vb-keyword" nd="166">End</span><span class="vb-keyword" nd="167">Try</span><span class="vb-keyword" nd="168">End</span><span class="vb-keyword" nd="169">Sub</span></pre>
		<p nd="170">Within the <code lang="vbnet" nd="172"><span class="vb-keyword" nd="171">Try</span>-<span class="vb-keyword" nd="173">Catch</span></code> block, note that format, SMTP, and general exceptions are trapped, and displayed to the user using the <code nd="174">MessageBox</code> subroutine at the beginning of the code block.</p>
		<h2>The Code: Sending an SMS Message Through ASP.NET 2.0</h2>
		<p nd="175">Open up the <i>sendSmsMsg.aspx</i> code window from the included example project, and examine the code used to send an SMS message as email.</p>
		<h3>Imports</h3>
		<p nd="176">Note that the project includes only three imports:</p>
		<pre lang="vbnet" nd="178">
				<span class="vb-keyword" nd="177">Imports</span> System
<span class="vb-keyword" nd="179">Imports</span> System.Net
<span class="vb-keyword" nd="180">Imports</span> System.Net.Mail</pre>
		<p>The application uses the <code>System.NET.Mail</code> libraries to format and send SMTP based email messages; these imports are required to run the project and to send the email based SMS messages.</p>
		<h3>Declarations</h3>
		<p>Within the declaration section at the beginning of the project, you will note a standard class declaration followed by a region called “Declarations”; within the <i>Declarations</i> region, is a collection of variables used to contain information used in sending the email based SMS messages:</p>
		<pre lang="vbnet">Partial <span class="vb-keyword">Class</span> sendSmsMsg _
        <span class="vb-keyword">Inherits</span> System.Web.UI.Page

#<span class="vb-keyword">Region</span><span class="vb-string">"Declarations"</span><span class="vb-comment">' message elements</span><span class="vb-keyword">Private</span> mMailServer <span class="vb-keyword">As</span><span class="vb-keyword">String</span><span class="vb-keyword">Private</span> mTo <span class="vb-keyword">As</span><span class="vb-keyword">String</span><span class="vb-keyword">Private</span> mFrom <span class="vb-keyword">As</span><span class="vb-keyword">String</span><span class="vb-keyword">Private</span> mMsg <span class="vb-keyword">As</span><span class="vb-keyword">String</span><span class="vb-keyword">Private</span> mSubject <span class="vb-keyword">As</span><span class="vb-keyword">String</span><span class="vb-keyword">Private</span> mPort <span class="vb-keyword">As</span><span class="vb-keyword">Integer</span>

#<span class="vb-keyword">End</span><span class="vb-keyword">Region</span></pre>
		<h3>The Code</h3>
		<p>So far, you may have noticed that everything is the same up to this point; from this point on, things will continue to be similar, but there are a few interface and variable differences that make it possible to send SMS messages via the SMTP server.</p>
		<p>The most interesting thing to note with regards to sending an SMS message is that you don’t have to do anything special. The carriers expose an interface through which you can send an email message (with some restrictions) to the cell phone subscriber, and the carrier will transmit that message as SMS to the subscriber.</p>
		<p>In general, the important things to know are that the address of the subscriber is their ten digit cell number (area code and number) coupled with the carrier's specified address. This application includes a list of most of the US carriers and some off shore carriers as well. If you are located outside of the US, you may need to do a little research to find the proper address for your targeted carriers, and I should point out that some carriers do not support this interface.</p>
		<p>In the page load event handler, I have populated a drop down list with the list of carriers:</p>
		<div class="precollapse" id="premain6" style="WIDTH: 100%">
				<img id="preimg6" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="6" />
				<span id="precollapse6" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="6"> Collapse</span>
		</div>
		<pre lang="vbnet" id="pre6" style="MARGIN-TOP: 0px">
				<span class="vb-keyword">Protected</span>
				<span class="vb-keyword">Sub</span> Page_Load(<span class="vb-keyword">ByVal</span> sender <span class="vb-keyword">As</span><span class="vb-keyword">Object</span>, _
          <span class="vb-keyword">ByVal</span> e <span class="vb-keyword">As</span> System.EventArgs) <span class="vb-keyword">Handles</span><span class="vb-keyword">Me</span>.Load

    <span class="vb-comment">' Load the names of the common carriers </span>
    cboCarrier.Items.Add(<span class="vb-string">"@itelemigcelular.com.br"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@message.alltel.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@message.pioneerenidcellular.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@messaging.cellone-sf.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@messaging.centurytel.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@messaging.sprintpcs.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mobile.att.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mobile.cell1se.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mobile.celloneusa.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mobile.dobson.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mobile.mycingular.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mobile.mycingular.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mobile.surewest.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@msg.acsalaska.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@msg.clearnet.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@msg.mactel.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@msg.myvzw.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@msg.telus.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mycellular.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mycingular.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mycingular.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@mycingular.textmsg.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@o2.net.br"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@ondefor.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@pcs.rogers.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@personal-net.com.ar"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@personal.net.py"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@portafree.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@qwest.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@qwestmp.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@sbcemail.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@sms.bluecell.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@sms.cwjamaica.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@sms.edgewireless.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@sms.hickorytech.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@sms.net.nz"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@sms.pscel.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@smsc.vzpacifica.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@speedmemo.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@suncom1.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@sungram.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@telesurf.com.py"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@teletexto.rcp.net.pe"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@text.houstoncellular.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@text.telus.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@timnet.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@timnet.com.br"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@tms.suncom.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@tmomail.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@tsttmobile.co.tt"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@txt.bellmobility.ca"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@typetalk.ruralcellular.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@unistar.unifon.com.ar"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@uscc.textmsg.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@voicestream.net"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@vtext.com"</span>)
    cboCarrier.Items.Add(<span class="vb-string">"@wireless.bellsouth.com"</span>)

<span class="vb-keyword">End</span><span class="vb-keyword">Sub</span></pre>
		<p>When using the application, you will see this list of carriers in the area used to define the recipient’s address (see Figure 12):</p>
		<p>
				<img height="452" src="http://www.codeproject.com/aspnet/EasySMTP_package/11.jpg" width="600" />
		</p>
		<p>
				<b>Figure 12</b>: List of carriers used to address SMS recipients</p>
		<p>The message contains the ‘To’ address, a ‘From’ address, a subject line, and the message body itself (which is limited to 140 characters in length).</p>
		<p>Clicking the Send button will start the ball rolling by executing the following <code>Click</code> event handler:</p>
		<div class="precollapse" id="premain7" style="WIDTH: 100%">
				<img id="preimg7" style="CURSOR: hand" height="9" src="http://www.codeproject.com/images/minus.gif" width="9" preid="7" />
				<span id="precollapse7" style="MARGIN-BOTTOM: 0px; CURSOR: hand" preid="7"> Collapse</span>
		</div>
		<pre lang="vbnet" id="pre7" style="MARGIN-TOP: 0px">
				<span class="vb-keyword">Protected</span>
				<span class="vb-keyword">Sub</span> Button2_Click(<span class="vb-keyword">ByVal</span> sender <span class="vb-keyword">As</span><span class="vb-keyword">Object</span>, _
          <span class="vb-keyword">ByVal</span> e <span class="vb-keyword">As</span> System.EventArgs) <span class="vb-keyword">Handles</span> Button2.Click

    <span class="vb-comment">'send message</span><span class="vb-keyword">Dim</span> strMsg <span class="vb-keyword">As</span><span class="vb-keyword">String</span>
    strMsg = txtMessage.Text

    <span class="vb-keyword">If</span> strMsg.Length &gt;= <span class="vb-literal">140</span><span class="vb-keyword">Then</span>
        strMsg = strMsg.Substring(<span class="vb-literal">1</span>, <span class="vb-literal">140</span>)
    <span class="vb-keyword">End</span><span class="vb-keyword">If</span>

    mTo = Trim(txtToNumber.Text) &amp; _
          Trim(cboCarrier.SelectedItem.ToString())
    mFrom = Trim(txtFrom.Text)
    mSubject = Trim(txtSubject.Text)
    mMsg = Trim(txtMessage.Text)
    mMailServer = ConfigurationManager.AppSettings.<span class="vb-keyword">Get</span>(<span class="vb-string">"MyMailServer"</span>)
    mPort = ConfigurationManager.AppSettings.<span class="vb-keyword">Get</span>(<span class="vb-string">"MyMailServerPort"</span>)

    <span class="vb-keyword">Try</span><span class="vb-keyword">Dim</span> message <span class="vb-keyword">As</span><span class="vb-keyword">New</span> MailMessage(mFrom, mTo, mSubject, mmsg)
        <span class="vb-keyword">Dim</span> mySmtpClient <span class="vb-keyword">As</span><span class="vb-keyword">New</span> SmtpClient(mMailServer, mPort)
        mySmtpClient.UseDefaultCredentials = <span class="vb-keyword">True</span>
        mySmtpClient.Send(message)

        MessageBox(<span class="vb-string">"The mail message has been sent to "</span> &amp; _
                    message.<span class="vb-keyword">To</span>.ToString())

    <span class="vb-keyword">Catch</span> ex <span class="vb-keyword">As</span> FormatException

        MessageBox(<span class="vb-string">"Format Exception: "</span> &amp; ex.Message)

    <span class="vb-keyword">Catch</span> ex <span class="vb-keyword">As</span> SmtpException

        MessageBox(<span class="vb-string">"SMTP Exception:  "</span> &amp; ex.Message)

    <span class="vb-keyword">Catch</span> ex <span class="vb-keyword">As</span> Exception

        MessageBox(<span class="vb-string">"General Exception:  "</span> &amp; ex.Message)

    <span class="vb-keyword">End</span><span class="vb-keyword">Try</span><span class="vb-keyword">End</span><span class="vb-keyword">Sub</span></pre>
		<p>As you will quickly see, the code is the same with a couple of minor exceptions; one pertains to validating the size of the message to be less than 140 characters, and the other major exception is in how the address of the recipient is constructed.</p>
		<p>Of course, it should go without saying that the recipient of the message is charged a fee for the transactions, and as tempting as it might be to set this up to loop a couple of thousand times and send “Happy Birthday” greetings to your ex-wife’s divorce attorney, don’t do it.</p>
		<p>The rest of the code in this page is identical to the default page described earlier; that includes the code to generate the alerts; there is also a hyperlink on both pages that allows you to traverse back and forth between the pages.</p>
		<h2>Summary</h2>
		<p>The article and sample project were intended to demonstrate the approach used to send email messages using SMTP through .NET; the examples also attempted to describe the ease with which this approach could be used to send SMS messages to cell phone subscribers using the same techniques applied to sending standard email messages.</p>
		<!-- Article Ends -->
		<script src="/script/togglePre.js" type="text/javascript">
		</script>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/87128.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-12-12 09:20 <a href="http://www.blogjava.net/Daniel2005/articles/87128.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>machineKey元素</title><link>http://www.blogjava.net/Daniel2005/articles/80402.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Fri, 10 Nov 2006 06:58:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/80402.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/80402.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/80402.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/80402.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/80402.html</trackback:ping><description><![CDATA[
		<h1>&lt;machineKey&gt; 元素</h1>
		<p>配置用于加密和解密 Forms 身份验证 Cookie 数据和视图状态数据的密钥，以及配置用于验证进程外会话状态标识的密钥。此节可以在计算机、站点或应用程序级别进行声明，但不能在子目录级别声明。</p>
		<p>
				<b>配置结构的示例：</b>
		</p>
		<p>
				<a href="http://www.haokucn.com/article/Tushu_html/JISHULEI/iismmc/htm/aaconconfigurationelement.htm">&lt;configuration&gt;</a>
				<br />   <a href="http://www.haokucn.com/article/Tushu_html/JISHULEI/iismmc/htm/aaconsystemwebelement.htm">&lt;system.web&gt;</a><br />      <b>&lt;machineKey&gt;</b></p>
		<pre>
				<code>
						<b>
								<i>&lt;</i>machineKey<i></i>validationKey</b>
						<i>="AutoGenerate|value[,IsolateApps]"</i>
						<b>            decryptionKey<i>=</i></b>
						<i>"AutoGenerate|value[,IsolateApps]</i>
						<b>            validation</b>
						<i>="SHA1|MD5|3DES</i>"<b>/&gt;</b></code>
		</pre>
		<h4>必需的属性</h4>
		<table width="100%">
				<tbody>
						<tr>
								<th>属性</th>
								<th>选项</th>
								<th>描述</th>
						</tr>
						<tr>
								<td>validationKey</td>
								<td>   </td>
								<td>指定用于验证加密数据的密钥。当 <a href="http://www.haokucn.com/article/Tushu_html/JISHULEI/iismmc/htm/aaconpageselement.htm">enableViewStateMAC</a> 为 <noloc><b>true</b></noloc> 时，可以使用 <b>validationKey</b> 创建一个消息验证代码 (MAC) 以确保视图状态不被篡改。<b>validationKey</b> 还用于生成进程外、应用程序特有的会话 ID 以确保在会话之间隔离会话状态变量。</td>
						</tr>
						<tr>
								<td>   </td>
								<td>AutoGenerate</td>
								<td>指定 ASP.NET 生成一个随机的密钥并将其存储在本地安全机构 (LSA) 中。<b>AutoGenerate</b> 选项是默认值。如果将 <b>IsolateApps</b> 修饰符添加到 <b>validationKey</b> 值中，ASP.NET 会使用每个应用程序的应用程序 ID 为每个应用程序生成一个唯一的加密密钥。</td>
						</tr>
						<tr>
								<td>   </td>
								<td>value</td>
								<td>指定一个手动分配的验证密钥。必须手动设置该值以确保整个 Web 服务器网络（Web 场）具有一致的配置。此密钥长度最少为 40 个字符（20 个字节），最多为 128 个字符（64 个字节）。如果使用的密钥比最大长度短，则采用真正随机的方法来创建这些密钥，例如使用 <b>RNGCryptoServiceProvider</b>。建议的密钥长度为 128 个十六进制字符。如果将 <b>IsolateApps</b> 修饰符添加到 <b>validationKey</b> 值中，ASP.NET 会使用每个应用程序的应用程序 ID 为每个应用程序生成一个唯一的加密密钥。</td>
						</tr>
						<tr>
								<td>decryptionKey</td>
								<td>   </td>
								<td>指定用于加密数据的密钥。<b>decryptionKey</b> 用于 Forms 身份验证加密和解密；当 <b>validation</b> 为 3DES 时，它还用于视图状态加密。</td>
						</tr>
						<tr>
								<td>   </td>
								<td>AutoGenerate</td>
								<td>指定 ASP.NET 生成一个随机的密钥并将其存储在 LSA 中。<b>AutoGenerate</b> 选项是默认值。如果将 <b>IsolateApps</b> 修饰符添加到 <b>decryptionKey</b> 值中，ASP.NET 会使用每个应用程序的应用程序 ID 为每个应用程序生成一个唯一的加密密钥。</td>
						</tr>
						<tr>
								<td>   </td>
								<td>value</td>
								<td>指定一个手动分配的密钥。必须手动将该值设置为十六进制字符串，以确保整个 Web 场具有一致的配置。在使用 DES 加密时，此密钥长度应该为 16 个字符；在使用三重 DES 加密时，此密钥长度应该为 48 个字符。如果使用的密钥比最大长度短，则应该采用真正随机的方法来创建这些密钥。ASP.NET 只能在可使用 128 位加密的计算机上使用三重 DES。如果将 <b>IsolateApps</b> 修饰符添加到 <b>decryptionKey</b> 值中，ASP.NET 会使用每个应用程序的应用程序 ID 为每个应用程序生成一个唯一的加密密钥。</td>
						</tr>
						<tr>
								<td>validation</td>
								<td>   </td>
								<td>指定用于数据验证的加密类型。</td>
						</tr>
						<tr>
								<td>   </td>
								<td>SHA1</td>
								<td>指定 ASP.NET 使用 <b>SHA1</b> 加密。</td>
						</tr>
						<tr>
								<td>   </td>
								<td>MD5</td>
								<td>指定 ASP.NET 使用 <b>MD5</b> 加密。</td>
						</tr>
						<tr>
								<td>   </td>
								<td>3DES</td>
								<td>指定 ASP.NET 使用三重 DES (3DES) 加密。在指定 <b>3DES</b> 时，Forms 身份验证默认为 <b>SHA1</b>。在将 <b>validation</b> 属性设置为 <b>3DES</b> 时，视图状态验证技术使用 <b>3DES</b> 加密。</td>
						</tr>
				</tbody>
		</table>
		<h4>示例</h4>
		<p>以下示例将 <b>validationKey</b> 和 <b>decryptionKey</b> 均设置为 <b>AutoGenerate</b>。指定 <b>isolateApps</b> 选项以便给服务器上的每个应用程序生成唯一的密钥。</p>
		<pre>
				<code>&lt;machineKey validationKey="AutoGenerate,IsolateApps" 
            decryptionKey="AutoGenerate,IsolateApps" 
            validation="SHA1"/&gt;</code>
		</pre>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/80402.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-11-10 14:58 <a href="http://www.blogjava.net/Daniel2005/articles/80402.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UPdate DataGrid</title><link>http://www.blogjava.net/Daniel2005/articles/57610.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 11 Jul 2006 02:34:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/57610.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/57610.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/57610.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/57610.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/57610.html</trackback:ping><description><![CDATA[
		<p>Private Sub btnUpdate_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles btnUpdate.Click<br />        Dim admin As New admin<br />        Dim i As Integer<br />        Dim item As DataGridItem<br />        Dim arrID(), arrIsMoney(), arrFlag(), arrAmount() As String</p>
		<p>        ReDim arrID(Me.dgdPurpose.Items.Count - 1)<br />        ReDim arrIsMoney(Me.dgdPurpose.Items.Count - 1)<br />        ReDim arrFlag(Me.dgdPurpose.Items.Count - 1)<br />        ReDim arrAmount(Me.dgdPurpose.Items.Count - 1)</p>
		<p>        For i = 0 To Me.dgdPurpose.Items.Count - 1<br />            item = Me.dgdPurpose.Items(i)</p>
		<p>            arrID(i) = Convert.ToString(item.Cells(0).Text).Trim<br />            arrIsMoney(i) = Convert.ToString(item.Cells(1).Text).Trim<br />            arrFlag(i) = CType(item.FindControl("rbtnAct"), System.Web.UI.WebControls.RadioButtonList).SelectedValue<br />            If arrIsMoney(i).CompareTo("Y") = 0 Then<br />                arrAmount(i) = CType(item.FindControl("txtMin"), System.Web.UI.WebControls.TextBox).Text<br />            Else<br />                arrAmount(i) = "0"<br />            End If</p>
		<p>        Next</p>
		<p>        '--04/06/05 For Late Billed Rides (Tom)<br />        ReDim Preserve arrID(Me.dgdPurpose.Items.Count)<br />        ReDim Preserve arrIsMoney(Me.dgdPurpose.Items.Count)<br />        ReDim Preserve arrFlag(Me.dgdPurpose.Items.Count)<br />        ReDim Preserve arrAmount(Me.dgdPurpose.Items.Count)</p>
		<p>        arrID(arrID.Length - 1) = "11"<br />        arrIsMoney(arrID.Length - 1) = "Y"<br />        arrAmount(arrID.Length - 1) = Me.txtDays.Text.Trim<br />        If Me.rdOn.Checked Then<br />            arrFlag(arrID.Length - 1) = "Y"<br />        Else<br />            arrFlag(arrID.Length - 1) = "N"<br />        End If</p>
		<p>
				<br />        If admin.exceptionrules_activeall(arrID, arrIsMoney, arrFlag, arrAmount, Convert.ToString(Session("user_id")).Trim) = False Then<br />            Response.Write("&lt;script language='javascript'&gt;alert('Failed to update.');&lt;/script&gt;")<br />        Else<br />            Response.Write("&lt;script language='javascript'&gt;alert('Updated successfully!');&lt;/script&gt;")<br />        End If<br />        'admin.Dispose()<br />        admin = Nothing<br />        dataLoad()<br />    End Sub</p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/57610.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-07-11 10:34 <a href="http://www.blogjava.net/Daniel2005/articles/57610.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>IIS+Asp.net2.0</title><link>http://www.blogjava.net/Daniel2005/articles/56468.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 04 Jul 2006 01:47:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/56468.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/56468.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/56468.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/56468.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/56468.html</trackback:ping><description><![CDATA[
		<strong>1、IIS快速浏览</strong>
		<p>   IIS支持在一台服务器上并存多“站点（Sites）”主机。这些站点由IP地址、主机名称、和/或端口号组成。例如假设我的站点是<a href="http://www.aspcool.com/">http://www.aspcool.com</a>，它的IP地址为192.197.157.24，主机名称是<a href="http://www.aspcool.com/">www.aspcool.com</a>，端口号是80（默认的HTTP端口）。  而Nikhil的站点是<a href="http://www.nikhilk.net/">http://www.nikhilk.net</a>，它的服务器和我的在同一台Web服务器上，所以和我一样，它拥有192.197.157.24 IP地址和默认的80端口，但是唯一不同就是绑定的主机名称不同。只要这三个之中（IP地址、主机名和端口号）有一个不同，就可以区分每一个站点，进而就可以单独映射到IIS Web服务器<br />   <br />   当一个站点经过注册和IIS关联后，你需要建立该站点的主目录，该主目录指出了将来您上传的页面文件的存放地址。当安装IIS时，默认的站点路径主目录映射的是c:\inetpub\wwwroot这个目录，如果你直接放置一个文件，例如test.html在该目录下，你就可以使用<a href="http://localhost/test.html">http://localhost/test.html</a>来从该web服务器上检索该页面信息。<br />    <br />  另外，在该目录下，你可以建立任意多的物理路径和子文件夹，IIS对此都进行了很好的支持。</p>
		<p>    IIS同样此持<strong>虚拟路径</strong>（virtual directories，简称vdirs）这一概念，顾名思义，虚拟路径并不是真实的路径，它可以把URL映射成逻辑路径，进而映射到物理离境，这样可以很好的保护文件。</p>
		<p>     例如，我建立了一个名称为app1 的虚拟路径，并且映射到 c:\inetpub\app1，然后在app1目录下建立了一个名称为test2.htm的文，并结合IIS默认的设置，那么具体用户请求映射如下：<br /><a href="http://localhost/test.html">http://localhost/test.html</a>－－－－&gt; c:\inetpub\wwwroot\test.html<br /><a href="http://mqingqing123.cnblogs.com/admin/sohu">http://localhost/app1/test2.htm</a>----&gt;c:\inetpub\app1\test2.htm</p>
		<p>    注意：上面的wwwroot和app1是平等的，或者说它们在同一文件夹下，所以虽然从URL逻辑上看似乎app1应该在wwwroot目录下，但是其实您并不能够确保实际存放是这样的。</p>
		<p>     IIS同样支持应用程序（Application）这一概念，这一概念和虚拟路径类似，它们在IIS6版本里还支持管理员来管理堆不同应用程序池的映射。(注意：ASP.NET的应用程序这一概念已经和传统的ASP应用程序的概念不同，它是应用程序的入口)</p>
		<p>   IIS的Application同样可以映射到主目录下的物理路径，它还可以映射到主目录以外的其他路径。它们能够支持多层次的深度嵌套</p>
		<p>例如<br /><a href="http://www.testsite.com/">http://www.testsite.com/</a> -&gt; c:\www.testsite.com\wwwroot (应用程序的主目录)</p>
		<p>
				<a href="http://www.testsite.com/app1">http://www.testsite.com/app1</a> -&gt; c:\www.testsite.com\app1 </p>
		<p>
				<a href="http://www.testsite.com/app2">http://www.testsite.com/app2</a> -&gt; c:\www.testsite.com\app2</p>
		<p>
				<a href="http://www.testsite.com/app3">http://www.testsite.com/app3</a> -&gt; c:\www.testsite.com\wwwroot\app3</p>
		<p>
				<a href="http://www.testsite.com/app3/app4">http://www.testsite.com/app3/app4</a> -&gt; c:\www.testsite.com\wwwroot\app3\app4</p>
		<p>注意上面例子里Application的主目录(<a href="http://www.testsite.com/">http://www.testsite.com/</a>) ，app1(<a href="http://www.testsite.com/app1">http://www.testsite.com/app1</a>)以及app2 (<a href="http://www.testsite.com/app2">http://www.testsite.com/app2</a>) ，从URL路径上看似乎app1和app2是在主目录下进行继承，但是其实在物理路径上是平等的。</p>
		<p>   这里特别强调一下，当你在IIS里在右击鼠标选择“建立虚拟路径”时，你其实同时也建立了一个应用程序（Application），（特别的，此时虚拟路径已经自动设置了一些应用程序元数据）<br /></p>
		<p>   如果你不想要这些应用程序元素，你可以打开刚建立的虚拟目录的属性页，最主要的记住：IIS实现对虚拟路径的绑定，而不是对物理路径的绑定，这一点决定了应用程序的范围和边界。</p>
		<p>   上面的映射，如果你打开IIS应该类似如下你可以单击删除，这并不会删除虚拟路径，但它会删除应用程序，一般并不建议这么做。<br /><img height="337" hspace="5" src="http://mqingqing123.cnblogs.com/images/cnblogs_com/mqingqing123/image001.jpg" width="549" align="baseline" /><br /><br /><br /><strong>ASP.NET 2.0和应用程序</strong></p>
		<p>  ASP.NET使用IIS应用程序元数据标示（这些标识存放在IIS元数据配置系统里）来区分每一个应用程序的应用区域，并且关联到具体主机内容，特别的，一个目录被映射成ASP.NET虚拟路径后会做如下一些事情：<br />（1）它允许在当前应用程序的主目录下建立一个 \bin 文件夹以此来解决汇编程序集合的引用，并可以立即使用它。<br />（2）它允许应用程序集等级（application-level）可以设置身份验证（具体在web.config里配置）。<br />（3）它允许全局设置（global.asax）文件定义处理全局等级事件（例如Application_Start/End，以及具体的模块事件如Session_Start/End）<br />（4）上面这些都在ASP.NET 2.0版本进行了支持，除此以外在ASP.NET2.0版本里，为了部署应用程序的方便和资源共享，它还提供了额外的目录，你可以在应用程序主目录下建立这些额外的目录，这写额外的目录包括<strong>App_Data、App_Code</strong>等以便提供数据访问、类库的编译和应用程序资源等。<br /><br /><span style="COLOR: #333399">何谓IIS的元数据标识？对于熟悉Windows的用户来说，应该知道windows系统的配置在注册表里，同样IIS也采用了配置文件的思想其配置信息放置在meta数据库里，这就是我们通常称为的元数据库</span></p>
		<p>ASP.NET会建立一个CLR的应用程序区域来处理正在允许应用程序代码的上下文环境。这个应用程序区域时在代码加载策略的设置里（也就是解决应用程序汇编集怎么挂接到 \bin 目录下），以前额外的代码访问权限问题。<br />使用上面的 <a href="http://www.testsite.com/">www.testsite.com</a>应用程序绑定的例子，这意味这\bin文件夹的位置应该类似如下： c:\www.testsite.com\wwwroot\bin <br />c:\www.testsite.com\app1\bin <br />c:\www.testsite.com\app2\bin <br />c:\www.testsite.com\wwwroot\app3\bin <br />c:\www.testsite.com\wwwroot\app3\app4\bin<br /><br /><br /> \app1运行时的代码会使用\app1\bin文件夹的汇编集。<br />\wwwroot\app3 运行时的代码会使用\wwwroot\app3 \bin 文件下的汇编集<br />\wwwroot文件夹下的运行时代码（注意不是\wwwroot\app3目录下）将使用\wwwroot\bin文件夹下的代码来加载汇编集<br />注意：这些汇编集是由.NET框架ASP.NET V1,V1.1和V2.0进行区分的<br /><br /><br /><strong>使用Visual Studio.NET 2005</strong></p>
		<p>
				<span style="COLOR: #ff0000"> 重要说明：在下面的介绍了，我们使用了Visual Web Express2005来开发ASP.NET2.0。VWE2005是Visual Stduio.NET2005的一部分，虽然VS.NET2005功能很强大，但是根据应用情况（例如有些人用C#版，就不用安装VB版本）有许多功能其实并不需要，所以这里说的VS2005其实是VWE2005，您可以到  <a href="http://www.asp.net/">http://www.asp.net</a>  免费下载</span>
				<br />    VS2005支持多种方式来打开和编辑ASP.NET应用程序。总体概括起来有四种方式：File System、Local IIS、FTP Site和Remote Site。如下图<br /><img height="337" hspace="5" src="http://mqingqing123.cnblogs.com/images/cnblogs_com/mqingqing123/image003.jpg" width="522" align="baseline" /></p>
		<p>
				<br />本节主要介绍Local IIS，其它方式以后会介绍。</p>
		<p> </p>
		<p>有些人可能会问如果如果使用Local IIS，你打开一个web站点时，该站点有多个嵌套的子应用程序怎么办？例如当你打开<a href="http://www.testsite.com/">www.testsite.com</a>(应用程序根目录)，而根目录下包含多个子应用程序（(<a href="http://www.testsite.com/app1">www.testsite.com/app1</a>, <a href="http://www.testsite.com/app2">www.testsite.com/app2</a>, 和 <a href="http://www.testsite.com/app3">www.testsite.com/app3</a>），一个广为关注的问题就是VS2005会不会将所有的子目录整合在一起，因为绑定的应用程序和项目会编译在\bin目录下（而事实上\bin目录和这四个应用程序应该不同）。</p>
		<p>一个非常好的消息是VS2005能够正确的获取每一个应用程序界定范围，也就是说当你打开一<a href="http://www.testsite.com/">www.testsite.com</a>应用程序的时候，你在VS2005里打开的项目看起来类似如下</p>
		<p>
				<img height="270" hspace="5" src="http://mqingqing123.cnblogs.com/images/cnblogs_com/mqingqing123/image004.jpg" width="201" align="baseline" /> <br /></p>
		<p>从解决方案资源管理器里可以看到，VS2005只包含在<a href="http://www.testsite.com/">www.testsite.com</a>应用程序里夹，和应用程序的子文件夹（例如上面的subdirectory1和subdirectory2）。 这样当你使用VS2005进行编译时，它仅仅编译包含在<a href="http://www.testsite.com/">www.testsite.com</a>应用程序里面的文件（注意这里不包括子应用程序）。而如果你部署该web项目，你页将仅仅部署这些在<a href="http://www.testsite.com/">www.testsite.com</a>的主应用程序（不包括子应用程序）。这其实和VS2003是一样的。</p>
		<p>另外VS2005进一步改善了在资源管理器里嵌套的应用程序的图标的显示，（请参考上面的app1，App2和app3的图标），这些图标能够让开发人员识别这些应用程序在web逻辑空间里它们是子应用程序，而并不是开发时的具体文件存放位置。</p>
		<p>这些子应用程序并不包含具体的内容（这和VS2003类似），所以你并不能够展开它们的内容，因为它们的设计目的是让你知道那里有这样一个子应用程序，目的是可以快速帮助你理解整个应用的体现结构。</p>
		<p>另外还有一点需要注意，在上面app3种被映射到c:\www.testsite.com\wwwroot\app3物理路径，它直接是在主目录 <a href="http://www.testsite.com/">www.testsite.com</a>应用程序（c:\www.testsite.com\wwwroot\）下，可是它被标记为应用程序，所以当你编译<a href="http://www.testsite.com/">www.testsite.com</a>项目时，他会排斥编译app3应用程序到主应用程序里，而subdirectory1和subdirectory2并为标记为应用程序，它将作为主目录的一部分编译到主应用程序里。</p>
		<p>另外一个工作流程改进点是VS2005允许你通过双击子应用程序图标来添加项目。当你在子应用程序上双击（例如在app3上双击）将弹出打开web站点对话框，如图，他会问你时打开该app3应用程序（这将关闭当前<a href="http://www.testsite.com/">www.testsite.com</a>应用程序）还是将该app1应用程序添加到当前<a href="http://www.testsite.com/">www.testsite.com</a>应用程序。</p>
		<p> 例如我选择“add the web site to the current solution”,然后单击OK，这样你的解决方法资源管理器将被分为两个项目，看起来如下</p>
		<p>
				<img height="169" hspace="5" src="http://mqingqing123.cnblogs.com/images/cnblogs_com/mqingqing123/image005.jpg" width="413" align="baseline" />
				<br />
				<br />
				<br />例如 我选择“add the web site to the current solution”，这样当我在解决方案资源管理器单击app3图标时，它就出现如下</p>
		<p>
				<img height="348" hspace="5" src="http://mqingqing123.cnblogs.com/images/cnblogs_com/mqingqing123/image006.jpg" width="205" align="baseline" />
				<br />
				<br />
				<br />
				<strong>
				</strong>
		</p>
		<p>你可以象使用VS2003的同样方式那样来使用VS2005管理Web应用程序以及子应用程序。比较典型的的子应用程序嵌套的例子是包含一个Web项目和一个或者多个类库。</p>
		<p>在下面的这个示意图是一个包含了三层体现结构的应用程序：一个web项目、一个或者多个类库等。我在这个解决方案里增加了数据访问层（Data Access Layer，DAL）和业务逻辑层（Business Logic Layer，BLL）。</p>
		<p>
				<img height="387" hspace="5" src="http://mqingqing123.cnblogs.com/images/cnblogs_com/mqingqing123/image007.jpg" width="207" align="baseline" />
				<br />
				<br />
				<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体">接下来，你就可以设置项目之间的引用和编译的依赖管理，例如上面的这个例子依赖关系如下：<br /><img height="368" hspace="5" src="http://mqingqing123.cnblogs.com/images/cnblogs_com/mqingqing123/image008.jpg" width="386" align="baseline" /><br /></span>
				<br />
		</p>
		<p>
				<span>  这样</span>
				<span lang="EN-US">BLL</span>
				<span>层建立在</span>
				<span lang="EN-US">DAL</span>
				<span>的基础上，而</span>
				<span lang="EN-US">http://localhost:81/</span>
				<span>则建立在</span>
				<span lang="EN-US">BLL</span>
				<span>基础上，这种依赖关系决定了系统编译的顺序为：先编译</span>
				<span lang="EN-US">DAL</span>
				<span>、然后编译</span>
				<span lang="EN-US">BLL</span>
				<span>最后编译</span>
				<span lang="EN-US">
						<a href="http://localhost:81/">http://localhost:81</a>
				</span>
				<span>这个</span>
				<span lang="EN-US">Web</span>
				<span>项目。</span>
		</p>
		<p>
				<span lang="EN-US"> </span>
				<span>我接下来就可以直接保保存我的解决方案，这个解决方法封装了所有的项目（包括项目之间的相互引用和依赖关系），在这方面它和和</span>
				<span lang="EN-US">VS2003</span>
				<span>是类似的，以后我只要打开该解决方案，系统将子定加载所有的项目和资源、文件。</span>
		</p>
		<p>
				<span>当以后我发以后发布</span>
				<span lang="EN-US">Web</span>
				<span>站点时，它会将</span>
				<span lang="EN-US">DAL</span>
				<span>、</span>
				<span lang="EN-US">BLL</span>
				<span>和</span>
				<span lang="EN-US">Web</span>
				<span>项目的整体结果整合在一起编译成二进制文件，因此当我发布</span>
				<span lang="EN-US">web</span>
				<span>网站时，你并不需要</span>
				<span lang="EN-US">DAL</span>
				<span>和</span>
				<span lang="EN-US">BLL</span>
				<span>项目。<br /></span>
		</p>
		<p>
				<span lang="EN-US">
						<strong>（关于上面DAL、BLL等具体的实际应用您可以参考《ASP.NET技术详解与应用实例》的最后一章）</strong> </span>
		</p>
		<p>
				<br />
				<br /> </p>
		<p>
				<b>
						<span>使用</span>
				</b>
				<b>
						<span lang="EN-US">ASP.NET2.0</span>
				</b>
				<b>
						<span>版本</span>
				</b>
		</p>
		<p>
				<span>最后在说一下</span>
				<span lang="EN-US">ASP.NET</span>
				<span>的版本问题。正如</span>
				<span lang="EN-US">Visual Stuido.NET2003</span>
				<span>和</span>
				<span lang="EN-US">.NET Framework V1.1</span>
				<span>配合的很好一样，</span>
				<span lang="EN-US">Visual Studio.NET 2005</span>
				<span>和</span>
				<span lang="EN-US">.NET Framework V2.0</span>
				<span>同样协调的也很好。这意味这</span>
				<span lang="EN-US">VS2003</span>
				<span>和</span>
				<span lang="EN-US">VS2005</span>
				<span>可以装在同一台机器上。原有的项目您仍然可以使用</span>
				<span lang="EN-US">VS2003</span>
				<span>继续开发，而新的项目你可以选择使用</span>
				<span lang="EN-US">VS2005</span>
				<span>进行开发。</span>
		</p>
		<p>
				<span>这也意味这你可以选择你的</span>
				<span lang="EN-US">ASP.NET</span>
				<span>应用程序在</span>
				<span lang="EN-US">web</span>
				<span>服务器上的运行版本，您可以让有些应用程序运行在</span>
				<span lang="EN-US">ASP.NET1.1</span>
				<span>版本上，有些运行在</span>
				<span lang="EN-US">ASP.NET2.0</span>
				<span>版本。也就是说，你可以自行决定</span>
				<span lang="EN-US">.NET</span>
				<span>运行版本的控制。</span>
		</p>
		<p>
				<span>默认的如果你以前在你的机器上安装了</span>
				<span lang="EN-US">ASP.NET1.1</span>
				<span>版本，然后又安装</span>
				<span lang="EN-US">ASP.NET2.0</span>
				<span>后，一般你也不会考虑立刻更改应用程序并升级到最新的版本，相反你可能想自行决定应用程序的使用的版本，正式由于这个原因，因此当你安装</span>
				<span lang="EN-US">ASP.NET2.0</span>
				<span>时，系统并不会更改您的默认设置，而仍然使用</span>
				<span lang="EN-US">ASP.NET1.1</span>
				<span>版本。</span>
		</p>
		<p>
				<span>为了实现</span>
				<span lang="EN-US">.NET</span>
				<span>版本控制的功能，系统是通过使用</span>
				<span lang="EN-US">IIS</span>
				<span>新增加的“</span>
				<span lang="EN-US">ASP.NET</span>
				<span>”页标签来实现的，</span>
				<span lang="EN-US">ASP.NET</span>
				<span>页标签是在我们安装</span>
				<span lang="EN-US">.NET2.0</span>
				<span>版本时自动添加的。在根目录的属性力，可以设置默认全局应用程序版本如下图，除此以外该页标签自动添加在任意一个应用程序的属性里，这页允许我们可以单独设置每一个应用程序的使用版本。</span>
		</p>
		<p>
				<span>这里需要强调一下“级联”性质，以前叙为例子，如果我将</span>
				<span lang="EN-US">app2</span>
				<span>设置为使用</span>
				<span lang="EN-US">.NET 2.0</span>
				<span>，那么此时</span>
				<span lang="EN-US">app3</span>
				<span>如果是</span>
				<span lang="EN-US">.NET1.1</span>
				<span>版本，则保持不变，因为</span>
				<span lang="EN-US">app2</span>
				<span>和</span>
				<span lang="EN-US">app3</span>
				<span>是并列的；</span>
		</p>
		<p>
				<span>然而如果我将</span>
				<span lang="EN-US">app3</span>
				<span>设置为</span>
				<span lang="EN-US">.NET2.0</span>
				<span>，由于</span>
				<span lang="EN-US">app4</span>
				<span>默认丛属于</span>
				<span lang="EN-US">app3</span>
				<span>，所以如果原先</span>
				<span lang="EN-US">app4</span>
				<span>是</span>
				<span lang="EN-US">.NET1.1</span>
				<span>版本，则会更新为</span>
				<span lang="EN-US">.NET2.0</span>
				<span>版本。</span>
		</p>
		<p>
				<img height="467" hspace="5" src="http://mqingqing123.cnblogs.com/images/cnblogs_com/mqingqing123/image009.jpg" width="473" align="baseline" />
		</p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/56468.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-07-04 09:47 <a href="http://www.blogjava.net/Daniel2005/articles/56468.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP开发技巧集锦</title><link>http://www.blogjava.net/Daniel2005/articles/55866.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Fri, 30 Jun 2006 02:11:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/55866.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/55866.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/55866.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/55866.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/55866.html</trackback:ping><description><![CDATA[
		<p>
				<strong>
						<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">21. </span>
				</strong>
				<strong>
						<span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">嵌入另一页</span>
				</strong>
				<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">
						<p>
						</p>
						<p>
						</p>
						<p>
								<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">  &lt;iframe class="TBGen" style="top:2px" ID="UploadFiles" src="upload.asp" frameborder=0 scrolling=no width="250" height="25"&gt;&lt;/iframe&gt;<br /><br /></span>
								<span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">
										<font face="宋体">－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－</font>
								</span>
								<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">
										<br />
								</span>
								<span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">
										<font face="宋体">其实也可以用</font>
								</span>
								<span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;!--#include file="fuck.asp"--&gt; 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">22. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">全部选定</span></strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;SCRIPT language=javascript&gt;<br />function CheckAll(form)<br />  {<br />  for (var i=0;i&lt;form.elements.length;i++)<br />    {<br />    var e = form.elements[i];<br />    if (e.Name != "chkAll")<br />       e.checked = form.chkAll.checked;<br />    }<br />  }<br />&lt;/script&gt;<br /></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">引用：</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />&lt;td width="250" height="30"&gt;&lt;input name="chkAll" type="checkbox" id="chkAll" onclick=CheckAll(this.form) value="checkbox"&gt;</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">选中本页显示的所有</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;/td&gt; 
<p></p><p></p><p><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">小格：</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />&lt;input name='username' type='checkbox'  id="username" value="&lt;%=cstr(rsView("username"))%&gt;"&gt; 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">23. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">如何处理页面执行时发生的错误？</span></strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;%@ LANGUAGE="VBScript" %&gt;<br />&lt;% <br />      Response.Buffer = True ' </span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">打开页面缓冲</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />      On Error Resume Next  ' </span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">打开错误处理</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />      …………' ASP</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">代码</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />%&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;% <br />      If Err.Number &lt;&gt; 0 Then  ' </span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">错误处理</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />      Response.Clear  ' </span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">清除缓冲区</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />%&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;HTML&gt;' </span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">显示错误信息页面</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />&lt;HEAD&gt;<br />&lt;TITLE&gt;</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">页面错误报告</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;/TITLE&gt;<br />&lt;/HEAD&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;BODY BGCOLOR="#C<chmetcnv w:st="on" unitname="C" sourcevalue="0" hasspace="False" negative="False" numbertype="1" tcsc="0">0C</chmetcnv><chmetcnv w:st="on" unitname="C" sourcevalue="0" hasspace="False" negative="False" numbertype="1" tcsc="0">0C</chmetcnv>0"&gt;<br />&lt;font color=red&gt;<br />&lt;p&gt;</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">页面错误报告</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;/p&gt; 
<p></p><p></p><p><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">错误号</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">:&lt;%= Err.Number %&gt;&lt;BR&gt;<br /></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">错误描述</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">:&lt;%= Err.Description %&gt;&lt;BR&gt; <br /></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">错误源</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">:Source &lt;%= Err.Source %&gt;&lt;BR&gt;<br /></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">错误发生行</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">:&lt;%= Err.Line %&gt;&lt;BR&gt;<br />&lt;/BODY&gt;<br />&lt;/HTML&gt;<br />&lt;% <br />End If<br />%&gt; 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">24. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">收藏夹图标</span></strong><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">.</span></strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">在</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"> HEAD </span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">部分加入下面的内容</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">:  <br />&lt;LINK REL="SHORTCUT ICON" HREF=<a href="http://www.alleasy.com.cn/alleasy.ico"><font face="Verdana" color="#0000ff">http://www.alleasy.com.cn/alleasy.ico</font></a>&gt; 
<p></p><p></p><p><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">在地址栏加入图标（图标必须是</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">.ico</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">格式，并且要加入收藏后才有效）</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br /></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">在</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">HEAD</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">里加入</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"> &lt;link rel="shortcut icon" href="favicon.ico"&gt; 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">25. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">校验提交表单（正则表达式应用）</span></strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;script language="JavaScript"&gt;<br />&lt;!--<br />function CheckForm()<br />{ <br />if (LoginID.value =="")<br />{<br />alert("</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">请填写您的登录名！</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">");<br />LoginID.focus();<br />return false;<br />}<br />var filter=/^\s*[.A-Za-z0-9_-]{5,15}\s*$/;<br />if (!filter.test(LoginID.value)) { <br />alert("</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">用户名填写不正确</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">,</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">请重新填写！可使用的字符为（</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">A-Z a-z 0-9 _ - .)</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">长度不小于</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">5</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">个字符，不超过</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">15</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">个字符，注意不要使用空格。</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">"); <br />LoginID.focus();<br />LoginID.select();<br />return false; <br />} <br />if (Password.value =="") <br />{<br />alert("</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">请填写您的密码！</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">");<br />Password.focus();<br />return false; <br />}<br />var filter=/^\s*[.A-Za-z0-9_-]{5,15}\s*$/;<br />if (!filter.test(Password.value)) { <br />alert("</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">密码填写不正确</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">,</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">请重新填写！可使用的字符为（</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">A-Z a-z 0-9 _ - .)</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">长度不小于</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">5</span><font face="宋体"><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">个字符，不超</span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">过</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">15</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">个字符，注意不要使用空格。</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">"); <br />Password.focus();<br />Password.select();<br />return false; <br />} <br />if (Password.value != ConfirmPassword.value) <br />{<br />alert("</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">请两次填写的密码不一致，请重新填写！</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">");<br />ConfirmPassword.focus();<br />return false; <br />}<br />if (CompanyName.value =="")<br />{<br />alert("</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">请填写贵公司名称！</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">");<br />CompanyName.focus();<br />return false;<br />}<br />var filter=/^[a-zA-Z][a-zA-Z0-9._-]*@([a-zA-Z0-9-_]+\.)+(com|gov|net|com\.cn|edu\.cn)$/;<br />if(!filter.test(document.myform.Email.value)){<br />alert("</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">邮箱格式不正确</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">!"); <br />document.myform.Email.focus();<br />return false;<br />}<br />myform.submit();<br />return true;<br />}<br />//--&gt;<br />&lt;/SCRIPT&gt; 
<p></p><p></p><p><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">统一一下，以后都这样写</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />&lt;form method="POST" name="myform"  action="Checkreg.asp" &gt;<br />&lt;/form&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;input type="button" name="Submit" value="</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">提交</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">" onClick="CheckForm();"&gt; 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">26. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">循环</span></strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;%<br />dim sql,rs<br />set rs=server.createobject("ADODB.recordset")<br />sql="select * from news where bigclassname='</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">解决方案</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">'"<br />rs.open sql,conn,1,3<br />for k=1 to rs.recordcount<br />if rs.eof then<br />exit for<br />else<br />%&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;tr&gt;<br /> &lt;td&gt;<br />         asfasdf<br /> &lt;/td&gt;<br />&lt;/tr&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;% <br />rs.movenext<br />end if<br />next<br />%&gt; 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">27. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">另一个只能输入数字代码</span></strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;script language=java script&gt;<br /> function check(){<br />   if(isNaN(tt.value))<br />    {<br />      alert("</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">必须是数字</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">!");<br />      tt.value="";<br />    }<br />&lt;/script&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;input type="text" name="tt" onkeyup="check();"&gt; 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">28. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">有选择显示</span></strong><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">function showco(va)<br />{<font face="Verdana"><span style="mso-spacerun: yes">  </span><br /><span style="mso-spacerun: yes">     </span>if (va=="CO")<br /><span style="mso-spacerun: yes">     </span>{ <br /><span style="mso-spacerun: yes">             </span>RefNum.style.display=''; //</font></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">不再用这个可以直接用</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"> block<br /><font face="Verdana"><span style="mso-spacerun: yes">             </span>buttonsp.style.display='none';<br /><span style="mso-spacerun: yes">      </span>}<br /><span style="mso-tab-count: 1">       </span>if (va=="SP")<br /><span style="mso-spacerun: yes">      </span>{ <br /><span style="mso-spacerun: yes">              </span>buttonco.style.display='none';<br /><span style="mso-spacerun: yes">              </span>buttonsp.style.display='';<br /><span style="mso-spacerun: yes">              </span>kokey.style.display='';<br /><span style="mso-spacerun: yes">      </span>}<br /><span style="mso-tab-count: 1">       </span>if (va=="Inventory")<br /><span style="mso-spacerun: yes">      </span>{<br /><span style="mso-spacerun: yes">               </span>RefNum.style.display='none'; //</font></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">不显示</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br /><font face="Verdana"><span style="mso-spacerun: yes">            </span><span style="mso-spacerun: yes">   </span>Reftr.style.display="block"; //</font></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">显示</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br /><font face="Verdana"><span style="mso-spacerun: yes">       </span>} </font><p></p><p></p><p><font face="宋体"><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">调用：</span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;select name="RefType" style='width:<chmetcnv w:st="on" unitname="pt" sourcevalue="77" hasspace="False" negative="False" numbertype="1" tcsc="0">77pt</chmetcnv>'<font face="Verdana"><span style="mso-spacerun: yes">  </span>onChange="showco(this.value)"&gt; </font><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><font face="Verdana"><span style="mso-spacerun: yes">   </span>&lt;option value="Inventory"&gt;Inventory&lt;/option&gt; </font><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><font face="Verdana"><span style="mso-spacerun: yes">   </span>&lt;option value="CO" &gt;CO&lt;/option&gt; </font><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><font face="Verdana"><span style="mso-spacerun: yes">   </span>&lt;option<span style="mso-spacerun: yes">  </span>value="SP"&gt;SP&lt;/option&gt; </font><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;/select&gt; 
<p></p><p></p><p><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">选择显示行</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"> &lt;tr id="Reftr" name="Reftr" style="display:none"&gt;</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">也可以用</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;div id=”Resftr” &gt;&lt;/div&gt; 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">29. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">调试参数显示规范</span></strong><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">Response.Write session("LoginCompanyId")&amp;","&amp;Date&amp;","&amp;Request.Form("Owner")&amp;","&amp;Request.Form("Name")&amp;<br />//</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">注意最后没有</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">"</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">只是在，之间用</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">","<span style="mso-spacerun: yes"><font face="Verdana">   </font></span></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">其他用</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&amp;&amp;</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">引用即可</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />//</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">也就是说只是用</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><font face="Verdana"><span style="mso-spacerun: yes">  </span>&amp;","&amp;<span style="mso-spacerun: yes">  </span></font></span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">中间加一个逗号，其他的该怎么写，就怎么写</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />Response.End 
<p></p><p></p><p><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体">30. </span></strong><strong><span style="FONT-SIZE: 9pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">从数据库填充下拉菜单</span></strong><strong><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana; mso-bidi-font-family: 宋体"><p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;%<br />sql = "select * from BigClass"<br />rs.open sql,conn,1,1<br />%&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;select name="BigClassName" size="1"&gt;<br />&lt;option selected value="&lt;%=trim(rs("BigClassName"))%&gt;"&gt;&lt;%=trim(rs("BigClassName"))%&gt;&lt;/option&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;%<br />rs.movenext //</span><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana"><font face="宋体">不能少，否则重复</font></span><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><br />do while not rs.eof<br />%&gt; 
<p></p><p></p><p><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">&lt;option value="&lt;%=trim(rs("BigClassName"))%&gt;"&gt;&lt;%=trim(rs("BigClassName"))%&gt;&lt;/option&gt;<br />&lt;%<br />rs.movenext<br />loop<br />rs.close<br />%&gt;<br />&lt;/select&gt; 
<p></p><p></p><p><b style="mso-bidi-font-weight: normal"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana">//</span></b><font face="宋体"><b style="mso-bidi-font-weight: normal"><span style="FONT-SIZE: 9pt; mso-ascii-font-family: Verdana; mso-hansi-font-family: Verdana">以下是新方法</span></b><b style="mso-bidi-font-weight: normal"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><p></p><p></p><p style="MARGIN-LEFT: 13.5pt; TEXT-INDENT: -13.5pt; mso-char-indent-count: -1.5"><span lang="EN-US" style="FONT-SIZE: 9pt; FONT-FAMILY: Verdana"><font face="Verdana"><span style="mso-spacerun: yes"> </span>&lt;select name="SrcNo"&gt;<br />&lt;%do while not SrcRs.eof%&gt;<br />&lt;option value="&lt;%=trim(SrcRs("Cost"))%&gt;" <br /><span style="mso-spacerun: yes">     </span><span style="mso-spacerun: yes">        </span>&lt;% <br /><span style="mso-spacerun: yes">             </span>if Trim(SrcComRs("SrcNo")) = Trim(SrcRs("Cost")) then <br /><span style="mso-spacerun: yes">             </span>response.Write "selected" <br /><span style="mso-spacerun: yes">             </span>end if<br /><span style="mso-spacerun: yes">             </span>%&gt;<br /><span style="mso-spacerun: yes">               </span>&gt;&lt;%=trim(SrcRs("Cost"))%&gt;<br />&lt;/option&gt;<br />&lt;%<br /><span style="mso-spacerun: yes">   </span>SrcRs.movenext<br /><span style="mso-spacerun: yes">    </span>loop<br /><span style="mso-spacerun: yes">    </span>SrcRs.close<br />%&gt;<br />&lt;/select&gt; </font></span></p></span></b></font></p></span></p></span></p></span></p></span></p></span></strong></p></span></p></span></strong></p></span></p></span></p></span></p></span></p></span></p></span></p></span></font></p></span></p></span></strong></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></font></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span></p></span>
						</p>
				</span>
		</p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/55866.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-06-30 10:11 <a href="http://www.blogjava.net/Daniel2005/articles/55866.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>整理MSDN中的SqlConnection.ConnectionString 属性 </title><link>http://www.blogjava.net/Daniel2005/articles/54638.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Fri, 23 Jun 2006 03:06:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/54638.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/54638.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/54638.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/54638.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/54638.html</trackback:ping><description><![CDATA[
		<div class="postbody">
				<p>MSDN中文版中，阿很多不该翻译的翻译了，或者翻译的有问题。我在参阅英文版MSDN和中文版MSDN基础上，跟据自己的经验，把数据库连接字符串整理了一下，具体如下：</p>
				<p>英文版可以看以下地址：</p>
				<p>
						<a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDataSqlClientSqlConnectionClassConnectionStringTopic.asp">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemDataSqlClientSqlConnectionClassConnectionStringTopic.asp</a>
				</p>
				<h1 class="dtH1">SqlConnection.ConnectionString 属性</h1>
				<p>
						<b>ConnectionString</b> 类似于 OLE DB 连接字符串，但并不相同。与 OLE DB 或 ADO 不同，如果“Persist Security Info ”值设置为 <b>false</b>（默认值），则返回的连接字符串与用户设置的 <b>ConnectionString</b> 相同但去除了安全信息。除非将“Persist Security Info ”设置为 <b>true</b>，否则，SQL Server .NET Framework 数据提供程序将不会保持，也不会返回连接字符串中的密码。</p>
				<p>可以使用 <b>ConnectionString</b> 属性连接到数据库。下面的示例阐释了一个典型的连接字符串。</p>
				<pre class="code">"Persist Security Info=False;Integrated Security=SSPI;database=northwind;server=mySQLServer"</pre>
				<p>
				</p>
				<p>只有在连接关闭时才能设置 <b>ConnectionString</b> 属性。许多连接字符串值都具有相应的只读属性。当设置连接字符串时，将更新所有这些属性（除非检测到错误）。检测到错误时，不会更新任何属性。SqlConnection 属性只返回那些包含在 <b>ConnectionString</b> 中的设置。</p>
				<p>若要连接到本地机器，请将服务器指定为“(local)”。（必须始终指定一个服务器。）</p>
				<p>重置已关闭连接上的 <b>ConnectionString</b> 会重置包括密码在内的所有连接字符串值（和相关属性）。例如，如果设置一个连接字符串，其中包含“Database= northwind”，然后再将该连接字符串重置为“Data Source=myserver;Integrated Security=SSPI”，则 Database 属性将不再设置为 Northwind。</p>
				<p>在设置后会立即分析连接字符串。如果在分析时发现语法中有错误，则产生运行库异常，如 ArgumentException。只有当试图打开连接时，才会发现其他错误。</p>
				<p>连接字符串的基本格式包括一系列由分号分隔的关键字/值对。等号 (=) 连接各个关键字及其值。若要包括含有分号、单引号字符或双引号字符的值，则该值必须用双引号括起来。如果该值同时包含分号和双引号字符，则该值可以用单引号括起来。如果该值以双引号字符开始，则还可以使用单引号。相反地，如果该值以单引号开始，则可以使用双引号。如果该值同时包含单引号和双引号字符，则用于将值括起来的引号字符每次出现时，都必须成对出现。</p>
				<p>若要在字符串值中包括前导或尾随空格，则该值必须用单引号或双引号括起来。即使将整数、布尔值或枚举值用引号括起来，其周围的任何前导或尾随空格也将被忽略。然而，保留字符串关键字或值内的空格。使用 .NET Framework 1.1 版时，在连接字符串中可以使用单引号或双引号而不用使用分隔符（例如，Data Source= my'Server 或 Data Source= my"Server），但引号字符不可以为值的第一个或最后一个字符。</p>
				<p>若要在关键字或值中包括等号 (=)，则它之前必须还有另一个等号。例如，在假设的连接字符串中，</p>
				<pre class="code">"key==word=value"</pre>
				<p>
				</p>
				<p>关键字是“key=word”并且值是“value”。</p>
				<p>如果“keyword= value”对中的一个特定关键字多次出现在连接字符串中，则将所列出的最后一个用于值集。</p>
				<p>关键字不区分大小写。</p>
				<p>下表列出了 <b>ConnectionString</b> 中的关键字值的有效名称。</p>
				<p>
				</p>
				<table class="dtTABLE" id="table2" cellspacing="0" width="500">
						<tbody>
								<tr valign="top">
										<th width="32%">名称</th>
										<th>默认值</th>
										<th width="34%">说明</th>
								</tr>
								<tr valign="top">
										<td width="32%">Application Name</td>
										<td> </td>
										<td width="34%">应用程序的名称，如果不提供应用程序名称，默认是：“.Net SqlClient Data Provider”</td>
								</tr>
								<tr valign="top">
										<td width="32%">AttachDBFilename<br />- 或 -<br />extended properties<br />- 或 -<br />Initial File Name </td>
										<td> </td>
										<td width="34%">可连接数据库的主文件的名称，包括完整的路径名。 
<p>必须使用关键字“database”来指定数据库的名称。</p></td>
								</tr>
								<tr valign="top">
										<td width="32%">
												<p>Connect Timeout <br />- 或 -<br />Connection Timeout</p>
										</td>
										<td>15</td>
										<td width="34%">在终止尝试连接并产生错误之前，等待与服务器的连接的时间长度（以秒为单位）。</td>
								</tr>
								<tr valign="top">
										<td width="32%">Current Language</td>
										<td> </td>
										<td width="34%">SQL Server 语言</td>
								</tr>
								<tr valign="top">
										<td width="32%">
												<p>Data Source <br />- 或 -<br />Server<br />- 或 -<br />Address<br />- 或 -<br />Addr<br />- 或 -<br />Network Address</p>
										</td>
										<td> </td>
										<td width="34%">要连接的 SQL Server 实例的名称或网络地址。</td>
								</tr>
								<tr valign="top">
										<td width="32%">Encrypt</td>
										<td>'false'</td>
										<td width="34%">当该值为 <b>true</b> 时，如果服务器端安装了证书，则 SQL Server 将对所有在客户端和服务器之间传送的数据使用 SSL 加密。可识别的值为 <b>true</b>、<b>false</b>、<b>yes</b> 和 <b>no</b>。</td>
								</tr>
								<tr valign="top">
										<td width="32%">
												<p>Initial Catalog<br />- 或 -<br />Database</p>
										</td>
										<td> </td>
										<td width="34%">数据库的名称。</td>
								</tr>
								<tr valign="top">
										<td width="32%">
												<p>Integrated Security <br />- 或 -<br />Trusted_Connection</p>
										</td>
										<td>'false'</td>
										<td width="34%">当为 <b>false</b> 时，将在连接中指定用户 ID 和密码。当为 <b>true</b> 时，将使用当前的 Windows 帐户凭据进行身份验证。 
<p>可识别的值为 <b>true</b>、<b>false</b>、<b>yes</b>、<b>no</b> 以及与 <b>true</b> 等效的 <b>sspi</b>（强烈推荐）。</p></td>
								</tr>
								<tr valign="top">
										<td width="32%">
												<p>Network Library <br />- 或 -<br />Net</p>
										</td>
										<td>'dbmssocn'</td>
										<td width="34%">用于建立与 SQL Server 实例的连接的网络库。支持的值包括 dbnmpntw（命名管道）、dbmsrpcn（多协议）、dbmsadsn (Apple Talk)、dbmsgnet (VIA)、dbmslpcn（共享内存）及 dbmsspxn (IPX/SPX) 和 dbmssocn (TCP/IP)。 
<p>相应的网络 DLL 必须安装在要连接的系统上。如果不指定网络而使用一个本地服务器（比如“.”或“(local)”），则使用共享内存。</p></td>
								</tr>
								<tr valign="top">
										<td width="32%">Packet Size</td>
										<td>8192</td>
										<td width="34%">用来与 SQL Server 的实例进行通讯的网络数据包的大小，以字节为单位。</td>
								</tr>
								<tr valign="top">
										<td width="32%">
												<p>Password <br />- 或 -<br />Pwd</p>
										</td>
										<td> </td>
										<td width="34%">SQL Server 帐户登录的密码（建议不要使用。为了维护最高级别的安全性，强烈建议改用 Integrated Security 或 Trusted_Connection 关键字）。</td>
								</tr>
								<tr valign="top">
										<td width="32%">Persist Security Info</td>
										<td>'false'</td>
										<td width="34%">当该值设置为 <b>false</b> 或 <b>no</b>（强烈推荐）时，如果连接是打开的或者一直处于打开状态，那么安全敏感信息（如密码）将不会作为连接的一部分返回。重置连接字符串将重置包括密码在内的所有连接字符串值。可识别的值为 <b>true</b>、<b>false</b>、<b>yes</b> 和 <b>no</b>。</td>
								</tr>
								<tr valign="top">
										<td width="32%">User ID</td>
										<td> </td>
										<td width="34%">SQL Server 登录帐户（建议不要使用。为了维护最高级别的安全性，强烈建议改用 Integrated Security 或 Trusted_Connection 关键字）。</td>
								</tr>
								<tr valign="top">
										<td width="32%">Workstation ID</td>
										<td>本地计算机名称</td>
										<td width="34%">连接到 SQL Server 的工作站的名称。</td>
								</tr>
						</tbody>
				</table>
				<p>下表列出了 <b>ConnectionString</b> 内连接池值的有效名称。有关连接池的更多信息，请参见 SQL Server .NET Framework 数据提供程序连接池。</p>
				<p>
				</p>
				<table class="dtTABLE" id="table3" cellspacing="0" width="500">
						<tbody>
								<tr valign="top">
										<th width="32%">名称</th>
										<th width="34%">默认值</th>
										<th width="34%">说明</th>
								</tr>
								<tr valign="top">
										<td width="32%">Connection Lifetime</td>
										<td width="34%">0</td>
										<td width="34%">当连接被返回到池时，将其创建时间与当前时间作比较，如果时间长度（以秒为单位）超出了由 <b>Connection Lifetime</b> 指定的值，该连接就会被销毁。这在聚集配置中很有用（用于强制执行运行中的服务器和刚置于联机状态的服务器之间的负载平衡）。 
<p>零 (0) 值将使池连接具有最大的连接超时。</p></td>
								</tr>
								<tr valign="top">
										<td width="32%">Connection Reset</td>
										<td width="34%">'true'</td>
										<td width="34%">确定从池中提取数据库连接时是否重置数据库连接。对于 Microsoft SQL Server 7.0 版，设置为 <b>false</b> 可避免获取连接时再有一次额外的服务器往返行程，但须注意此时并未重置连接状态（如数据库上下文）。</td>
								</tr>
								<tr valign="top">
										<td width="32%">Enlist</td>
										<td width="34%">'true'</td>
										<td width="34%">当该值为 <b>true</b> 时，池程序在创建线程的当前事务上下文中自动登记连接。可识别的值为 <b>true</b>、<b>false</b>、<b>yes</b> 和 <b>no</b>。</td>
								</tr>
								<tr valign="top">
										<td width="32%">Max Pool Size</td>
										<td width="34%">100</td>
										<td width="34%">池中允许的最大连接数。</td>
								</tr>
								<tr valign="top">
										<td width="32%">Min Pool Size</td>
										<td width="34%">0</td>
										<td width="34%">池中允许的最小连接数。</td>
								</tr>
								<tr valign="top">
										<td width="32%">Pooling</td>
										<td width="34%">'true'</td>
										<td width="34%">当该值为 <b>true</b> 时，系统将从相应池中提取 <b>SQLConnection</b> 对象，或在必要时创建该对象并将其添加到相应池中。可识别的值为 <b>true</b>、<b>false</b>、<b>yes</b> 和 <b>no</b>。</td>
								</tr>
						</tbody>
				</table>
				<p>当设置需要布尔值的关键字或连接池值时，您可以使用 'yes' 代替 'true'，'no' 代替 'false'。整数值表示为字符串。</p>
				<p>
						<b class="le">注意</b>   SQL Server .NET Framework 数据提供程序使用它自己的协议与 SQL Server 进行通信。因此，当连接到 SQL Server 时，它不支持 ODBC 数据源名称 (DSN) 的使用，因为它不添加 ODBC 层。 <b class="le">警告</b>   在此版本中，在应用程序中根据用户输入构造连接字符串时（例如，从对话框中检索用户 ID 和密码信息并将其追加到连接字符串时）应相当谨慎。应用程序应确保用户无法在这些值中嵌入额外的连接字符串参数（例如，输入“validpassword;database=somedb”作为密码，以试图连接到其他数据库）。 </p>
				<h4 class="dtH4">示例</h4>
				<p style="DISPLAY: block">
						<span class="lang" style="DISPLAY: none">[Visual Basic, C#]</span> 下面的示例创建一个 SqlConnection并设置它的一些属性。</p>
				<pre class="code">
						<span class="lang" style="DISPLAY: none">[Visual Basic]</span> 
Public Sub CreateSqlConnection()
    Dim myConnection As New SqlConnection()
    myConnection.ConnectionString = <br />"Persist Security Info=False;Integrated Security=SSPI;<br />database=northwind;server=mySQLServer;Connect Timeout=30"
    myConnection.Open()
End Sub 'CreateSqlConnection</pre>
				<p>
				</p>
				<pre class="code">
						<span class="lang" style="DISPLAY: none">[C#]</span> 
public void CreateSqlConnection() 
 {
    SqlConnection myConnection = new SqlConnection();
    myConnection.ConnectionString = <br />"Persist Security Info=False;Integrated Security=SSPI;<br />database=northwind;server=mySQLServer;Connect Timeout=30";
    myConnection.Open();
 }</pre>
		</div>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/54638.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-06-23 11:06 <a href="http://www.blogjava.net/Daniel2005/articles/54638.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.net中DateGrid导出excel方法二！</title><link>http://www.blogjava.net/Daniel2005/articles/50712.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 06 Jun 2006 03:53:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/50712.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/50712.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/50712.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/50712.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/50712.html</trackback:ping><description><![CDATA[
		<p>Call Me.BindGrid()<br />        Me.dgRides.AllowPaging = False<br />        Me.dgRides.DataBind()<br />        Dim strFileName As String = "group_search"<br />        Dim obj_DataGrid As DataGrid = Me.dgRides</p>
		<p>        If obj_DataGrid Is Nothing Then<br />            'ERROR: Session "ojb_DataGrid"<br />            Exit Sub<br />        End If</p>
		<p>        Response.Clear()<br />        Response.Buffer = True<br />        Response.Charset = "utf-8"<br />        Response.AppendHeader("Content-Disposition", "attachment;filename=" &amp; strFileName &amp; ".xls")<br />        Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8")<br />        Response.ContentType = "application/ms-excel"</p>
		<p>        obj_DataGrid.EnableViewState = False</p>
		<p>        obj_DataGrid.AllowPaging = False<br />        obj_DataGrid.DataBind()</p>
		<p>        Dim strTmp As String</p>
		<p>        Dim obj_Col As DataGridColumn<br />        For Each obj_Col In obj_DataGrid.Columns<br />            Response.Write(Adjust(obj_Col.HeaderText) &amp; vbTab)<br />        Next<br />        Response.Write(vbCrLf)</p>
		<p>        Dim obj_Row As DataGridItem<br />        Dim obj_Cell As TableCell<br />        For Each obj_Row In obj_DataGrid.Items<br />            For Each obj_Cell In obj_Row.Cells<br />                Dim obj_Ctrl As Control<br />                For Each obj_Ctrl In obj_Cell.Controls<br />                    If obj_Ctrl.GetType Is GetType(HyperLink) Then<br />                        Dim obj_hplnk As HyperLink<br />                        obj_hplnk = CType(obj_Ctrl, HyperLink)<br />                        Response.Write(Adjust(obj_hplnk.Text))<br />                    ElseIf obj_Ctrl.GetType Is GetType(Label) Then<br />                        Dim obj_Label As Label<br />                        obj_Label = CType(obj_Ctrl, Label)<br />                        Response.Write(Adjust(obj_Label.Text))<br />                    End If<br />                Next<br />                Response.Write(Adjust(obj_Cell.Text) &amp; vbTab)<br />            Next<br />            Response.Write(vbCrLf)<br />        Next</p>
		<p>        For Each obj_Col In obj_DataGrid.Columns<br />            Response.Write(Adjust(obj_Col.FooterText) &amp; vbTab)<br />        Next<br />        Response.Write(vbCrLf)</p>
		<p>        Response.End()</p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/50712.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-06-06 11:53 <a href="http://www.blogjava.net/Daniel2005/articles/50712.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Asp.net中DateGrid导出Excel方法！</title><link>http://www.blogjava.net/Daniel2005/articles/50667.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 06 Jun 2006 01:47:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/50667.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/50667.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/50667.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/50667.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/50667.html</trackback:ping><description><![CDATA[
		<p>Protected Sub btnExcel_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnExcel.Click<br />        Dim strLevelID As String = Trim(Session("level_id"))<br />        Dim strFileName As String = "DayOfReport"<br />        Dim obj_DataGrid As DataGrid = DataGrid_VoucherList</p>
		<p>        If strLevelID = String.Empty Then<br />            'ERROR: Session "Acct_ID" missing<br />            'Response.Redirect("Login.aspx?LogOff=1")<br />            Exit Sub<br />        End If</p>
		<p>        If obj_DataGrid Is Nothing Then<br />            'ERROR: Session "ojb_DataGrid"<br />            Exit Sub<br />        End If</p>
		<p>        Response.Clear()<br />        Response.Buffer = True<br />        Response.Charset = "utf-8"<br />        Response.AppendHeader("Content-Disposition", "attachment;filename=" &amp; strFileName &amp; ".xls")<br />        Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8")<br />        Response.ContentType = "application/ms-excel"</p>
		<p>        obj_DataGrid.EnableViewState = False</p>
		<p>        obj_DataGrid.AllowPaging = False<br />        obj_DataGrid.DataBind()</p>
		<p>        Dim strTmp As String</p>
		<p>        Dim obj_Col As DataGridColumn<br />        For Each obj_Col In obj_DataGrid.Columns<br />            Response.Write(Adjust(obj_Col.HeaderText) &amp; vbTab)<br />        Next<br />        Response.Write(vbCrLf)</p>
		<p>        Dim obj_Row As DataGridItem<br />        Dim obj_Cell As TableCell<br />        For Each obj_Row In obj_DataGrid.Items<br />            For Each obj_Cell In obj_Row.Cells<br />                Dim obj_Ctrl As Control<br />                For Each obj_Ctrl In obj_Cell.Controls<br />                    If obj_Ctrl.GetType Is GetType(HyperLink) Then<br />                        Dim obj_hplnk As HyperLink<br />                        obj_hplnk = CType(obj_Ctrl, HyperLink)<br />                        Response.Write(Adjust(obj_hplnk.Text))<br />                    ElseIf obj_Ctrl.GetType Is GetType(Label) Then<br />                        Dim obj_Label As Label<br />                        obj_Label = CType(obj_Ctrl, Label)<br />                        Response.Write(Adjust(obj_Label.Text))<br />                    End If<br />                Next<br />                Response.Write(Adjust(obj_Cell.Text) &amp; vbTab)<br />            Next<br />            Response.Write(vbCrLf)<br />        Next</p>
		<p>        For Each obj_Col In obj_DataGrid.Columns<br />            Response.Write(Adjust(obj_Col.FooterText) &amp; vbTab)<br />        Next<br />        Response.Write(vbCrLf)</p>
		<p>        Response.End()<br />    End Sub</p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/50667.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-06-06 09:47 <a href="http://www.blogjava.net/Daniel2005/articles/50667.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET 中 Cookie 的基本知识</title><link>http://www.blogjava.net/Daniel2005/articles/50424.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Mon, 05 Jun 2006 01:51:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/50424.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/50424.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/50424.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/50424.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/50424.html</trackback:ping><description><![CDATA[Mike Pope<br />Visual Basic User Education<br />Microsoft Corporation <br />2003年1月 
<p><b class="le">摘要：</b>本文介绍如何使用 Visual Basic 在 ASP.NET Web 应用程序中读写 HTTP Cookie。</p><p><b>适用于：</b></p><ul type="disc"><li>ASP.NET 
</li><li>Microsoft® Visual Studio® .NET 
</li><li>Web 窗体 </li></ul><p><b><i>读者范围：初级 Web 程序员</i></b></p><h4 class="dtH4">目录</h4><ul><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor1" target="_self">简介</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor2" target="_self">什么是 Cookie？</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor3" target="_self">Cookie 的限制</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor5" target="_self">编写 Cookie</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor6" target="_self">多值 Cookie（子键）</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor7" target="_self">控制 Cookie 的有效范围</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor8" target="_self">读取 Cookie</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor9" target="_self">修改和删除 Cookie</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor4" target="_self">Cookie 和安全性</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor10" target="_self">检查浏览器是否接受 Cookie</a></li><li><a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor11" target="_self">Cookie 和会话状态</a></li></ul><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor1"></a>简介</h2><p>Cookie 为 Web 应用程序保存用户相关信息提供了一种有用的方法。例如，当用户访问您的站点时，您可以利用 Cookie 保存用户首选项或其他信息，这样，当用户下次再访问您的站点时，应用程序就可以检索以前保存的信息。</p><p>本文概要介绍 Cookie 在 ASP.NET 应用程序中的应用，为您展示在 ASP.NET 中应用 Cookie 的技术细节，例如编写 Cookie、然后再读取它们。同时，还将为您介绍 Cookie 的各种特性和各种特殊情况，以及 ASP.NET 对 Cookie 的支持。</p><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor2"></a>什么是 Cookie？</h2><p>Cookie 是一小段文本信息，伴随着用户请求和页面在 Web 服务器和浏览器之间传递。用户每次访问站点时，Web 应用程序都可以读取 Cookie 包含的信息。</p><p>假设在用户请求访问您的网站 www.contoso.com 上的某个页面时，您的应用程序发送给该用户的不仅仅是一个页面，还有一个包含日期和时间的 Cookie。用户的浏览器在获得页面的同时还得到了这个 Cookie，并且将它保存在用户硬盘上的某个文件夹中。</p><p>以后，如果该用户再次访问您站点上的页面，当该用户输入 URL www.contoso.com 时，浏览器就会在本地硬盘上查找与该 URL 相关联的 Cookie。如果该 Cookie 存在，浏览器就将它与页面请求一起发送到您的站点，您的应用程序就能确定该用户上一次访问站点的日期和时间。您可以根据这些信息向用户发送一条消息，也可以检查过期时间或执行其他有用的功能。</p><p>Cookie 是与 Web 站点而不是与具体页面关联的，所以无论用户请求浏览站点中的哪个页面，浏览器和服务器都将交换 www.contoso.com 的 Cookie 信息。用户访问其他站点时，每个站点都可能会向用户浏览器发送一个 Cookie，而浏览器会将所有这些 Cookie 分别保存。</p><p>以上就是 Cookie 的基本工作原理。那么，Cookie 有哪些用途呢？最根本的用途是 Cookie 能够帮助 Web 站点保存有关访问者的信息。更概括地说，Cookie 是一种保持 Web 应用程序连续性（即执行“状态管理”）的方法。浏览器和 Web 服务器除了在短暂的实际信息交换阶段以外总是断开的，而用户向 Web 服务器发送的每个请求都是单独处理的，与其他所有请求无关。然而在大多数情况下，都有必要让 Web 服务器在您请求某个页面时对您进行识别。例如，购物站点上的 Web 服务器跟踪每个购物者，以便站点能够管理购物车和其他的用户相关信息。因此 Cookie 的作用就类似于名片，它提供了相关的标识信息，可以帮助应用程序确定如何继续执行。</p><p>使用 Cookie 能够达到多种目的，所有这些目的都是为了使 Web 站点记住您。例如，一个实施民意测验的站点可以简单地利用 Cookie 作为布尔值，表示您的浏览器是否已经参与了投票，从而避免您重复投票； 而那些要求用户登录的站点则可以通过 Cookie 来确定您是否已经登录过，这样您就不必每次都输入凭据。</p><p>有关 Cookie 的更多背景信息，建议您阅读 Verizon Web 站点中的“How Internet Cookies Work”一文，地址为 <a href="http://www22.verizon.com/about/community/learningcenter/articles/displayarticle1/0,4065,1022z1,00.html">http://www22.verizon.com/about/community/learningcenter/articles/displayarticle1/0,4065,1022z1,00.html</a>（英文）。其作者详细解释了什么是 Cookie 以及 Cookie 是如何在浏览器和服务器之间交换信息的，他还全面总结了 Cookie 涉及的隐私问题。</p><p>顺便问一下，您是否想知道它们为什么被称作“Cookie”？Jargon File（又称为“The New Hacker's Dictionary”）版本 4.3.3 对这一术语的词源给出了准确的定义和合理的解释。您可以在 <a href="http://www.catb.org/~esr/jargon/jargon.html#cookie">http://www.catb.org/~esr/jargon/jargon.html#cookie</a>（英文）找到相关的条目。</p><p>在此后的内容中，本文将假设您已经知道什么是 Cookie，并且假设您已经清楚为什么要在 ASP.NET 应用程序中使用 Cookie。</p><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor3"></a>Cookie 的限制</h2><p>在开始讨论 Cookie 的技术细节之前，我想先介绍一下 Cookie 应用的几条限制。大多数浏览器支持最多可达 4096 字节的 Cookie，如果要将为数不多的几个值保存到用户计算机上，这一空间已经足够大，但您不能用一个 Cookie 来保存数据集或其他大量数据。在实际应用中，您可能并不希望在 Cookie 中保存大量的用户信息，而只希望保存用户编号或其他标识符。之后，当用户再次访问您的站点时，您就可以使用该用户 ID 在数据库中查找用户的详细信息。（有关保存用户信息的说明，请参阅 <a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor4" target="_self">Cookie 和安全性</a>。）</p><p>浏览器还限制了您的站点可以在用户计算机上保存的 Cookie 数。大多数浏览器只允许每个站点保存 20 个 Cookie。如果试图保存更多的 Cookie，则最先保存的 Cookie 就会被删除。还有些浏览器会对来自所有站点的 Cookie 总数作出限制，这个限制通常为 300 个。</p><p>您最可能遇到的 Cookie 限制是：用户可以设置自己的浏览器，拒绝接受 Cookie。您很难解决这个问题，除非完全不使用 Cookie 而是通过其他机制来保存用户相关信息。保存用户信息的一种常用方法是会话状态，但会话状态又依赖于 Cookie。这一点在后面的 <a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor11" target="_self">Cookie 和会话状态</a>中阐述。</p><blockquote class="dtBlock"><b>注意：</b>有关状态管理和 Web 应用程序中用于保存信息的选项的详细信息，请参阅 <a href="http://www.microsoft.com/msdn/library/en-us/vbcon/html/vbconIntroductionToWebFormsStateManagement.asp">Introduction to Web Forms State</a>（英文）和 <a href="http://www.microsoft.com/msdn/library/en-us/vbcon/html/vbconChoosingServerStateOption.asp">State Management Recommendations</a>（英文）。</blockquote><p>更一般的经验很可能是，尽管 Cookie 在应用程序中非常有用，应用程序也不应该依赖于能够保存 Cookie。利用 Cookie 可以做到锦上添花，但不要利用它们来支持关键功能。如果您的应用程序必须使用 Cookie，则您可以通过测试来确定浏览器是否接受 Cookie。我在本文后面的<a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor10" target="_self">检查浏览器是否接受 Cookie</a> 一节中简单介绍了一种测试方法。</p><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor5"></a>编写 Cookie</h2><p>您可以利用页面的 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebUIPageClassResponseTopic.asp">Response</a>（英文）属性来编写 Cookie，该属性提供的对象使用户可以将信息添加到由页面向浏览器呈现的信息中。<b>Response</b> 对象支持一个名为 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebHttpResponseClassCookiesTopic.asp">Cookies</a>（英文）的集合，您可以向其中添加要写入浏览器的 Cookie。</p><blockquote class="dtBlock"><b class="le">注意：</b>下面要讨论的 <b>Response</b> 对象和 <b>Request</b> 对象分别是包含 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebHttpResponseClassTopic.asp">HttpResponse</a>（英文）和 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebHttpRequestClassTopic.asp">HttpRequest</a>（英文）类实例的页面的属性。要在文档中查找 <b>Response</b> 和 <b>Request</b> 的信息，请参阅 <b>HttpResponse</b> 和 <b>HttpRequest</b> 下的内容。</blockquote><p>在创建 Cookie 时，您需要指定几个值。最初，您要指定 Cookie 的名称和其中保存的值。您可以创建多个 Cookie，每个 Cookie 都必须具有唯一的名称，以便日后读取时识别。（Cookie 是按名称保存的，所以如果您创建了两个名称相同的 Cookie，后保存的那一个将覆盖前一个。）</p><p>您可能还希望指定 Cookie 的过期日期和时间。Cookie 一般都写入到用户的磁盘，然后可能一直都留在磁盘上。因此，您可以指定 Cookie 过期的日期和时间。当用户再次访问您的站点时，浏览器会先检查您站点的 Cookie 集合，如果某个 Cookie 已经过期，浏览器不会把这个 Cookie 随页面请求一起发送给服务器，而是删除这个已经过期的 Cookie。（您的站点可能已经在用户计算机上写入了多个 Cookie，每个 Cookie 都有各自的过期日期和时间。） 请注意，由浏览器负责管理硬盘上的 Cookie，这将影响您在应用程序中对 Cookie 的使用，我很快会介绍这方面的内容。</p><p>一个 Cookie 的有效期应为多长？这取决于 Cookie 的用途，换句话说，取决于您的应用程序需要 Cookie 值保持有效的时间有多长。如果利用 Cookie 统计网站的访问者，您可以把有效期设置为 1 年，如果某个用户已有一年时间未访问您的站点，则可以把该用户当作新的访问者； 如果利用 Cookie 来保存用户的首选项，则可以把其设置为永远有效（例如 50 年后到期），因为定期重新设置首选项对用户而言是比较麻烦的。有时，您可能需要编写在数秒或数分钟内即过期的 Cookie。在本文后面的<a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor10" target="_self">检查浏览器是否接受 Cookie</a> 一节中，我列举了一个示例，该示例中创建的 Cookie 的实际有效期就只有几秒。</p><blockquote class="dtBlock"><b class="le">注意：</b>不要忘记用户随时可以删除自己计算机上的 Cookie，所以即使您保存了长期有效的 Cookie，用户也可以自行决定将其全部删除，同时清除保存在 Cookie 中的所有设置。</blockquote><p>如果没有设置 Cookie 的有效期，还是可以创建 Cookie，但它不会保存到用户的硬盘上，而是会成为用户会话信息的一部分。如果用户关闭浏览器或会话超时，该 Cookie 就会被删除。这种非永久性的 Cookie 很适合用来保存只需短时间保存的信息，或者保存由于安全原因不应该写入客户计算机磁盘的信息。例如，如果用户使用的是一台公用计算机，而您不希望把 Cookie 写入这种计算机的磁盘上，这时就可以使用非永久性的 Cookie。</p><p>您可以通过多种方法把 Cookie 添加到 <b>Response.Cookies</b> 集合中。以下示例介绍了两种完成此任务的方法：</p><pre class="code">Response.Cookies("userName").Value = "mike"
Response.Cookies("userName").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("lastVisit")
aCookie.Value = DateTime.Now.ToString
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)
</pre><p>该示例向 <b>Cookies</b> 集合中添加了两个 Cookie，一个称为“userName”，另一个称为“lastVisit”。对于第一个 Cookie，我直接设置了 <b>Response.Cookies</b> 集合的值。您可以使用这种方法向集合中添加值，因为 <b>Response.Cookies</b> 是从 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemCollectionsSpecializedNameObjectCollectionBaseClassTopic.asp">NameObjectCollectionBase</a>（英文）类型的特殊集合派生得到的。</p><p>对于第二个 Cookie，我创建了 Cookie 对象的一个实例（<a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebHttpCookieClassTopic.asp">HttpCookie</a> [英文] 类型），并设置了其属性，然后通过 <b>Add</b> 方法把它添加到 <b>Response.Cookies</b> 集合。实例化 <b>HttpCookie</b> 对象时，您必须把 Cookie 名称作为构造函数的一部分进行传递。</p><p>这两个示例完成了相同的任务，即向浏览器写入一个 Cookie。您要采用哪种方法主要取决于您的个人喜好。您可能会发现第二种方法在设置 Cookie 属性方面要稍微容易一些，但同时您也会注意到两者的差别并不是很大。</p><p>在这两种方法中，有效期值必须为 <b>DateTime</b> 类型。而“lastVisited”值也是日期/时间值。但在这种情况下，我必须把日期/时间值转换为字符串，因为 Cookie 中的任何值最终都是以字符串的形式保存的。</p><h3 class="dtH3">查看您的 Cookie</h3><p>您可能会发现，了解创建 Cookie 的效果会对您很有帮助。而查看 Cookie 是比较容易的，因为它们都是文本文件，关键在于您能找到它们。不同的浏览器保存 Cookie 的方式也不同。我将介绍 Internet Explorer 是如何保存 Cookie 的。如果您使用的是其他浏览器，请查看该浏览器的帮助，以了解有关 Cookie 处理方面的知识。</p><p>查看 Cookie 的一个简便方法是让 Internet Explorer 为您查找。在 Internet Explorer 中，从“工具”菜单中选择“Internet 选项”，在“常规”选项卡中单击“设置”，然后单击“查看文件”。Internet Explorer 将打开一个窗口，显示所有的临时文件，包括 Cookie。在窗口中查找以“Cookie:”开头的文件 或查找文本文件。双击一个 Cookie，在默认的文本文件中打开它。</p><p>您也可以在硬盘上查找 Cookie 的文本文件，从而打开 Cookie。Internet Explorer 将站点的 Cookie 保存在文件名格式为 <i>&lt;user&gt;</i>@<i>&lt;domain&gt;</i>.txt 的文件中，其中 <i>&lt;user&gt;</i> 是您的帐户名。例如，如果您的名称为 mikepope，您访问的站点为 www.contoso.com，那么该站点的 Cookie 将保存在名为 <code class="ce">mikepope@www.contoso.txt</code> 的文件中。（该文件名可能包含一个顺序的编号，如 <code class="ce">mikepope@www.contoso[1].txt</code>。） </p><p>这个 Cookie 文本文件是与用户相关的，所以会按照帐户分别保存。例如，在 Windows XP 中，您可以在如下所示的目录中找到 Cookie 文件：</p><pre class="code">c:\Documents and Settings\<i>&lt;user&gt;</i>\Cookies
</pre><p>要查找最新创建的 Cookie，可以按修改日期对目录内容进行排序，并查找最近修改的文件。</p><p>您可以使用文本编辑器打开 Cookie。如果该文件包含多个 Cookie，这些 Cookie 之间将用星号 (*) 分隔。每个 Cookie 的第一行是 Cookie 的名称，第二行是值，其余各行则包含 Cookie 的日常处理信息，例如过期日期和时间。Cookie 中还有一个简单的校验和，如果更改 Cookie 名称或值的长度，浏览器就会检测到修改并删除该 Cookie。</p><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor6"></a>多值 Cookie（子键）</h2><p>以上示例为每个要保存的值（用户名、上次访问时间）都使用了一个 Cookie 。您也可以在一个 Cookie 中保存多个名称/值对。名称/值对也称作“键”或“子键”，具体取决于您读取的内容。（如果您熟悉 URL 的结构，就会发现子键与其中的查询字符串非常相象。） 例如，如果不希望创建名为“userName”和“lastVisit”的两个单独的 Cookie，可以创建一个名为“userInfo”的 Cookie，并使其包含两个子键：“userName”和“lastVisit”。</p><p>有很多原因会让我们用子键来代替单独的 Cookie。最显而易见的是，把相关或类似的信息放在一个 Cookie 中会比较有条理。另外，由于所有信息都在一个 Cookie 中，所以诸如有效期之类的 Cookie 属性就适用于所有信息。（当然，如果要为不同类型的信息指定不同的过期日期，就应该把信息保存在单独的 Cookie 中。）</p><p>带有子键的 Cookie 还可以帮助您减小 Cookie 的大小。如前面的 <a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor3" target="_self">Cookie 的限制</a>一节所述，Cookie 的总大小限制在 4096 字节以内，而且不能为一个网站保存超过 20 个 Cookie。利用带子键的单个 Cookie，站点的 Cookie 数量就不会超过 20 个的限制。此外，一个 Cookie 会占用大约 50 个字符的基本空间开销（用于保存有效期信息等），再加上其中保存的值的长度，其总和接近 4K 的限制。如果使用五个子键而不是五个单独的 Cookie，您可以省去四个 Cookie 的基本空间开销，总共能节省大约 200 个字节。</p><p>要创建带子键的 Cookie，您可以使用用于编写单个 Cookie 的各种语法。以下示例显示了编写同一 Cookie 的两种不同方法，其中的每个 Cookie 都带有两个子键：</p><pre class="code">Response.Cookies("userInfo")("userName") = "mike"
Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)

Dim aCookie As New HttpCookie("userInfo")
aCookie.Values("userName") = "mike"
aCookie.Values("lastVisit") = DateTime.Now.ToString
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)
</pre><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor7"></a>控制 Cookie 有效范围</h2><p>默认情况下，一个站点的全部 Cookie 都一起保存在客户机上，而且所有这些 Cookie 都会随着对该站点发送的请求一起发送到服务器，也就是说，站点的每个页面都能得到该站点的所有 Cookie。但有时候，您可能希望 Cookie 更具有针对性，这时，您可以通过两种方法设置 Cookie 的有效范围： 
</p><ul type="disc"><li>把 Cookie 的有效范围限制在服务器上的一个文件夹中，实际上这样就将 Cookie 限制到站点上的某个应用程序。 
</li><li>把有效范围设置为某个域，从而允许您指定域中的哪些子域可以访问 Cookie。 </li></ul><h3 class="dtH3">将 Cookie 限制到某个文件夹或应用程序</h3><p>要将 Cookie 限制到服务器上的某个文件夹，请按如下方法设置 Cookie 的 <b>Path</b> 属性：</p><pre class="code">Dim appCookie As New HttpCookie("AppCookie")
appCookie.Value = "written " &amp; Now.ToString
appCookie.Expires = Now.AddDays(1)
<code><b class="cfe">appCookie.Path = "/Application1"</b></code>
Response.Cookies.Add(appCookie)
</pre><p>当然，您也可以通过直接设置 <b>Response.Cookies</b> 来编写 Cookie，如前文所述。</p><p>路径可以是站点根目录下的物理路径，也可以是虚拟根目录。这样一来，Cookie 就只能用于 Application1 文件夹或虚拟根目录中的页面。例如，如果您的站点名为 www.contoso.com，则前面示例中生成的 Cookie 就只能用于路径为 http://www.contoso.com/Application1/ 的页面以及该文件夹下的所有页面，而不适用于其他应用程序中的页面，如 http://www.contoso.com/Application2/ 或 http://www.contoso.com/ 下的页面。</p><blockquote class="dtBlock"><b class="le">提示：</b>通过对 Internet Explorer 和 Mozilla 浏览器进行测试发现，此处使用的路径是区分大小写的。一般而言，Windows 服务器上的 URL 不区分大小写，但这种情况例外。您无法控制用户如何在浏览器中输入 URL，但是，如果您的应用程序依赖于与特定路径相关的 Cookie，则请确保您所创建的所有超链接中的 URL 与 <b>Path</b> 属性值的大小写相匹配。</blockquote><h3 class="dtH3">将 Cookie 的有效范围限制到域</h3><p>默认情况下，Cookie 与特定的域相关联。例如，如果您的站点是 www.contoso.com，那么当用户向该站点请求页面时，您编写的 Cookie 就被发送到服务器。（有特定路径值的 Cookie 除外，我在上一节刚刚解释过。） 如果您的站点有子域（例如 contoso.com、sales.contoso.com 和 support.contoso.com），就可以把 Cookie 同特定的子域相关联。为此，需要设置 Cookie 的 <b>Domain</b> 属性，如下所示：</p><pre class="code">Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
<code><b class="cfe">Response.Cookies("domain").Domain = "support.contoso.com"</b></code></pre><p>如果按照这种方式设置域，则 Cookie 只能用于指定子域中的页面。</p><p>您也可以利用 <b>Domain</b> 属性来创建可在多个子域中共享的 Cookie。例如，对域进行如下设置：</p><pre class="code">Response.Cookies("domain").Value = DateTime.Now.ToString
Response.Cookies("domain").Expires = DateTime.Now.AddDays(1)
<code><b class="cfe">Response.Cookies("domain").Domain = "contoso.com"</b></code></pre><p>这样，该 Cookie 就可用于主域、sales.contoso.com 和 support.contoso.com。</p><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor8"></a>读取 Cookie</h2><p>当浏览器向服务器发送请求时，该服务器的 Cookie 会与请求一起发送。在 ASP.NET 应用程序中，您可以使用 <b>Request</b> 对象来读取 Cookie。<b>Request</b> 对象的结构与 <b>Response</b> 对象的结构基本相同，所以从 <b>Request</b> 对象中读取 Cookie 的方法与向 <b>Response</b> 对象中写入 Cookie 的方法非常类似。以下示例显示了两种方法，目的都是获取名为“username”的 Cookie 的值并将值显示在 <b>Label</b> 控件中：</p><pre class="code">If Not Request.Cookies("userName") Is Nothing Then
   Label1.Text = Server.HtmlEncode(Request.Cookies("userName").Value)
End If

If Not Request.Cookies("userName") Is Nothing Then
   Dim aCookie As HttpCookie = Request.Cookies("userName")
   Label1.Text = Server.HtmlEncode(aCookie.Value)
End If 
</pre><p>在获取 Cookie 的值之前，应该确保该 Cookie 确实存在。否则，您将得到一个 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemNullReferenceExceptionClassTopic.asp">System.NullReferenceException</a>（英文）异常。还需要注意的是，在页面中显示 Cookie 的内容之前，我调用了 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebHttpServerUtilityClassHtmlEncodeTopic1.asp">HttpServerUtility.HtmlEncode</a>（英文）方法对 Cookie 的内容进行编码。之所以这样做，是因为我要显示 Cookie 的内容（一般您不会这样做）而且要确保没有任何恶意用户在 Cookie 中添加了可执行脚本。有关 Cookie 安全性的详细信息，请参阅 <a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor4" target="_self">Cookie 和安全性</a>。</p><blockquote class="dtBlock"><b class="le">注意：</b>由于不同的浏览器保存 Cookie 的方式也不同，所以同一台计算机上的不同浏览器不一定能够相互读取各自的 Cookie。例如，如果使用 Internet Explorer 测试一个页面，然后再使用其他浏览器进行测试，那么后者就不会找到 Internet Explorer 保存的 Cookie。当然，大多数人一般都是使用同一种浏览器进行 Web 交互的，因此在大多数情况下不会出现问题。但有时还是会遇到问题，比如您要测试应用程序对浏览器的兼容性。</blockquote><p>读取 Cookie 中子键值的方法与设置该值的方法类似。以下是获取子键值的一种方法：</p><pre class="code">If Not Request.Cookies("userInfo") Is Nothing Then
   Label1.Text = _
        Server.HtmlEncode(Request.Cookies("userInfo")("userName"))
   Label2.text = _
        Server.HtmlEncode(Request.Cookies("userInfo")("lastVisit"))
End If
</pre><p>在上面的示例中，我获取的是子键“lastVist”的值，在此前的讨论中我把该值设置为 <b>DateTime</b> 值的字符串表示形式。请记住，Cookie 是用字符串的形式保存值的，所以要将 lastVisit 值用作日期，就必须对其进行转换：</p><pre class="code">Dim dt As DateTime
dt = CDate(Request.Cookies("userInfo")("lastVisit"))
</pre><p>Cookie 中子键的类型是 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemCollectionsSpecializedNameValueCollectionClassTopic.asp">NameValueCollection</a>（英文）类型的集合。因此，另一种获取单个子键的方法是先获取子键集合，然后按名称提取子键的值，如下所示：</p><pre class="code">If Not Request.Cookies("userInfo") Is Nothing Then
   Dim UserInfoCookieCollection As _
      System.Collections.Specialized.NameValueCollection
   UserInfoCookieCollection = Request.Cookies("userInfo").Values
   Label1.Text = Server.HtmlEncode(UserInfoCookieCollection("userName"))
   Label2.Text = Server.HtmlEncode(UserInfoCookieCollection("lastVisit"))
End If
</pre><p>就像设置 Cookie 一样，使用哪种方法读取 Cookie 也由您自己决定。</p><h3 class="dtH3">什么是有效期？</h3><p>您可以读取 Cookie 的名称和值，除此以外，需要了解的有关 Cookie 的信息并不是很多。虽然您可以获取 <b>Domain</b> 和 <b>Path</b> 属性，但是这些属性的用途很有限。例如，您可以读取 <b>Domain</b> 属性，但如果您的页面与 Cookie 不在相同的域，您根本就不会在页面的位置接收到该 Cookie。</p><p>您无法读取的是 Cookie 的过期日期和时间。事实上，当浏览器向服务器发送 Cookie 信息时，浏览器并未将过期信息包括在内。您可以读取 <b>Expires</b> 属性，但总是返回为零的日期/时间值。</p><p>在前面的<a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor5" target="_self">编写 Cookie</a> 一节中，我已经讲过，是浏览器负责管理 Cookie 的，<b>Expires</b> 属性就很好地印证了这一点。<b>Expires</b> 属性的主要作用是帮助浏览器执行有关 Cookie 保存的日常管理。从服务器的角度来看，Cookie 要么存在要么不存在，所以对服务器而言，有效期并不是有用的信息。所以，浏览器在发送 Cookie 时并不提供此信息。如果您需要 Cookie 的过期日期，就必须重新设置，关于这一点我将在<a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor9" target="_self">修改和删除 Cookie</a> 中介绍。</p><p>更确切地说，您可以在向浏览器发送 Cookie 之前读取已在 <b>Response</b> 对象中设置的 <b>Expires</b> 属性，但您无法从返回的 <b>Request</b> 对象中获取有效期信息。</p><h3 class="dtH3">读取 Cookie 集合</h3><p>前面的示例假设您要读取名称已知的 Cookie。有时，您可能需要读取可供页面使用的所有 Cookie。要读取可供页面使用的所有 Cookie 的名称和值，您可以利用如下代码遍历 <b>Request.Cookies</b> 集合：</p><pre class="code">Dim i As Integer
Dim output As String = ""
Dim aCookie As HttpCookie
For i = 0 to Request.Cookies.Count - 1
    aCookie = Request.Cookies(i)
    output &amp;= "Cookie 名称 = " &amp; Server.HtmlEncode(aCookie.Name) &amp; "&lt;br&gt;"
    output &amp;= "Cookie 值 = " &amp; Server.HtmlEncode(aCookie.Value) &amp; _
        &amp; "&lt;br&gt;&lt;br&gt;"
Next 
Label1.Text = output
</pre><blockquote class="dtBlock"><b class="le">注意：</b>运行此代码时，您很可能会看到一个名为“ASP.NET_SessionId”的 Cookie，ASP.NET 用这个 Cookie 来保存您的会话的唯一标识符。这个会话 Cookie 不会永久保存到您的硬盘上。有关会话 Cookie 的详细信息，请参阅本文后面的 <a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor11" target="_self">Cookie 和会话状态</a>。</blockquote><p>前面的示例有一个限制：如果 Cookie 有子键，就会以一个单独的名称/值字符串来显示子键。Cookie 的 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebHttpCookieClassHasKeysTopic.asp">HasKeys</a>（英文）属性可以告诉您该 Cookie 是否有子键。如果有子键，您可以在子键集合中向下钻取，获取各个子键的名称和值。</p><p>如前文所述，您可以从 Cookie 属性 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebHttpCookieClassValuesTopic.asp">Values</a>（英文）中获取有关子键的信息，该属性是类型 <b>NameValueCollection</b> 的集合。您可以根据索引值从 <b>Values</b> 集合中直接读取子键值。相应的子键值可以从 <b>Values</b> 集合的成员 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemCollectionsSpecializedNameValueCollectionClassAllKeysTopic.asp">AllKeys</a>（英文）中得到，该成员将返回一个字符串集合。</p><p>以下示例是对前一示例的修改。示例中使用 <b>HasKeys</b> 属性来测试子键，如果检测到子键，就从 <b>Values</b> 集合中获取子键：</p><pre class="code">Dim i As Integer
<code><b class="cfe">Dim j As Integer</b></code>
Dim output As String = ""
Dim aCookie As HttpCookie
Dim subkeyName As String
Dim subkeyValue As String
For i = 0 To Request.Cookies.Count - 1
   aCookie = Request.Cookies(i)
   output &amp;= "名称 = " &amp; aCookie.Name &amp; "&lt;br&gt;"
<code><b class="cfe">   If aCookie.HasKeys Then</b></code><code><b class="cfe">      For j = 0 To aCookie.Values.Count - 1</b></code><code><b class="cfe">         subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j))</b></code><code><b class="cfe">         subkeyValue = Server.HtmlEncode(aCookie.Values(j))</b></code><code><b class="cfe">         output &amp;= "子键名称 = " &amp; subkeyName &amp; "&lt;br&gt;"</b></code><code><b class="cfe">         output &amp;= "子键值 = " &amp; subkeyValue &amp; "&lt;br&gt;&lt;br&gt;"</b></code><code><b class="cfe">     Next</b></code><code><b class="cfe">   Else</b></code>
     output &amp;= "值 = " &amp; Server.HtmlEncode(aCookie.Value) &amp; "&lt;br&gt;&lt;br&gt;"
   End If
Next
Label1.Text = output
</pre><p>您也可以把子键作为 <b>NameValueCollection</b> 对象进行提取，如下所示：</p><pre class="code">If aCookie.HasKeys Then
<code><b class="cfe">   Dim CookieValues As _</b></code><code><b class="cfe">      System.Collections.Specialized.NameValueCollection = aCookie.Values</b></code><code><b class="cfe">   Dim CookieValueNames() As String = CookieValues.AllKeys</b></code><code><b class="cfe">   For j = 0 To CookieValues.Count – 1</b></code><code><b class="cfe">      subkeyName = Server.HtmlEncode(CookieValueNames(j))</b></code><code><b class="cfe">      subkeyValue = Server.HtmlEncode(CookieValues(j))</b></code>
      output &amp;= "子键名称 = " &amp; subkeyName  &amp; "&lt;br&gt;"
      output &amp;= "子键值 = " &amp; subkeyValue &amp; "&lt;br&gt;&lt;br&gt;"
   Next
Else
   output &amp;= "值 = " &amp; aCookie.Value &amp; "&lt;br&gt;&lt;br&gt;"
End If
</pre><blockquote class="dtBlock"><b class="le">注意：</b>请记住，我之所以调用 <b>Server.HtmlEncode</b> 方法，只是因为我要在页面上显示 Cookie 的值。如果您只是测试 Cookie 的值，就不必在使用前对其进行编码。</blockquote><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor9"></a>修改和删除 Cookie</h2><p>有时，您可能需要修改某个 Cookie，更改其值或延长其有效期。（请记住，由于浏览器不会把有效期信息传递到服务器，所以您无法读取 Cookie 的过期日期。）</p><p>当然，实际上您并不是直接更改 Cookie。尽管您可以从 <b>Request.Cookies</b> 集合中获取 Cookie 并对其进行操作，但 Cookie 本身仍然存在于用户硬盘上的某个地方。因此，修改某个 Cookie 实际上是指用新的值创建新的 Cookie，并把该 Cookie 发送到浏览器，覆盖客户机上旧的 Cookie。</p><p>以下示例说明了如何更改用于储存站点访问次数的 Cookie 的值：</p><pre class="code">Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
    counter = 0
Else
    counter = CInt(Request.Cookies("counter").Value)
End If
counter += 1
Response.Cookies("counter").Value = counter.ToString
Response.Cookies("counter").Expires = DateTime.Now.AddDays(1)
</pre><p>或者：</p><pre class="code">Dim ctrCookie As HttpCookie
Dim counter As Integer
If Request.Cookies("counter") Is Nothing Then
    ctrCookie = New HttpCookie("counter")
Else
    ctrCookie = Request.Cookies("counter")
End If
counter = CInt(ctrCookie.Value) + 1
ctrCookie.Value = counter.ToString
ctrCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(ctrCookie)
</pre><h3 class="dtH3">删除 Cookie</h3><p>删除 Cookie（即把该 Cookie 从用户的硬盘上物理删除）是修改 Cookie 的一种形式。由于 Cookie 位于用户的计算机中，所以您无法直接将其删除。但是，您可以让浏览器为您删除 Cookie。修改 Cookie 的方法前面已经介绍过（即用相同的名称创建一个新的 Cookie），不同的是将其有效期设置为过去的某个日期。当浏览器检查 Cookie 的有效期时，就会删除这个已过期的 Cookie。</p><p>所以，删除 Cookie 的方法与创建该 Cookie 的方法是相同的，只不过要把其有效期设置为过去的某个日期。以下示例比删除单个 Cookie 要稍微有趣一些，它使用的方法可以删除当前域的所有 Cookie：</p><pre class="code">Dim i As Integer
Dim cookieName As String
Dim limit As Integer = Request.Cookies.Count - 1
For i = 0 To limit
   aCookie = Request.Cookies(i)
<code><b class="cfe">   aCookie.Expires = DateTime.Now.AddDays(-1)</b></code>
   Response.Cookies.Add(aCookie)
Next
</pre><h3 class="dtH3">修改或删除子键</h3><p>修改单个子键的方法与最初创建它的方法相同：</p><pre class="code">Response.Cookies("userInfo")("lastVisit") = DateTime.Now.ToString
Response.Cookies("userInfo").Expires = DateTime.Now.AddDays(1)
</pre><p>比较复杂的问题是如何删除单个子键。您不能只是简单地重新设置 Cookie 的过期日期，因为这样只能删除整个 Cookie 而不能删除单个子键。实际的解决方案是对包含子键的 Cookie 的 <b>Values</b> 集合进行操作。首先，通过从 <b>Request.Cookies</b> 对象中获取 Cookie 来重新创建 Cookie。然后，您就可以调用 <b>Values</b> 集合的 <b>Remove</b> 方法，将要删除的子键名称传递到 <b>Remove</b> 方法。接下来，您通常可以将修改后的 Cookie 添加到 <b>Response.Cookies</b> 集合，以便将修改后的 Cookie 发送回浏览器。</p><p>以下代码显示了如何删除子键。在示例中，要删除的子键的名称在变量中指定。</p><pre class="code">Dim subkeyName As String
subkeyName = "userName"
Dim aCookie As HttpCookie = Request.Cookies("userInfo")
aCookie.Values.Remove(subkeyName)
aCookie.Expires = DateTime.Now.AddDays(1)
Response.Cookies.Add(aCookie)
</pre><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor4"></a>Cookie 与安全性</h2><p>在使用 Cookie 时，您必须意识到其固有的安全弱点。我所指的安全性并不是隐私问题，正如我在前面的<a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor2" target="_self">什么是 Cookie？</a>中所述，隐私在更大程度上是某些用户面对的问题：这些用户很关心 Cookie 中的信息是如何被使用的。而 Cookie 的安全性问题与从客户机获取数据的安全性问题类似。对于初学者，就应用程序而言，Cookie 是用户输入的另一种形式，因而很容易被他人非法获取和利用。由于 Cookie 保存在用户自己的计算机上，所以用户至少可以看到您保存在 Cookie 中的信息。如果用户愿意，还能在浏览器向您发送 Cookie 之前修改该 Cookie。</p><p>所以，您千万不要在 Cookie 中保存保密信息 - 用户名、密码、信用卡号等等。在 Cookie 中不要保存不应该由用户掌握的内容，也不要保存可能被其他窃取 Cookie 的人控制的内容。</p><p>同样，要对从 Cookie 中得到的任何信息都持怀疑态度。不要认为得到的数据就是您当初设想的信息。处理 Cookie 值时采用的安全措施应该与处理 Web 页面中用户键入的数据时采用的安全措施相同。例如，在页面中显示值之前，我会对 Cookie 中的内容进行 HTML 编码。这是一种标准的方法，可以在显示之前净化从用户处得到的信息，对 Cookie 的处理与此相同。</p><p>另一个需要关心的问题是，Cookie 是以纯文本的形式在浏览器和服务器之间传送的，任何可以截取 Web 通信的人都可以读取 Cookie。您可以对 Cookie 的属性进行设置，使其只能在使用安全套接字层（SSL，又称 https://）的连接上传输。SSL 并不能防止保存在用户计算机上的 Cookie 被他人读取或操作，但它能防止 Cookie 在传输途中被他人截取。本文不讨论 SSL，但您必须清楚，您可以对 Cookie 进行传输保护。有关 SSL 的详细信息，请参阅 <a href="http://msdn.microsoft.com/msdnmag/issues/01/04/SSL/default.aspx">Secure Sockets Layer: Protect Your E-Commerce Web Site with SSL and Digital Certificates</a>（英文）。</p><p>面对这些安全问题，如何才能安全地使用 Cookie？您可以在 Cookie 中保存一些不重要的数据，如用户首选项或其他对应用程序没有重大影响的信息。如果确实需要把某些敏感信息（如用户 ID）保存在 Cookie 中，就对这些信息进行加密。一种可行的方法是利用 ASP.NET Forms Authentication 实用程序创建一个身份验证票据，作为 Cookie 保存。本文不讨论有关加密的问题，但是，如果您需要在 Cookie 中保存敏感信息，就应该试着采取措施来隐藏信息，防止被他人盗用。</p><p>在 <a href="http://www.microsoft.com/workshop/author/dhtml/httponly_cookies.asp">Mitigating Cross-site Scripting With HTTP-only Cookies</a>（英文）一文中，您可以了解到更多有关 Cookie 及其安全弱点的信息。</p><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor10"></a>检查浏览器是否接受 Cookie</h2><p>我在前面的 <a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor3" target="_self">Cookie 的限制</a>一节中曾经提到一个潜在问题，即用户可以设置自己的浏览器拒绝接受 Cookie。如何才能知道您是否可以读写 Cookie？在不能写入 Cookie 时不会出现任何错误（例如 <b>Response.Cookies</b> 不会抛出异常），因为服务器并不跟踪呈现页面后出现的情况。浏览器同样不会向服务器发送任何有关其当前的 Cookie 设置的信息。（也许您需要了解，但 <a href="http://www.microsoft.com/msdn/library/en-us/cpref/html/frlrfSystemWebHttpBrowserCapabilitiesClassCookiesTopic.asp">HttpBrowserCapabilities.Cookies Property</a> [英文] 属性并不会告诉您 Cookie 是否被启用，而只能告诉您当前的浏览器是否支持 Cookie。）</p><p>一种确定浏览器是否接受 Cookie 的方法是先编写一个 Cookie，然后再尝试读取这个 Cookie。如果不能读取这个 Cookie，则可以认为该浏览器不接受 Cookie。</p><p>我编写了一个简单的示例来说明如何测试 Cookie 是否被接受。该示例包含两个页面。在第一个页面中，我编写了一个 Cookie，然后把浏览器重新定向到第二个页面。第二个页面尝试读取这个 Cookie，转而将浏览器重新定向到第一个页面，并向 URL 添加一个带有测试结果的查询字符串变量。</p><p>第一个页面的代码如下：</p><pre class="code">Sub Page_Load()
   If Not Page.IsPostBack Then
      If Request.QueryString("AcceptsCookies") Is Nothing Then
           Response.Cookies("TestCookie").Value = "ok"
           Response.Cookies("TestCookie").Expires = _
              DateTime.Now.AddMinutes(1)
           Response.Redirect("TestForCookies.aspx?redirect=" &amp; _
              Server.UrlEncode(Request.Url.ToString))
      Else
           labelAcceptsCookies.Text = "接受 Cookie = " &amp; _
              Request.QueryString("AcceptsCookies")
      End If
   End If
End Sub
</pre><p>第一个页面测试是否有回信，如果没有，就搜索包含测试结果的查询字符串变量 (<code class="ce">AcceptsCookies</code>)。如果没有找到查询字符串变量，则表示测试还没有完成，代码就写出一个名为“TestCookie”的 Cookie。写出 Cookie 之后，示例调用 <b>Response.Redirect</b> 来切换到测试页面 (TestForCookies.aspx)。附加到测试页面的 URL 的是名为 <code class="ce">redirect</code> 的查询字符串变量，该变量中包含了当前页面的 URL，这样就能在执行测试后把重定向到该页面。</p><p>测试页面可以完全由代码组成，不需要包含控件。以下就是我使用的代码：</p><pre class="code">Sub Page_Load()
    Dim redirect As String = Request.QueryString("redirect")
    Dim acceptsCookies As String
    ' 是否接受 Cookie？
    If Request.Cookies("TestCookie") Is Nothing Then
        ' 没有 Cookie，因此不需要接受
        acceptsCookies = 0
    Else
        acceptsCookies = 1
        ' 删除测试 Cookie
        Response.Cookies("TestCookie").Expires = _
           DateTime.Now.AddDays(-1)
    End If
    Response.Redirect(redirect &amp; "?AcceptsCookies=" &amp; acceptsCookies, _
       True)
End Sub
</pre><p>读取 <code class="ce">redirect</code> 查询字符串变量后，代码就尝试读取 Cookie。为了实现日常管理，如果该 Cookie 确实存在，就会被立即删除。测试完成后，代码从 <code class="ce">redirect</code> 查询字符串变量传递的 URL 构造一个新的 URL。新的 URL 也包括一个包含测试结果的查询字符串变量。最后一步是使用新的 URL 将浏览器重定向到原来的页面。</p><p>这个示例十分简单，但说明了通过运行程序并查看结果来进行测试的基本原则。其中最需要改进的地方是要永久保存 Cookie 测试结果，这样用户就不必在每次浏览原始页面时都重复进行测试。但是，实际上并不能做到这一点。Cookie 不会起作用，原因是显而易见的。另一种可能是把测试结果保存在会话状态中，但在默认情况下，会话状态也依赖于 Cookie，而如果浏览器不接受 Cookie，会话状态也不会起作用。解决后一个问题的办法是采用无 Cookie 的会话状态。下一节我将简要介绍会话状态如何与 Cookie 协作。</p><h2 class="dtH2"><a name="vbtchaspnetcookies101anchor11"></a>Cookie 和会话状态</h2><p>当用户访问您的站点时，服务器会为该用户创建唯一的会话，会话将一直延续到用户访问结束。对于每个会话，ASP.NET 都维护一种基于服务器的结构（会话状态），在该结构中应用程序可以保存用户的相关信息。有关详细信息，请参阅 <a href="http://www.microsoft.com/msdn/library/en-us/cpguide/html/cpconsessionstate.asp">Session State</a>（英文）。</p><p>ASP.NET 需要能跟踪每个用户的会话 ID，这样才能把用户映射到服务器上的会话状态信息。默认情况下，ASP.NET 使用一个非永久性的 Cookie 来保存会话状态。如果您使用<a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor8" target="_self">读取 Cookie</a> 一节的“读取 Cookie 集合”中的示例，您可能就会在 Cookie 中发现一个会话状态 Cookie。</p><p>但是如果用户禁用了浏览器的 Cookie，会话状态就不能使用 Cookie 来保存会话 ID，会话状态也不会起作用。这就是为什么我在前面的<a href="http://www.microsoft.com/china/MSDN/library/archives/library/dv_vstechart/html/vbtchaspnetcookies101.asp#vbtchaspnetcookies101anchor10" target="_self">检查浏览器是否接受 Cookie</a> 中说，无法在 Cookie 测试完毕后把测试结果实际保存在会话状态中，因为没有 Cookie 就没有会话状态。</p><p>ASP.NET 提供了一种解决方案，即利用无 Cookie 的会话。您可以配置自己的应用程序，不在 Cookie 中保存会话 ID，而是在站点页面的 URL 中保存。会话 ID 保存在 URL 中，也就是 ASP.NET 将 ID 保存在浏览器中，从而能够在用户请求其他页面时取回 ID。</p><p>无 Cookie 会话可以避免浏览器拒绝 Cookie 的问题，使您能够使用会话状态。如果您的应用程序依赖于会话状态，您可能就需要对其进行配置，使它能使用无 Cookie 会话。但是，在某些情况下，如果用户与其他人共享 URL - 可能是用户通过电子邮件将 URL 发送给同事，而该用户的会话仍然处于激活状态 - 那么最终这两个用户可能共享同一个会话，结果将难以预料。</p><p>有关配置应用程序以使用无 Cookie 会话的详细信息，请参阅 Knowledge Base 中的文章 <a href="http://support.microsoft.com/default.aspx?scid=kb;en-us;307598">INFO: ASP.NET State Management Overview</a>（英文）。</p><img src ="http://www.blogjava.net/Daniel2005/aggbug/50424.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-06-05 09:51 <a href="http://www.blogjava.net/Daniel2005/articles/50424.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET中Cookie编程的基础知识-读取 Cookie 集合</title><link>http://www.blogjava.net/Daniel2005/articles/46562.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Wed, 17 May 2006 02:27:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/46562.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/46562.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/46562.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/46562.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/46562.html</trackback:ping><description><![CDATA[前面的示例假设您要读取名称已知的 Cookie。有时，您可能需要读取可供页面使用的所有 Cookie。要读取可供页面使用的所有 Cookie 的名称和值，您可以利用如下代码遍历 Request.Cookies 集合：
<p>Dim i As Integer<br />Dim output As String = ""<br />Dim aCookie As HttpCookie<br />For i = 0 to Request.Cookies.Count - 1<br />aCookie = Request.Cookies(i)<br />output &amp;= "Cookie 名称 = " &amp; Server.HtmlEncode(aCookie.Name) &amp; "&lt;br&gt;"<br />output &amp;= "Cookie 值 = " &amp; Server.HtmlEncode(aCookie.Value) &amp; _<br />&amp; "&lt;br&gt;&lt;br&gt;"<br />Next <br />Label1.Text = output </p><p>　　注意：运行此代码时，您很可能会看到一个名为“ASP.NET_SessionId”的 Cookie，ASP.NET 用这个 Cookie 来保存您的会话的唯一标识符。这个会话 Cookie 不会永久保存到您的硬盘上。有关会话 Cookie 的详细信息，请参阅本文后面的 Cookie 和会话状态。<br />前面的示例有一个限制：如果 Cookie 有子键，就会以一个单独的名称/值字符串来显示子键。Cookie 的 HasKeys（英文）属性可以告诉您该 Cookie 是否有子键。如果有子键，您可以在子键集合中向下钻取，获取各个子键的名称和值。</p><p>　　如前文所述，您可以从 Cookie 属性 Values（英文）中获取有关子键的信息，该属性是类型 NameValueCollection 的集合。您可以根据索引值从 Values 集合中直接读取子键值。相应的子键值可以从 Values 集合的成员 AllKeys（英文）中得到，该成员将返回一个字符串集合。</p><p>　　以下示例是对前一示例的修改。示例中使用 HasKeys 属性来测试子键，如果检测到子键，就从 Values 集合中获取子键：</p><p>Dim i As Integer<br />Dim j As Integer<br />Dim output As String = ""<br />Dim aCookie As HttpCookie<br />Dim subkeyName As String<br />Dim subkeyValue As String<br />For i = 0 To Request.Cookies.Count - 1<br />aCookie = Request.Cookies(i)<br />output &amp;= "名称 = " &amp; aCookie.Name &amp; "&lt;br&gt;"<br />If aCookie.HasKeys Then<br />For j = 0 To aCookie.Values.Count - 1<br />subkeyName = Server.HtmlEncode(aCookie.Values.AllKeys(j))<br />subkeyValue = Server.HtmlEncode(aCookie.Values(j))<br />output &amp;= "子键名称 = " &amp; subkeyName &amp; "&lt;br&gt;"<br />output &amp;= "子键值 = " &amp; subkeyValue &amp; "&lt;br&gt;&lt;br&gt;"<br />Next<br />Else<br />output &amp;= "值 = " &amp; Server.HtmlEncode(aCookie.Value) &amp; "&lt;br&gt;&lt;br&gt;"<br />End If<br />Next<br />Label1.Text = output </p><p>　　您也可以把子键作为 NameValueCollection 对象进行提取，如下所示：</p><p>If aCookie.HasKeys Then<br />Dim CookieValues As _<br />System.Collections.Specialized.NameValueCollection = aCookie.Values<br />Dim CookieValueNames() As String = CookieValues.AllKeys<br />For j = 0 To CookieValues.Count – 1<br />subkeyName = Server.HtmlEncode(CookieValueNames(j))<br />subkeyValue = Server.HtmlEncode(CookieValues(j))<br />output &amp;= "子键名称 = " &amp; subkeyName &amp; "&lt;br&gt;"<br />output &amp;= "子键值 = " &amp; subkeyValue &amp; "&lt;br&gt;&lt;br&gt;"<br />Next<br />Else<br />output &amp;= "值 = " &amp; aCookie.Value &amp; "&lt;br&gt;&lt;br&gt;"<br />End If </p><p>　　注意：请记住，我之所以调用 Server.HtmlEncode 方法，只是因为我要在页面上显示 Cookie 的值。如果您只是测试 Cookie 的值，就不必在使用前对其进行编码。</p><p>　　修改和删除 Cookie</p><p>　　有时，您可能需要修改某个 Cookie，更改其值或延长其有效期。（请记住，由于浏览器不会把有效期信息传递到服务器，所以您无法读取 Cookie 的过期日期。）</p><p>　　当然，实际上您并不是直接更改 Cookie。尽管您可以从 Request.Cookies 集合中获取 Cookie 并对其进行操作，但 Cookie 本身仍然存在于用户硬盘上的某个地方。因此，修改某个 Cookie 实际上是指用新的值创建新的 Cookie，并把该 Cookie 发送到浏览器，覆盖客户机上旧的 Cookie。</p><p>　　以下示例说明了如何更改用于储存站点访问次数的 Cookie 的值：</p><p>Dim counter As Integer<br />If Request.Cookies("counter") Is Nothing Then<br />counter = 0<br />Else<br />counter = CInt(Request.Cookies("counter").Value)<br />End If<br />counter += 1<br />Response.Cookies("counter").Value = counter.ToString<br />Response.Cookies("counter").Expires = DateTime.Now.AddDays(1)  </p><p>　　或者：</p><p>Dim ctrCookie As HttpCookie<br />Dim counter As Integer<br />If Request.Cookies("counter") Is Nothing Then<br />ctrCookie = New HttpCookie("counter")<br />Else<br />ctrCookie = Request.Cookies("counter")<br />End If<br />counter = CInt(ctrCookie.Value) + 1<br />ctrCookie.Value = counter.ToString<br />ctrCookie.Expires = DateTime.Now.AddDays(1)<br />Response.Cookies.Add(ctrCookie) <br /></p><img src ="http://www.blogjava.net/Daniel2005/aggbug/46562.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-05-17 10:27 <a href="http://www.blogjava.net/Daniel2005/articles/46562.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Asp.net2.0发邮件</title><link>http://www.blogjava.net/Daniel2005/articles/38837.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Mon, 03 Apr 2006 02:17:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/38837.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/38837.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/38837.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/38837.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/38837.html</trackback:ping><description><![CDATA[
		<p>这是一个后台发mail的类 ,用在 <a href="http://bugonline.org/">http://BugOnline.org</a> 网站上，在系统中使用的很好，特拿出来共享。<br />用的是.net framework 2.0.<br /><br />其中用到了.net2.0最新的System.Net.Mail空间，比.net 1.1好用多了。<br />还有线程类。有兴趣的朋友可以看看。<br /><br />using System;<br />using System.Collections.Generic;<br />using System.Collections.ObjectModel;<br />using System.Text;<br />using System.Net.Mail;<br />using System.Net;</p>
		<p>using System.Threading;</p>
		<p>namespace com.XXX.SPMS.Common<br />{<br />    /// &lt;summary&gt;<br />    /// Mail 多进程发mail<br />    /// &lt;/summary&gt;<br />    public class Mail<br />    {<br />        private string subject;<br />        private string body;<br />        private string[] mailTo;</p>
		<p>        /// &lt;summary&gt;<br />        /// Mail<br />        /// &lt;/summary&gt;<br />        /// &lt;param name="mailTo"&gt;&lt;/param&gt;<br />        /// &lt;param name="subject"&gt;&lt;/param&gt;<br />        /// &lt;param name="body"&gt;&lt;/param&gt;<br />        public Mail(string[] mailTo, string subject, string body)<br />        {<br />            this.mailTo = mailTo;<br />            this.subject = subject;<br />            this.body = body;<br />        }</p>
		<p>        /// &lt;summary&gt;<br />        /// Send a mail no MultiThread<br />        /// &lt;/summary&gt;<br />        /// &lt;returns&gt;&lt;/returns&gt;<br />        public void Send()<br />        {<br />            Send(mailTo, subject, body);<br />        }</p>
		<p>        /// &lt;summary&gt;<br />        /// Send a mail MultiThread<br />        /// &lt;/summary&gt;<br />        /// &lt;param name="mailTo"&gt;&lt;/param&gt;<br />        /// &lt;param name="subject"&gt;&lt;/param&gt;<br />        /// &lt;param name="body"&gt;&lt;/param&gt;<br />        /// &lt;returns&gt;&lt;/returns&gt;<br />        public static void SendAtBackground(string[] mailTo, string subject, string body)<br />        {<br />            Mail newMail = new Mail(mailTo, subject, body);<br />            Thread thread = new Thread(new ThreadStart(newMail.Send));<br />            thread.Start();<br />        }</p>
		<p>        /// &lt;summary&gt;<br />        /// Send<br />        /// &lt;/summary&gt;<br />        /// &lt;returns&gt;&lt;/returns&gt;<br />        private static bool Send(string[] mailTo, string subject, string body)<br />        {<br />            MailMessage msg = new MailMessage();<br />            try<br />            {<br />                msg.From = new MailAddress(SPMSConfiguration.MailSender);</p>
		<p>                foreach (string address in mailTo)<br />                {<br />                    msg.To.Add(address);<br />                }</p>
		<p>                msg.Subject = subject;<br />                msg.Body = body;</p>
		<p>                System.Net.Mail.SmtpClient smtp = new SmtpClient(SPMSConfiguration.SmtpServer);<br />                smtp.Credentials = new NetworkCredential(SPMSConfiguration.SmtpCredential, SPMSConfiguration.CredentialPassword);</p>
		<p>                smtp.Send(msg);<br />            }<br />            catch (Exception)<br />            {<br />            }<br />            return true;<br />        }<br />    }<br />}</p>
<img src ="http://www.blogjava.net/Daniel2005/aggbug/38837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-04-03 10:17 <a href="http://www.blogjava.net/Daniel2005/articles/38837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ArrayList的用法!</title><link>http://www.blogjava.net/Daniel2005/articles/34859.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Sat, 11 Mar 2006 13:13:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/34859.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/34859.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/34859.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/34859.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/34859.html</trackback:ping><description><![CDATA[1、什么是ArrayList<BR>ArrayList就是传说中的动态数组，用MSDN中的说法，就是Array的复杂版本，它提供了如下一些好处：<BR><BR>动态的增加和减少元素<BR><BR>实现了ICollection和IList接口<BR><BR>灵活的设置数组的大小<BR><BR>2、如何使用ArrayList<BR>最简单的例子：<BR>ArrayList List = new ArrayList();<BR>for( int i=0;i&lt;10;i++ ) //给数组增加10个Int元素<BR>List.Add(i); <BR>//..程序做一些处理<BR>List.RemoveAt(5);//将第6个元素移除<BR>for( int i=0;i&lt;3;i++ ) //再增加3个元素<BR>List.Add(i+20);<BR>Int32[] values = (Int32[])List.ToArray(typeof(Int32));//返回ArrayList包含的数组<BR><BR>这是一个简单的例子，虽然没有包含ArrayList所有的方法，但是可以反映出ArrayList最常用的用法<BR><BR>3、ArrayList重要的方法和属性<BR>（1）构造器<BR>ArrayList提供了三个构造器：<BR>public ArrayList();<BR>默认的构造器，将会以默认（16）的大小来初始化内部的数组<BR>public ArrayList(ICollection);<BR>用一个ICollection对象来构造，并将该集合的元素添加到ArrayList<BR>public ArrayList(int);<BR>用指定的大小来初始化内部的数组<BR><BR>（2）IsSynchronized属性和ArrayList.Synchronized方法<BR>IsSynchronized属性指示当前的ArrayList实例是否支持线程同步，而ArrayList.Synchronized静态方法则会返回一个ArrayList的线程同步的封装。<BR>如果使用非线程同步的实例，那么在多线程访问的时候，需要自己手动调用lock来保持线程同步，例如：<BR>ArrayList list = new ArrayList();<BR>//...<BR>lock( list.SyncRoot ) //当ArrayList为非线程包装的时候，SyncRoot属性其实就是它自己，但是为了满足ICollection的SyncRoot定义，这里还是使用SyncRoot来保持源代码的规范性<BR>{<BR>list.Add( “Add a Item” );<BR>}<BR><BR>如果使用ArrayList.Synchronized方法返回的实例，那么就不用考虑线程同步的问题，这个实例本身就是线程安全的，实际上ArrayList内部实现了一个保证线程同步的内部类，ArrayList.Synchronized返回的就是这个类的实例，它里面的每个属性都是用了lock关键字来保证线程同步。<BR><BR>****<BR><BR>但是，使用这个方法（ArrayList.Synchronized）并不能保证枚举的同步，例如，一个线程正在删除或添加集合项，而另一个线程同时进行枚举，这时枚举将会抛出异常。所以，在枚举的时候，你必须明确使用 SyncRoot 锁定这个集合。<BR><BR><BR><BR>Hashtable与ArrayList关于线程安全性的使用方法类似。<BR><BR>****<BR><BR>（3）Count属性和Capacity属性<BR>Count属性是目前ArrayList包含的元素的数量，这个属性是只读的。<BR>Capacity属性是目前ArrayList能够包含的最大数量，可以手动的设置这个属性，但是当设置为小于Count值的时候会引发一个异常。<BR><BR>（4）Add、AddRange、Remove、RemoveAt、RemoveRange、Insert、InsertRange<BR>这几个方法比较类似<BR>Add方法用于添加一个元素到当前列表的末尾<BR>AddRange方法用于添加一批元素到当前列表的末尾<BR>Remove方法用于删除一个元素，通过元素本身的引用来删除<BR>RemoveAt方法用于删除一个元素，通过索引值来删除<BR>RemoveRange用于删除一批元素，通过指定开始的索引和删除的数量来删除<BR>Insert用于添加一个元素到指定位置，列表后面的元素依次往后移动<BR>InsertRange用于从指定位置开始添加一批元素，列表后面的元素依次往后移动<BR><BR>另外，还有几个类似的方法：<BR>Clear方法用于清除现有所有的元素<BR>Contains方法用来查找某个对象在不在列表之中<BR><BR>其他的我就不一一累赘了，大家可以查看MSDN，上面讲的更仔细<BR>（5）TrimSize方法<BR>这个方法用于将ArrayList固定到实际元素的大小，当动态数组元素确定不在添加的时候，可以调用这个方法来释放空余的内存。<BR>（6）ToArray方法<BR>这个方法把ArrayList的元素Copy到一个新的数组中。<BR><BR>4、ArrayList与数组转换<BR>例1：<BR>ArrayList List = new ArrayList();<BR>List.Add(1);<BR>List.Add(2);<BR>List.Add(3);<BR><BR>Int32[] values = (Int32[])List.ToArray(typeof(Int32));<BR><BR>例2：<BR>ArrayList List = new ArrayList();<BR>List.Add(1);<BR>List.Add(2);<BR>List.Add(3);<BR><BR>Int32[] values = new Int32[List.Count];<BR>List.CopyTo(values);<BR><BR>上面介绍了两种从ArrayList转换到数组的方法<BR><BR>例3：<BR>ArrayList List = new ArrayList();<BR>List.Add( “string” );<BR>List.Add( 1 );<BR>//往数组中添加不同类型的元素<BR><BR>object[] values = List.ToArray(typeof(object)); //正确<BR>string[] values = (string[])List.ToArray(typeof(string)); //错误<BR><BR>和数组不一样，因为可以转换为Object数组，所以往ArrayList里面添加不同类型的元素是不会出错的，但是当调用ArrayList方法的时候，要么传递所有元素都可以正确转型的类型或者Object类型，否则将会抛出无法转型的异常。<BR><BR>5、ArrayList最佳使用建议<BR>这一节我们来讨论ArrayList与数组的差别，以及ArrayList的效率问题<BR>（1）ArrayList是Array的复杂版本<BR>ArrayList内部封装了一个Object类型的数组，从一般的意义来说，它和数组没有本质的差别，甚至于ArrayList的许多方法，如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。<BR>（2）内部的Object类型的影响<BR>对于一般的引用类型来说，这部分的影响不是很大，但是对于值类型来说，往ArrayList里面添加和修改元素，都会引起装箱和拆箱的操作，频繁的操作可能会影响一部分效率。<BR>但是恰恰对于大多数人，多数的应用都是使用值类型的数组。<BR>消除这个影响是没有办法的，除非你不用它，否则就要承担一部分的效率损失，不过这部分的损失不会很大。<BR>（3）数组扩容<BR>这是对ArrayList效率影响比较大的一个因素。<BR>每当执行Add、AddRange、Insert、InsertRange等添加元素的方法，都会检查内部数组的容量是否不够了，如果是，它就会以当前容量的两倍来重新构建一个数组，将旧元素Copy到新数组中，然后丢弃旧数组，在这个临界点的扩容操作，应该来说是比较影响效率的。<BR>例1：比如，一个可能有200个元素的数据动态添加到一个以默认16个元素大小创建的ArrayList中，将会经过：<BR>16*2*2*2*2 = 256<BR>四次的扩容才会满足最终的要求，那么如果一开始就以：<BR>ArrayList List = new ArrayList( 210 );<BR>的方式创建ArrayList，不仅会减少4次数组创建和Copy的操作，还会减少内存使用。<BR><BR>例2：预计有30个元素而创建了一个ArrayList：<BR>ArrayList List = new ArrayList(30);<BR>在执行过程中，加入了31个元素，那么数组会扩充到60个元素的大小，而这时候不会有新的元素再增加进来，而且有没有调用TrimSize方法，那么就有1次扩容的操作，并且浪费了29个元素大小的空间。如果这时候，用：<BR>ArrayList List = new ArrayList(40);<BR>那么一切都解决了。<BR>所以说，正确的预估可能的元素，并且在适当的时候调用TrimSize方法是提高ArrayList使用效率的重要途径。<BR>（4）频繁的调用IndexOf、Contains等方法（Sort、BinarySearch等方法经过优化，不在此列）引起的效率损失<BR>首先，我们要明确一点，ArrayList是动态数组，它不包括通过Key或者Value快速访问的算法，所以实际上调用IndexOf、Contains等方法是执行的简单的循环来查找元素，所以频繁的调用此类方法并不比你自己写循环并且稍作优化来的快，如果有这方面的要求，建议使用Hashtable或SortedList等键值对的集合。<BR>ArrayList al=new ArrayList();<BR><BR>al.Add("How");<BR>al.Add("are");<BR>al.Add("you!");<BR><BR>al.Add(100);<BR>al.Add(200);<BR>al.Add(300);<BR><BR>al.Add(1.2);<BR>al.Add(22.8);<BR><BR>.........<BR><BR>//第一种遍历 ArrayList 对象的方法<BR>foreach(object o in al)<BR>{<BR>Console.Write(o.ToString()+" ");<BR>}<BR><BR>//第二种遍历 ArrayList 对象的方法<BR>IEnumerator ie=al.GetEnumerator();<BR>while(ie.MoveNext())<BR>{<BR>Console.Write(ie.Curret.ToString()+" ");<BR>}<BR><BR>//第三种遍历 ArrayList 对象的方法<BR>我忘记了,好象是 利用 ArrayList对象的一个属性,它返回一此对象中的元素个数.<BR><BR>然后在利用索引 <BR>for(int i=0;i&lt;Count;i++)<BR>{<BR>Console.Write(al[i].ToString()+" ");<BR><img src ="http://www.blogjava.net/Daniel2005/aggbug/34859.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-03-11 21:13 <a href="http://www.blogjava.net/Daniel2005/articles/34859.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>广告传动的使用</title><link>http://www.blogjava.net/Daniel2005/articles/34858.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Sat, 11 Mar 2006 13:08:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/34858.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/34858.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/34858.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/34858.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/34858.html</trackback:ping><description><![CDATA[&lt;marquee id=mrqNews scrollAmount=2 onmouseover=stop() width=40% onmouseout=start()&gt;我是陈涛&lt;/marquee&gt;<BR>加入到body之间<img src ="http://www.blogjava.net/Daniel2005/aggbug/34858.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-03-11 21:08 <a href="http://www.blogjava.net/Daniel2005/articles/34858.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[ASP]GetRows的用法详解！</title><link>http://www.blogjava.net/Daniel2005/articles/30551.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 14 Feb 2006 02:24:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/30551.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/30551.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/30551.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/30551.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/30551.html</trackback:ping><description><![CDATA[<P>大家应该都知道&nbsp;Recordset&nbsp;有个&nbsp;GetRows&nbsp;属性，但是真正使用的不多，我也是最近才用的！汗……</P>
<P>其实这个属性很简单，就是把数据集输出到一个数组中。但是实用性可不小，在这里我举一个例子说明一下GetRows的使用方法，大家举一反三能想到更多的用法！</P>
<P>比如一个分类的表&nbsp;T_Cate，结构和数据如下：</P>
<P>ID&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;Title&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;Intro<BR>-----------------------------------------<BR>1&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;新闻&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;这里是新闻<BR>2&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;教程&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;这里是教程<BR>3&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;下载&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;这里是下载</P>
<P>好了，表建立好了，数据也有了，下面我们就要用到GetRows咯！ </P>
<P>
<P><SPAN class=code style="WIDTH: 502px; HEIGHT: 124px"></P>
<P>
<P>Dim&nbsp;Rs_Cate<BR>Dim&nbsp;Arr_Cate<BR>Set&nbsp;Rs_Cate=Conn.ExeCute("SELECT&nbsp;ID,Title,Intro&nbsp;FROM&nbsp;T_Cate&nbsp;ORDER&nbsp;BY&nbsp;ID&nbsp;ASC")<BR>Arr_Cate=Rs_Cate.GetRows<BR>Set&nbsp;Rs_Cate=Nothing</P></SPAN>
<P></P>
<P>好了表数据已经导出到数组了！下面我们将遍历这个数组</P>
<P><SPAN class=code style="WIDTH: 512px; HEIGHT: 138px"></P>
<P>Dim&nbsp;Arr_CateNumS,Arr_CateNumI<BR>Arr_CateNumS=Ubound(Arr_Cate,2)&nbsp;&nbsp;'得到数组中数据的下标<BR>For&nbsp;Arr_CateNumI=0&nbsp;To&nbsp;Arr_CateNumS<BR>&nbsp;&nbsp;&nbsp;&nbsp;Response.Write("ID："&amp;Arr_Cate(0,Arr_CateNumI)&amp;"&nbsp;|&nbsp;标题："&amp;Arr_Cate(1,Arr_CateNumI)&amp;"&nbsp;|&nbsp;介绍："&amp;Arr_Cate(2,Arr_CateNumI)&amp;"&lt;br&gt;")<BR>Next</P></SPAN>
<P></P>
<P>呵呵，好了，输出的数据为：<BR>ID：1&nbsp;|&nbsp;标题：新闻&nbsp;|&nbsp;介绍：这里是新闻<BR>ID：2&nbsp;|&nbsp;标题：教程&nbsp;|&nbsp;介绍：这里是教程<BR>ID：3&nbsp;|&nbsp;标题：下载&nbsp;|&nbsp;介绍：这里是下载</P>
<P>好了，具体就写这么多吧！文采不行，如果大家有什么不明白的，多用用就可以了，呵呵<BR><BR><BR><BR><BR></P>
<P>The GetRows method copies multiple records from a Recordset object into a two-dimensional array.</P>
<H3>Syntax</H3>
<P>
<TABLE class=ex cellSpacing=0 cellPadding=3 width="100%" border=1>
<TBODY>
<TR>
<TD vAlign=top><PRE>vararray=objRecordset.GetRows(rows,start,fields)</PRE></TD></TR></TBODY></TABLE><BR>
<TABLE class=ex cellSpacing=0 cellPadding=3 width="100%" border=1>
<TBODY>
<TR>
<TH vAlign=top align=left width="20%">Parameter</TH>
<TH vAlign=top align=left width="80%">Description</TH></TR>
<TR>
<TD vAlign=top>rows</TD>
<TD vAlign=top>Optional. A <A href="http://www.w3schools.com/ado/met_rs_getrows.asp#getrowsoptionenum">GetRowsOptionEnum</A> value that specifies the number of records to retrieve. Default is adGetRowsRest. 
<P><B>Note:</B> If you omit this argument it will retrieve all records in the Recordset</P></TD></TR>
<TR>
<TD vAlign=top>start</TD>
<TD vAlign=top>
<P>Optional. What record to start on, a record number or a <A href="http://www.w3schools.com/ado/met_rs_getrows.asp#bookmarkenum">BookmarkEnum</A> value</P></TD></TR>
<TR>
<TD vAlign=top>fields</TD>
<TD vAlign=top>Optional. If you want to specify only the fields that the GetRows call will return, it is possible to pass a single field name/number or an array of field names/numbers in this argument </TD></TR></TBODY></TABLE></P>
<H3>Example</H3>
<P>
<TABLE class=ex cellSpacing=0 cellPadding=3 width="100%" border=1>
<TBODY>
<TR>
<TD vAlign=top><PRE>&lt;%
set conn=Server.CreateObject("ADODB.Connection")
conn.Provider="Microsoft.Jet.OLEDB.4.0"
conn.Open(Server.Mappath("northwind.mdb"))
set rs = Server.CreateObject("ADODB.recordset")
rs.Open "Select * from Customers", conn

'The first number indicates how many records to copy
'The second number indicates what recordnumber to start on
p=rs.GetRows(2,0)
rs.close
conn.close</PRE><PRE>'This example returns the value of the first
'column in the first two records
response.write(p(0,0))
response.write("&lt;br&gt;")
response.write(p(0,1))

'This example returns the value of the first
'three columns in the first record
response.write(p(0,0))
response.write("&lt;br&gt;")
response.write(p(1,0))
response.write("&lt;br&gt;")
response.write(p(2,0))
%&gt;</PRE></TD></TR></TBODY></TABLE></P><img src ="http://www.blogjava.net/Daniel2005/aggbug/30551.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-02-14 10:24 <a href="http://www.blogjava.net/Daniel2005/articles/30551.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UploadFile函数上传文件到Server的某文件夹下</title><link>http://www.blogjava.net/Daniel2005/articles/27333.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 10 Jan 2006 01:08:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/27333.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/27333.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/27333.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/27333.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/27333.html</trackback:ping><description><![CDATA[<P><FONT color=#0000ff>Private Const IMAGEURL As String = "Images"<BR>Private Const IMAGENAME As String = "logo.gif"<BR>&nbsp;&nbsp;&nbsp; <BR>Private Function UploadFile(ByVal FileName As String) As Int16</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Dim file As String<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If FileName &lt;&gt; "" Then<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file = FileName<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If file.Substring(file.Length - 4).ToLower &lt;&gt; ".gif" Then<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write("&lt;script language=javascript&gt;alert('Please select the .GIF file!');&lt;/script&gt;")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Exit Function<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Else</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file = ""<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If FileName &lt;&gt; "" Then<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; file = FileName</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'upload files<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Try</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; browse.PostedFile.SaveAs(Server.MapPath(".\" &amp; Me.IMAGEURL &amp; "\") &amp; Me.IMAGENAME)&nbsp; 'Me.EXTENSION)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 'browse.PostedFile.SaveAs(Server.MapPath(file))&nbsp; 'Me.EXTENSION)</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Catch ex As Exception</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return 0<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Exit Function</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Finally</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End Try</FONT></P>
<P><BR><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Return 1</FONT></P>
<P><FONT color=#0000ff>&nbsp;&nbsp;&nbsp; End Function</FONT></P><img src ="http://www.blogjava.net/Daniel2005/aggbug/27333.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2006-01-10 09:08 <a href="http://www.blogjava.net/Daniel2005/articles/27333.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>格式化 DataGrid 输出</title><link>http://www.blogjava.net/Daniel2005/articles/22253.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Fri, 02 Dec 2005 07:50:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/22253.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/22253.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/22253.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/22253.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/22253.html</trackback:ping><description><![CDATA[在这个论坛中，我看到了大量的关于如何在DataGrid中格式化显示数据的问题。人们想知道在特殊情况下，怎样改变某行的颜色，文字或基本的显示值 。 在这篇文章中，我将使用两种不同的技术向您演示如何修改您的数据的输出格式。我将向你展示怎样使用helper函数来改变数据数据显示格式。在这之后，我将解释怎样使用DataGrid的<SPAN class=CodeInText>OnItemDataBound事件来修改DataGrid的数据并格式化显示它。</SPAN>
<P class=SubHeading><B>计划</B></P>
<P>首先，我设计了这个示例中的数据文件，它是一个简单的关于联系人的XML文件。我的DataGird中的显示需求包括：</P>
<UL>
<LI>合并首尾姓名。 
<LI>如果Manager的值是1或Employee的值是0时改变Manager的显示方式。 
<LI>如果Manager字段中有任一一行的值是1，则改变该行的背景色。</LI></UL>
<P class=CodeTable>&lt;?xml version="1.0" standalone="yes"?&gt;<BR>&lt;Contacts&gt;<BR>&nbsp;&nbsp;&lt;Contact&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Email&gt;myaddress@mycompany.com&lt;/Email&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;FirstName&gt;John&lt;/FirstName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;LastName&gt;Doe&lt;/LastName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Manager&gt;0&lt;/Manager&gt;<BR>&nbsp;&nbsp;&lt;/Contact&gt;<BR>&nbsp;&nbsp;&lt;Contact&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Email&gt;youraddress@yourcompany.com&lt;/Email&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;FirstName&gt;Jane&lt;/FirstName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;LastName&gt;Doe&lt;/LastName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Manager&gt;1&lt;/Manager&gt;<BR>&nbsp;&nbsp;&lt;/Contact&gt;<BR>&nbsp;&nbsp;&lt;Contact&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Email&gt;fred@bedrock.com&lt;/Email&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;FirstName&gt;Fred&lt;/FirstName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;LastName&gt;Flintstone&lt;/LastName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Manager&gt;0&lt;/Manager&gt;<BR>&nbsp;&nbsp;&lt;/Contact&gt;<BR>&nbsp;&nbsp;&lt;Contact&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Email&gt;barney@bedrock.com&lt;/Email&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;FirstName&gt;Barney&lt;/FirstName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;LastName&gt;Rubble&lt;/LastName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Manager&gt;0&lt;/Manager&gt;<BR>&nbsp;&nbsp;&lt;/Contact&gt;<BR>&nbsp;&nbsp;&lt;Contact&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Email&gt;slate@bedrock.com&lt;/Email&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;FirstName&gt;Mr&lt;/FirstName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;LastName&gt;Slate&lt;/LastName&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;Manager&gt;1&lt;/Manager&gt;<BR>&nbsp;&nbsp;&lt;/Contact&gt;<BR>&lt;/Contacts&gt;</P>
<P class=Normal>接下来设置数据网格。我想用　<STRONG>First Name, Last Name</STRONG> 格式将名字组合到一列中，因此我使用 <SPAN class=CodeInText>TemplateColumn</SPAN>。其它两列，每列简单的绑定在一个字段&nbsp;，因此用 <SPAN class=CodeInText>BoundColumn</SPAN> 就足够了。</P>
<P class=CodeTable>&lt;asp:DataGrid id="dgContacts" runat="server" AutoGenerateColumns="False" Width="370px"&gt;<BR>&nbsp;&nbsp;&lt;ItemStyle CssClass="item"&gt;&lt;/ItemStyle&gt;<BR>&nbsp;&nbsp;&lt;HeaderStyle CssClass="heading"&gt;&lt;/HeaderStyle&gt;<BR>&nbsp;&nbsp;&lt;Columns&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;asp:TemplateColumn HeaderText="Name"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;ItemTemplate&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;asp:Label runat="server" Text= ''&lt;%# DataBinder.Eval(Container, "DataItem.FirstName") %&gt;''&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/asp:Label&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;/ItemTemplate&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/asp:TemplateColumn&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;asp:BoundColumn DataField="Email" ReadOnly="True" HeaderText="Email"&gt;&lt;/asp:BoundColumn&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;asp:BoundColumn DataField="Manager" ReadOnly="True" HeaderText="Status"&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;HeaderStyle HorizontalAlign="Center"&gt;&lt;/HeaderStyle&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ItemStyle HorizontalAlign="Center"&gt;&lt;/ItemStyle&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&lt;/asp:BoundColumn&gt;<BR>&nbsp;&nbsp;&lt;/Columns&gt;<BR>&lt;/asp:DataGrid&gt;</P>
<P class=SubHeading>哪个方法?</P>
<P>现在，需要显示网格数据，我需要决定使用哪个方法来显示这些数据。 使用 helper 函数是一种非常容易的改变数据输出的方法。 为了改变网格的格式，应使用 <SPAN class=CodeInText>ItemDataBound</SPAN> 事件。&nbsp;大脑中应记住这些规则，下面是这决定要做的事情：</P>
<P>　 
<TABLE id=Table1 cellSpacing=1 cellPadding=1 border=0>
<TBODY>
<TR>
<TD width=64><STRONG>列</STRONG></TD>
<TD width=110><STRONG>方法</STRONG></TD>
<TD><STRONG>说明</STRONG></TD></TR>
<TR>
<TD vAlign=top width=64>Name</TD>
<TD vAlign=top width=110>Helper</TD>
<TD vAlign=top>输出需要简单的组合 FirstName 和 LastName 字段.</TD></TR>
<TR>
<TD vAlign=top width=64>Email</TD>
<TD vAlign=top width=110>None</TD>
<TD vAlign=top>不做任何改变.</TD></TR>
<TR>
<TD vAlign=top width=64>Status</TD>
<TD vAlign=top width=110>ItemDataBound</TD>
<TD vAlign=top>需要改变基于 Manager　字段值的行的背景色。另外，需要改变显示基于 Manager　字段值的&nbsp;<STRONG>Manager</STRONG> 或 <STRONG>Employee</STRONG> 。第二部分能够使用 helper 函数很容易的实现，但是因为我已经使用了 ItemDataBound 事件，因此我决定在同一个位置做两次操作。</TD></TR></TBODY></TABLE>
<P class=SubHeading><B>Helper 函数</B></P>
<P>设置　helper 函数非常简单。&nbsp; 首先，我在代码区创建了这个函数。&nbsp; 注意：函数作用域被声明为 protected.&nbsp;这是必需的，因为函数将会在代码后的ASPX页中被调用。&nbsp; 去掉函数的私有属性将会在分析页面时出现错误。</P>
<P class=CodeTable>[C#]<BR><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">&nbsp; protectedstring</SPAN><SPAN> FormatFullName(</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">object</SPAN><SPAN> FirstName, </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">object</SPAN><SPAN> LastName)<BR>&nbsp; {<BR>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">//&nbsp; Combine the names to get the Last, First format.<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">return</SPAN><SPAN> (</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">string</SPAN><SPAN>)LastName + </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">", "</SPAN><SPAN> + (</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">string</SPAN><SPAN>)FirstName;<BR>&nbsp; }</SPAN><BR><BR>[VB]<BR><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">&nbsp; ProtectedFunction</SPAN><SPAN> FormatFullName(</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">ByVal</SPAN><SPAN> FirstName </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">AsObject</SPAN><SPAN>, </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">ByVal</SPAN><SPAN> LastName </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">AsObject</SPAN><SPAN>) </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">AsString</SPAN><SPAN><BR>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">''&nbsp; Combine the names to get the Last, First format.<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">ReturnCType</SPAN><SPAN>(LastName, </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">String</SPAN><SPAN>) &amp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">", "</SPAN><SPAN> &amp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">CType</SPAN><SPAN>(FirstName, </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">String</SPAN><SPAN>)<BR></SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">&nbsp; EndFunction</SPAN></P>
<P><SPAN>为了从网格中调用函数，我改变了　<SPAN class=CodeInText>TemplateColumn　中标签的文本值。</SPAN></SPAN></P>
<P class=CodeTable>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;asp:Label runat="server" Text=''&lt;%# FormatFullName(DataBinder.Eval(Container, "DataItem.FirstName"), DataBinder.Eval(Container, "DataItem.LastName")) %&gt;''&gt;</P>
<P class=SubHeading>ItemDataBound 事件</P>
<P>然后，我设置了网格的 <SPAN class=CodeInText>ItemDataBound</SPAN> 事件。有一件事你必须记住：当使用这个事件时，它会触发DataGrid中已建立的每一行。&nbsp; 这包含了页首及页尾行！&nbsp;结果是，你必须确信你正确的设置了数据行的类型。 这由检查Item对象的<SPAN class=CodeInText>ItemType　属性来完成。</SPAN>我无法告诉你当我试着存取数据行中已存在的控件时，曾经遇到过多少次运行时错误，但页首中就不存在这样的情况。</P>
<P class=CodeTable>[C#]<SPAN><BR>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">protectedvoid</SPAN><SPAN> dgContacts_ItemDataBound(</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">object</SPAN><SPAN> source, System.Web.UI.WebControls.DataGridItemEventArgs e)<BR>&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">//&nbsp; 确定是数据行而非页首或页尾<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">if</SPAN><SPAN> (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">//&nbsp; 取得 manager 字段的值<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">string</SPAN><SPAN> isManager = (</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">string</SPAN><SPAN>)DataBinder.Eval(e.Item.DataItem, </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">"Manager"</SPAN><SPAN>);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">if</SPAN><SPAN> (isManager == </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">"1"</SPAN><SPAN>)<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">//&nbsp; 设置文本及背景颜色.<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Item.Cells[2].Text = </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">"Manager"</SPAN><SPAN>;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Item.BackColor = System.Drawing.Color.AliceBlue;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">else</SPAN><SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">//&nbsp; 仅设置文本.<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Item.Cells[2].Text = </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">"Employee"</SPAN><SPAN>;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<BR>&nbsp;&nbsp;&nbsp; }<BR></SPAN><BR>[VB]<BR><SPAN>&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">PrivateSub</SPAN><SPAN> dgContacts_ItemDataBound(</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">ByVal</SPAN><SPAN> sender </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">AsObject</SPAN><SPAN>, </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">ByVal</SPAN><SPAN> e </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">As</SPAN><SPAN> System.Web.UI.WebControls.DataGridItemEventArgs) </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">Handles</SPAN><SPAN> dgContacts.ItemDataBound<BR>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">''&nbsp; 确定是数据行而非页首或页尾<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">If</SPAN><SPAN> e.</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">Item</SPAN><SPAN>.ItemType = ListItemType.</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">Item</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">OrElse</SPAN><SPAN> e.</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">Item</SPAN><SPAN>.ItemType = ListItemType.AlternatingItem </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">Then</SPAN><SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">''&nbsp; 取得 manager 字段的值<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">Dim</SPAN><SPAN> isManager </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">AsString</SPAN><SPAN> = </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">CType</SPAN><SPAN>(DataBinder.Eval(e.</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">Item</SPAN><SPAN>.DataItem, </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">"Manager"</SPAN><SPAN>), </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">String</SPAN><SPAN>)<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">If</SPAN><SPAN> isManager = </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">"1"</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">Then</SPAN><SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">''&nbsp; 设置文本及背景颜色.<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">Item</SPAN><SPAN>.Cells(2).Text = </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">"Manager"</SPAN><SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">Item</SPAN><SPAN>.BackColor = System.Drawing.Color.AliceBlue<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">Else</SPAN><SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #008000; FONT-FAMILY: Courier New">''&nbsp;仅设置文本.<BR></SPAN><SPAN>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.</SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">Item</SPAN><SPAN>.Cells(2).Text = </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #000000; FONT-FAMILY: Courier New">"Employee"</SPAN><SPAN><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">EndIf</SPAN><SPAN><BR>&nbsp;&nbsp;&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">EndIf</SPAN><SPAN><BR>&nbsp; </SPAN><SPAN style="FONT-WEIGHT: 400; FONT-SIZE: 12px; COLOR: #0000ff; FONT-FAMILY: Courier New">EndSub</SPAN><SPAN><BR></SPAN></P>
<P class=SubHeading><B>结果</B></P>
<P>最后，我们总结一下，看看已经创建了什么！&nbsp; 如果我已经正确的完成了每件工作，我将可以获得一个包含了3列的简单网格。名字由　last name 和 first name　组合而成。接着是电子邮件地址，然后是状态列指示此人是否是管理员或雇员。 &nbsp; 最后，任何显示为管理人员的行都有背景色，让我们看看最终的运行结果！</P>
<P><B>摘要</B></P>
<P>正如你所看到的，有多种不同的方法可以改变你的DataGrid中的数据输出格式。&nbsp;你所选择的方法依赖于你需要执行的操作或你考虑的方式。&nbsp;以上方法都非常简单，当你使用它们的时候，就会增加DataGrid控件的可有性。</P><img src ="http://www.blogjava.net/Daniel2005/aggbug/22253.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2005-12-02 15:50 <a href="http://www.blogjava.net/Daniel2005/articles/22253.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>掌握 ASP.NET 之路：自定义实体类简介</title><link>http://www.blogjava.net/Daniel2005/articles/21246.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Thu, 24 Nov 2005 02:57:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/21246.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/21246.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/21246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/21246.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/21246.html</trackback:ping><description><![CDATA[<DIV class=date>发布日期： 5/24/2005<SPAN class=datePipe> | </SPAN>更新日期： 5/24/2005</DIV>
<DIV class=overview>
<P>Karl Seguin<BR>Microsoft Corporation</P>
<P><B>摘要：</B>有些情况下，非类型化的 <B>DataSet</B> 可能并非数据操作的最佳解决方案。本指南的目的就是探讨 <B>DataSet</B> 的一种替代解决方案，即：自定义实体与集合。（本文包含一些指向英文站点的链接。）</P></DIV>
<CENTER><IMG title="" height=6 alt=* src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/3squares.gif" width=30 border=0></CENTER>
<DIV style="HEIGHT: 18px"></DIV>
<H5 style="PADDING-TOP: 2px">本页内容</H5>
<TABLE style="MARGIN-TOP: 7px; MARGIN-BOTTOM: 12px" cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EXAA"><IMG height=9 alt=引言 hspace=4 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width=7 vspace=2 border=0></A></TD>
<TD class=onThisPage><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EXAA">引言</A></TD></TR>
<TR vAlign=top>
<TD><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EUAA"><IMG height=9 alt="DataSet 存在的问题" hspace=4 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width=7 vspace=2 border=0></A></TD>
<TD class=onThisPage><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EUAA">DataSet 存在的问题</A></TD></TR>
<TR vAlign=top>
<TD><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#ERAA"><IMG height=9 alt=自定义实体类 hspace=4 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width=7 vspace=2 border=0></A></TD>
<TD class=onThisPage><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#ERAA">自定义实体类</A></TD></TR>
<TR vAlign=top>
<TD><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EOAA"><IMG height=9 alt=对象关系映射 hspace=4 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width=7 vspace=2 border=0></A></TD>
<TD class=onThisPage><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EOAA">对象关系映射</A></TD></TR>
<TR vAlign=top>
<TD><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#ELAA"><IMG height=9 alt=自定义集合 hspace=4 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width=7 vspace=2 border=0></A></TD>
<TD class=onThisPage><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#ELAA">自定义集合</A></TD></TR>
<TR vAlign=top>
<TD><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EIAA"><IMG height=9 alt=管理关系 hspace=4 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width=7 vspace=2 border=0></A></TD>
<TD class=onThisPage><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EIAA">管理关系</A></TD></TR>
<TR vAlign=top>
<TD><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EFAA"><IMG height=9 alt=高级内容 hspace=4 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width=7 vspace=2 border=0></A></TD>
<TD class=onThisPage><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#EFAA">高级内容</A></TD></TR>
<TR vAlign=top>
<TD><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#ECAA"><IMG height=9 alt=小结 hspace=4 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_down.gif" width=7 vspace=2 border=0></A></TD>
<TD class=onThisPage><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#ECAA">小结</A></TD></TR></TBODY></TABLE><A name=EXAA></A>
<H2>引言</H2>
<P><B>ADODB.RecordSet</B> 和常常被遗忘的 <B>MoveNext</B> 的时代已经过去，取而代之的是 Microsoft ADO.NET 强大而又灵活的功能。我们的新武器就是 <B>System.Data</B> 名称空间，它的特点是具有速度极快的 <B>DataReader</B> 和功能丰富的 <B>DataSet</B>，而且打包在一个面向对象的强大模型中。能够使用这样的工具一点都不奇怪。任何 3 层体系结构都依靠可靠的数据访问层 (DAL) 将数据层与业务层完美地连接起来。高质量的 DAL 有助于改善代码的重新使用，它是获得高性能的关键，而且是完全透明的。</P>
<P>随着工具的改进，我们的开发模式也发生了变化。告别 <B>MoveNext</B> 并不只是让我们摆脱了繁琐的语法，它还让我们认识了断开连接的数据，这种数据对我们开发应用程序的方式产生了深刻的影响。 </P>
<P>因为我们已经熟悉了 <B>DataReader</B>（其行为与 <B>RecordSet</B> 非常类似），所以没花多长时间就进一步开发出 <B>DataAdapter</B>、<B>DataSet</B>、<B>DataTable</B> 和 <B>DataView</B>。正是在开发这些新对象的过程中不断得到磨炼的技能改变了我们的开发方式。断开连接的数据使我们可以利用新的缓存技术，从而大大提高了应用程序的性能。这些类的功能使我们能够编写出更智能、更强大的函数，同时还能减少（有时候甚至是大大减少）常见活动所需的代码数量。</P>
<P>有些情况下非常适合使用 <B>DataSet</B>，例如在设计原型、开发小型系统和支持实用程序时。但是，在企业系统中使用 <B>DataSet</B> 可能并不是最佳的解决方案，因为对企业系统来说，易于维护要比投入市场的时间更重要。本指南的目的就是探讨一种适合处理此类工作的 <B>DataSet</B> 的替代解决方案，即：自定义实体与集合。尽管还存在其他替代解决方案，但它们都无法提供相同的功能或无法获得更多的支持。我们的首要任务是了解 <B>DataSet</B> 的缺点，以便理解我们要解决的问题。 </P>
<P>记住，每种解决方案都有优缺点，所以 <B>DataSet</B> 的缺点可能比自定义实体的缺点（我们也将进行讨论）更容易让您接受。您和您的团队必须自己决定哪个解决方案更适合您的项目。记住要考虑解决方案的总成本，包括要求改变的实质所在以及生产后所需的时间比实际开发代码的时间更长的可能性。最后请注意，我所说的 <B>DataSet</B> 并不是类型化的 <B>DataSet</B>，但它确实可以弥补非类型化的 <B>DataSet</B> 的一些缺点。</P>
<DIV style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px"><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top"><IMG height=9 alt=返回页首 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width=7 border=0></A><A class=topOfPage href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top">返回页首</A></DIV><A name=EUAA></A>
<H2>DataSet 存在的问题</H2>
<P><B>缺少抽象</B></P>
<P>寻找替代解决方案的第一个也是最明显的原因就是 <B>DataSet</B> 无法从数据库结构中提取代码。<B>DataAdapter</B> 可以很好地使您的代码独立于基础数据库供应商（Microsoft、Oracle、IBM 等），但不能抽象出数据库的核心组件：表、列和关系。这些核心数据库组件也是 <B>DataSet</B> 的核心组件。<B>DataSet</B> 和数据库不仅共享通用组件，不幸的是，它们还共享架构。假定有下面这样一个 Select 语句：</P><PRE class=codeSample>SELECT UserId, FirstName, LastName
FROM Users
</PRE>
<P>我们知道这些值可以从 <B>DataSet</B> 中的 <B>UserId</B>、<B>FirstName</B> 和 <B>LastName</B> 这些 <B>DataColumn</B> 中获得。 </P>
<P>为什么会这么复杂？让我们看一个基本的日常示例。首先我们有一个简单的 DAL 函数：</P><PRE class=codeSample>'Visual Basic .NET
Public Function GetAllUsers() As DataSet
Dim connection As New SqlConnection(CONNECTION_STRING)
Dim command As SqlCommand = New SqlCommand("GetUsers", connection)
command.CommandType = CommandType.StoredProcedure
Dim da As SqlDataAdapter = New SqlDataAdapter(command)
Try
Dim ds As DataSet = New DataSet
da.Fill(ds)
Return ds
Finally
connection.Dispose()
command.Dispose()
da.Dispose()
End Try
End Function

//C#
public DataSet GetAllUsers() {
SqlConnection connection = new SqlConnection(CONNECTION_STRING);
SqlCommand command = new SqlCommand("GetUsers", connection);
command.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter(command);
try {
DataSet ds = new DataSet();
da.Fill(ds);
return ds;
}finally {
connection.Dispose();
command.Dispose();
da.Dispose();
 }            
}
</PRE>
<P>然后我们有一个页面，它使用重复器显示所有用户：</P><PRE class=codeSample>&lt;HTML&gt;
&lt;body&gt;
&lt;form id="Form1" method="post" runat="server"&gt;
&lt;asp:Repeater ID="users" Runat="server"&gt;
&lt;ItemTemplate&gt;
&lt;%# DataBinder.Eval(Container.DataItem, "FirstName") %&gt;
&lt;br /&gt;
&lt;/ItemTemplate&gt;
&lt;/asp:Repeater&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/HTML&gt;
&lt;script runat="server"&gt;
public sub page_load
users.DataSource = GetAllUsers()
users.DataBind()
end sub
&lt;/script&gt;
</PRE>
<P>正如我们所看到的那样，我们的 ASPX 页面利用 DAL 函数 <B>GetAllUsers</B> 作为重复器的 <B>DataSource</B>。如果由于某种原因（为了性能而降级、为清楚起见而进行了标准化、要求发生了变化）导致数据库架构发生变化，变化就会一直影响 ASPX，即影响使用“FirstName”列名的 <B>Databinder.Eval</B> 行。这将立刻在您脑海中产生一个危险信号：数据库架构的变化会一直影响到 ASPX 代码吗？听起来不太像 N 层，对吗？</P>
<P>如果我们所要做的只是对列进行简单的重命名，那么更改本例中的代码并不复杂。但是，如果在许多地方都使用了 <B>GetAllUsers</B>，更糟糕的是，如果将其作为为无数用户提供服务的 Web 服务，那又会怎么样呢？怎样才能轻松或安全地传播更改？对于这个基本示例而言，存储过程本身作为抽象层可能已经足够；但是依赖存储过程获得除最基本的保护以外的功能则可能会在以后造成更大的问题。可以将此视为一种硬编码；实质上，使用 <B>DataSet</B> 时，您可能需要在数据库架构（不管使用列名称还是序号位置）和应用层/业务层之间建立一个严格的连接。但愿以前的经验（或逻辑）已经让您了解到硬编码对维护工作以及将来的开发产生的影响。</P>
<P><B>DataSet</B> 无法提供适当抽象的另一个原因是它要求开发人员必须了解基础架构。我们所说的不是基础知识，而是关于列名称、类型和关系的所有知识。去掉这个要求不仅使您的代码不像我们看到的那样容易中断，还使代码更易于编写和维护。简单地说：</P><PRE class=codeSample>Convert.ToInt32(ds.Tables[0].Rows[i]["userId"]);
</PRE>
<P>不仅难于阅读，而且需要非常熟悉列名称及其类型。理想情况下，您的业务层不需要知道有关基础数据库、数据库架构或 SQL 的任何内容。如果您像上述代码字符串中那样使用 <B>DataSet</B>（使用 <B>CodeBehind</B> 并不会有任何改善），您的业务层可能会很薄。</P>
<P><B>弱类型</B></P>
<P><B>DataSet</B> 属于弱类型，因此容易出错，还可能会影响您的开发工作。这意味着无论何时从 <B>DataSet</B> 中检索值，值都以 <B>System.Object</B> 的形式返回，您需要对这种值进行转换。您面临转换可能会失败的风险。不幸的是，失败不是在编译时发生，而是在运行时发生。另外，在处理弱类型的对象时，Microsoft Visual Studio.NET (VS.NET) 等工具对您的开发人员并没有太大的帮助。前面我们说过需要深入了解构架的知识，就是指这个意思。我们再来看一个非常常见的示例：</P><PRE class=codeSample>'Visual Basic.NET
Dim userId As Integer = 
?      Convert.ToInt32(ds.Tables(0).Rows(0)("UserId"))
Dim userId As Integer = CInt(ds.Tables(0).Rows(0)("UserId"))
Dim userId As Integer = CInt(ds.Tables(0).Rows(0)(0))

//C#
int userId = Convert.ToInt32(ds.Tables[0].Rows[0]("UserId"));
</PRE>
<P>这段代码显示了从 <B>DataSet</B> 中检索值的可能方法——可能您的代码中到处都需要检索值（如果不进行转换，而您使用的又是 Visual Basic .NET，您可能会使用 Option Strict Off 这样的代码，而这会给您带来更大的麻烦。）</P>
<P>不幸的是，这些代码中的每一行都可能会产生大量的运行时错误： </P>
<TABLE class=numberedList cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR vAlign=top>
<TD class=listNumber noWrap align=right>
<P>1.</P></TD>
<TD>
<P>转换可能由于以下原因而失败： </P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>值可能为空。 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>开发人员可能对基础数据类型判断有误（还是这个问题，即开发人员需要非常熟悉数据库架构）。 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>如果您使用序号值，谁知道位置 X 处实际上是一个什么样的列。 </P></TD></TR></TBODY></TABLE></TD></TR>
<TR vAlign=top>
<TD class=listNumber noWrap align=right>
<P>2.</P></TD>
<TD>
<P><B>ds.Tables(0)</B> 可能返回一个空引用（如果 DAL 方法或存储过程中有任何部分失败）。 </P></TD></TR>
<TR vAlign=top>
<TD class=listNumber noWrap align=right>
<P>3.</P></TD>
<TD>
<P>“UserId”可能由于以下原因而是一个无效的列名称： </P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>可能已经更改了名称。 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>可能不是由存储过程返回的。 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>可能包含错别字。 </P></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<P>我们可以修改代码并以更安全的方式编写，即为 <B>null/nothing</B> 添加检查，为转换添加 <B>try/catch</B>，但这些对开发人员都没有帮助。</P>
<P>更糟糕的是，正如我们前面所说，这不是抽象的。这意味着，每次要从 <B>DataSet</B> 中检索 <B>userId</B> 时，您都将面临上面提到的风险，或者需要对相同的保护性步骤进行重新编程（当然，实用程序功能可能会有助于降低风险）。弱类型对象将错误从设计时或编译时（这时总能够自动检测并轻松修复错误）转移到运行时（这时的错误可能会出现在生产过程中，而且更难查明）。</P>
<P><B>非面向对象</B></P>
<P>您不能仅仅因为 <B>DataSet</B> 是对象，而 C# 和 Visual Basic .NET 是面向对象 (OO) 的语言就能以面向对象的方式使用 <B>DataSet</B>。OO 编程的“hello world”是一个典型的 <B>Person</B> 类，该类又是 <B>Employee</B> 的子类。但 <B>DataSet</B> 并没有使此类继承或其他大多数 OO 技术成为可能（或者至少使它们变得自然/直观）。Scott Hanselman 是类实体的坚决支持者，他做出了最好的解释：</P>
<P>“DataSet 是一个对象，对吗？但它并不是域对象，它不是一个‘苹果’或‘桔子’，而是一个‘DataSet’类型的对象。<B>DataSet </B><B>是一只碗</B>（它知道支持数据存储）。DataSet 是一个知道如何保存行和列的对象，它非常了解数据库。但是，我不希望返回碗，我希望返回域对象，例如‘苹果’。”<SUP>1</SUP></P>
<P><B>DataSet</B> 使数据之间保持一种关系，使它们更强大并且能够在关系数据库中方便地使用。不幸的是，这意味着您将失去 OO 的所有优点。 </P>
<P>因为 <B>DataSet</B> 不能作为域对象，所以无法向它们添加功能。通常情况下，对象具有字段、属性和方法，它们的行为针对的是类的实例。例如，您可能会将 <B>Promote</B> 或 <B>CalcuateOvertimePay</B> 函数与 <B>User</B> 对象相关联，该对象可以通过 <B>someUser.Promote()</B> 或 <B>someUser.CalculateOverTimePay()</B> 安全地调用。因为无法向 <B>DataSet</B> 添加方法，所以您需要使用实用程序功能来处理弱类型对象，并且在整个代码中包含硬编码值的更多实例。您一般会以过程代码结束，在过程代码中，您要么不断地从 <B>DataSet</B> 中获取数据，要么以繁琐的方式将它们存储在本地变量中并向其他位置传递。两种方法都有缺点，而且都没有任何优点。</P>
<P><B>与</B><B> DataSet </B><B>相反的情况</B></P>
<P>如果您认为数据访问层应返回 <B>DataSet</B>，您可能会漏掉一些重要的优点。其中一个原因是您可能正在使用一个较薄或不存在的业务层，除了其他问题外，它还限制了您进行抽象的能力。另外，因为您使用的是一般的预编译解决方案，所以很难利用 OO 技术。最后，Visual Studio.NET 等工具使开发人员无法轻松地利用弱类型对象（例如 <B>DataSet</B>），因此降低了效率并且增加了出错的可能性。</P>
<P>所有这些因素都以不同的方式对代码的可维护性产生了直接的影响。缺乏抽象使功能改善和错误修复变得更复杂、更危险。您无法充分利用 OO 提供的代码重新使用或可读性方面的改进。当然还有一点，无论您的开发人员处理的是业务逻辑还是表示逻辑，他们都必须非常了解您的基础数据结构。</P>
<DIV style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px"><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top"><IMG height=9 alt=返回页首 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width=7 border=0></A><A class=topOfPage href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top">返回页首</A></DIV><A name=ERAA></A>
<H2>自定义实体类</H2>
<P>与 <B>DataSet</B> 有关的大多数问题都可以利用 OO 编程的丰富功能在定义明确的业务层中解决。实际上，我们希望获得按照关系组织的数据（数据库），并将数据作为对象（代码）使用。这个概念就是，不是获得保存汽车信息的 <B>DataTable</B>，而是获得汽车对象（称为自定义实体或域对象）。 </P>
<P>在了解自定义实体之前，让我们首先看一看我们将要面临的挑战。最明显的挑战就是所需代码的数量。我们不是简单地获取数据并自动填充 <B>DataSet</B>，而是获取数据并手动将数据映射到自定义实体（必须先创建好）。由于这是一项重复性的任务，我们可以使用代码生成工具或 O/R 映射器（后文有详细的介绍）来减轻工作量。更大的问题是将数据从关系世界映射到对象世界的具体过程。对于简单的系统，映射通常是直接的，但是随着复杂性的增加，这两个世界之间的差异就会产生问题。例如，继承在对象世界中是获得代码重新使用以及可维护性的重要技术。不幸的是，继承对关系数据库来说却是一个陌生的概念。另外一个例子就是处理关系的方式不同：对象世界依靠维护单个对象的引用，而关系世界则是利用外键。</P>
<P>因为代码的数量以及关系数据和对象之间的差异不断增加，看起来这个方法并不太适合更复杂的系统，但事实正好相反。通过将各种问题隔离到一个层中，即映射过程（同样可以自动化），复杂的系统也可以从此方法获益。另外，此方法已经很常用，这意味着可以通过几种已有的设计模式彻底解决增加的复杂性。前面讨论的 <B>DataSet</B> 的缺点在复杂系统中将成倍扩大，最后您会得出这样一个系统，它欠缺灵活应变能力的缺点恰好超出其构建的难度。</P>
<P><B>什么是自定义实体？</B></P>
<P>自定义实体是代表业务域的对象，因此，它们是业务层的基础。如果您有一个用户身份验证组件（本指南通篇都使用该示例进行讲解），您就可能具有 <B>User</B> 和 <B>Role</B> 对象。电子商务系统可能具有 <B>Supplier</B> 和 <B>Merchandise</B> 对象，而房地产公司则可能具有 <B>House</B>、<B>Room</B> 和 <B>Address</B> 对象。在您的代码中，自定义实体只是一些类（实体和“类”之间具有非常密切的关系，就像在 OO 编程中使用的那样）。一个典型的 <B>User</B> 类可能如下所示：</P><PRE class=codeSample>'Visual Basic .NET
Public Class User
#Region "Fields and Properties"
Private _userId As Integer
Private _userName As String
Private _password As String
Public Property UserId() As Integer
Get
Return _userId
End Get
Set(ByVal Value As Integer)
_userId = Value
End Set
End Property
Public Property UserName() As String
Get
Return _userName
End Get
Set(ByVal Value As String)
_userName = Value
End Set
End Property
Public Property Password() As String
Get
Return _password
End Get
Set(ByVal Value As String)
_password = Value
End Set
End Property
#End Region
#Region "Constructors"
Public Sub New()
End Sub
Public Sub New(id As Integer, name As String, password As String)
Me.UserId = id
Me.UserName = name
Me.Password = password
End Sub
#End Region
End Class

//C#
public class User {
#region "Fields and Properties"
private int userId;
private string userName;
private string password;
public int UserId {
get { return userId; }
set { userId = value; }
  }
public string UserName {
get { return userName; }
set { userName = value; }
 }
public string Password {
get { return password; }
set { password = value; }
 }
#endregion
#region "Constructors"
public User() {}
public User(int id, string name, string password) {
this.UserId = id;
this.UserName = name;
this.Password = password;
 }
#endregion
}
</PRE>
<P><B>为什么能够从它们获益？</B></P>
<P>使用自定义实体获得的主要好处来自这样一个简单的事实，即它们是完全受您控制的对象。具体而言，它们允许您： </P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>利用继承和封装等 OO 技术。 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>添加自定义行为。 </P></TD></TR></TBODY></TABLE>
<P>例如，我们的 <B>User</B> 类可以通过为其添加 <B>UpdatePassword</B> 函数而受益（我们可能会使用外部/实用程序函数对数据集执行此类操作，但会影响可读性/维护性）。另外，它们属于强类型，这表示我们可以获得 IntelliSense 支持：</P>
<DIV style="WIDTH: 348px"><IMG height=172 alt="" src="http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/entity_fig01.gif" width=348 border=0><BR>
<P class=figureCaption><B>图</B><B> 1</B><B>：</B><B>User </B><B>类的</B><B> IntelliSense</B></P>
<DIV class=figureRule></DIV></DIV>
<P>最后，因为自定义实体为强类型，所以不太需要进行容易出错的强制转换：</P><PRE class=codeSample>Dim userId As Integer = user.UserId
'与
Dim userId As Integer = 
?         Convert.ToInt32(ds.Tables("users").Rows(0)("UserId"))
</PRE>
<DIV style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px"><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top"><IMG height=9 alt=返回页首 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width=7 border=0></A><A class=topOfPage href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top">返回页首</A></DIV><A name=EOAA></A>
<H2>对象关系映射</H2>
<P>正如前文所讨论的那样，此方法的主要挑战之一就是处理关系数据和对象之间的差异。因为我们的数据始终存储在关系数据库中，所以我们只能在这两个世界之间架起一座桥梁。对于上文的 <B>User</B> 示例，我们可能希望在数据库中建立一个如下所示的用户表：</P>
<DIV style="WIDTH: 319px"><IMG height=64 alt="" src="http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/entity_fig02.gif" width=319 border=0><BR>
<P class=figureCaption><B>图</B><B> 2</B><B>：</B><B>User </B><B>的数据视图</B></P>
<DIV class=figureRule></DIV></DIV>
<P>从这个关系架构映射到自定义实体是一个非常简单的事情：</P><PRE class=codeSample>'Visual Basic .NET
Public Function GetUser(ByVal userId As Integer) As User
Dim connection As New SqlConnection(CONNECTION_STRING)
Dim command As New SqlCommand("GetUserById", connection)
command.Parameters.Add("@UserId", SqlDbType.Int).Value = userId
Dim dr As SqlDataReader = Nothing
Try
connection.Open()
dr = command.ExecuteReader(CommandBehavior.SingleRow)
If dr.Read Then
Dim user As New User
user.UserId = Convert.ToInt32(dr("UserId"))
user.UserName = Convert.ToString(dr("UserName"))
user.Password = Convert.ToString(dr("Password"))
Return user
End If
Return Nothing
Finally
If Not dr is Nothing AndAlso Not dr.IsClosed Then
dr.Close()
End If
connection.Dispose()
command.Dispose()
End Try
End Function

//C#
public User GetUser(int userId) {
SqlConnection connection = new SqlConnection(CONNECTION_STRING);
SqlCommand command = new SqlCommand("GetUserById", connection);
command.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;
SqlDataReader dr = null;
try{
connection.Open();
dr = command.ExecuteReader(CommandBehavior.SingleRow);
if (dr.Read()){
User user = new User();
user.UserId = Convert.ToInt32(dr["UserId"]);
user.UserName = Convert.ToString(dr["UserName"]);
user.Password = Convert.ToString(dr["Password"]);
return user;            
  }
return null;
}finally{
if (dr != null &amp;&amp; !dr.IsClosed){
dr.Close();
  }
connection.Dispose();
command.Dispose();
 }
}
</PRE>
<P>我们仍然按照通常的方式设置连接和命令对象，但接着创建了 <B>User</B> 类的一个新实例并从 <B>DataReader</B> 中填充该实例。您仍然可以在此函数中使用 <B>DataSet</B> 并将其映射到您的自定义实体，但 <B>DataSet</B> 相对于 <B>DataReader</B> 的主要好处是前者提供了数据的断开连接的视图。在本例中，<B>User</B> 实例提供了断开连接的视图，使我们可以利用 <B>DataReader</B> 的速度。</P>
<P><B>等一下！您并没有解决任何问题！</B></P>
<P>细心的读者可能注意到我前面提到 <B>DataSet</B> 的问题之一是它们并非强类型，这导致效率降低并增加了出现运行时错误的可能性。它们还需要开发人员深入了解基础数据结构。看一看上文的代码，您可能会注意到这些问题依然存在。但请注意，我们已经将这些问题封装到一个非常孤立的代码区域内；这表示您的类实体的使用者（Web 界面、Web 服务使用者、Windows 表单）仍然完全没有意识到这些问题。相反，使用 <B>DataSet</B> 可以将这些问题分散到整个代码中。</P>
<P><B>改进</B></P>
<P>上文的代码对显示映射的基本概念很有用，但可以在两个关键的方面进行改进。首先，我们需要提取并将代码填充到其自己的函数中，因为代码有可能会被重新使用：</P><PRE class=codeSample>'Visual Basic .NET
Public Function PopulateUser(ByVal dr As IDataRecord) As User
Dim user As New User
user.UserId = Convert.ToInt32(dr("UserId"))
'检查 NULL 的示例
If Not dr("UserName") Is DBNull.Value Then
user.UserName = Convert.ToString(dr("UserName"))
End If
user.Password = Convert.ToString(dr("Password"))
Return user
End Function

//C#
public User PopulateUser(IDataRecord dr) {
User user = new User();
user.UserId = Convert.ToInt32(dr["UserId"]);
//检查 NULL 的示例
if (dr["UserName"] != DBNull.Value){
user.UserName = Convert.ToString(dr["UserName"]);   
 }
user.Password = Convert.ToString(dr["Password"]);
return user;
}
</PRE>
<P>第二个需要注意的事项是，我们不对映射函数使用 <B>SqlDataReader</B>，而是使用 <B>IDataRecord</B>。这是所有 <B>DataReader</B> 实现的接口。使用 <B>IDataRecord</B> 使我们的映射过程独立于供应商。也就是说，我们可以使用上一个函数从 Access 数据库中映射 <B>User</B>，即使它使用 <B>OleDbDataReader</B> 也可以。如果您将这个特定的方法与 Provider Model Design Pattern（<A href="http://msdn.microsoft.com/asp.net/default.aspx?pull=/library/en-us/dnaspnet/html/asp02182004.asp" target=_blank>链接 1</A>、<A href="http://msdn.microsoft.com/asp.net/default.aspx?pull=/library/en-us/dnaspnet/html/asp04212004.asp" target=_blank>链接 2</A>）结合使用，您的代码就可以轻松地用于不同的数据库提供程序。</P>
<P>最后，以上代码说明了封装的强大功能。处理 <B>DataSet</B> 中的 <B>NULL</B> 并非最简单的事，因为每次提取值时都需要检查它是否为 <B>NULL</B>。使用上述填充方法，我们在一个地方就轻松地解决了此问题，使我们的客户无需处理它。</P>
<P><B>映射到何处？</B></P>
<P>关于此类数据访问和映射函数的归属问题存在一些争论，即究竟是作为独立类的一部分，还是作为适当自定义实体的一部分。将所有用户相关的任务（获取数据、更新和映射）都作为 <B>User</B> 自定义实体的一部分当然很不错。这在数据库架构与自定义实体很相似时会很有用（比如在本例中）。随着系统复杂性的增加，这两个世界的差异开始显现出来，将数据层和业务层明确分离对简化维护有很大的帮助（我喜欢将其称为数据访问层）。将访问和映射代码放在其自己的层 (DAL) 上有一个副作用，即它为确保数据层与业务层的明确分离提供了一个严格的原则：</P>
<P><B>“</B><B>永远不要从</B><B> System.Data </B><B>返回类或从</B><B> DAL </B><B>返回子命名空间</B><B>”</B></P>
<DIV style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px"><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top"><IMG height=9 alt=返回页首 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width=7 border=0></A><A class=topOfPage href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top">返回页首</A></DIV><A name=ELAA></A>
<H2>自定义集合</H2>
<P>到目前为止，我们只了解了如何处理单个实体，但您经常需要处理多个对象。一个简单的解决方案是将多个值存储在一个一般的集合（例如 <B>Arraylist</B>）中。这并非最理想的解决方案，因为它又产生了与 <B>DataSet</B> 有关的一些问题，即： </P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>它们不是强类型，并且 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P>无法添加自定义行为。 </P></TD></TR></TBODY></TABLE>
<P>最能满足我们需求的解决方案是创建我们自己的自定义集合。幸亏 Microsoft .NET Framework 提供了一个专门为了此目的而继承的类：<B>CollectionBase</B><B>。</B><B>CollectionBase</B> 的工作原理是，将所有类型的对象都存储在专有 <B>Arraylist</B> 中，但是通过只接受特定类型（例如 <B>User</B> 对象）的方法来提供对这些专有集合的访问。也就是说，将弱类型代码封装在强类型的 API 中。</P>
<P>虽然自定义集合可能看起来有很多代码，但大多数都可以由代码生成功能或通过剪切和粘贴方便地完成，并且通常只需要一次搜索和替换即可。让我们看一看构成 <B>User</B> 类的自定义集合的不同部分：</P><PRE class=codeSample>'Visual Basic .NET
Public Class UserCollection
Inherits CollectionBase
Default Public Property Item(ByVal index As Integer) As User
Get
Return CType(List(index), User)
End Get
Set
List(index) = value
End Set
End Property
Public Function Add(ByVal value As User) As Integer
Return (List.Add(value))
End Function
Public Function IndexOf(ByVal value As User) As Integer
Return (List.IndexOf(value))
End Function
Public Sub Insert(ByVal index As Integer, ByVal value As User)
List.Insert(index, value)
End Sub
Public Sub Remove(ByVal value As User)
List.Remove(value)
End Sub
Public Function Contains(ByVal value As User) As Boolean
Return (List.Contains(value))
End Function
End Class

//C#
public class UserCollection :CollectionBase {
public User this[int index] {
get {return (User)List[index];}
set {List[index] = value;}
 }
public int Add(User value) {
return (List.Add(value));
 }
public int IndexOf(User value) {
return (List.IndexOf(value));
 }
public void Insert(int index, User value) {
List.Insert(index, value);
 }
public void Remove(User value) {
List.Remove(value);
 }
public bool Contains(User value) {
return (List.Contains(value));
 }
}
</PRE>
<P>通过实现 <B>CollectionBase</B> 可以完成更多任务，但上面的代码代表了自定义集合所需的核心功能。观察一下 <B>Add</B> 函数，可以看出我们只是简单地将对 <B>List.Add</B>（它是一个 <B>Arraylist</B>）的调用封装到仅允许 <B>User</B> 对象的函数中。</P>
<P><B>映射自定义集合</B></P>
<P>将我们的关系数据映射到自定义集合的过程与我们对自定义实体执行的过程非常相似。我们不再创建一个实体并将其返回，而是将该实体添加到集合中并循环到下一个：</P><PRE class=codeSample>'Visual Basic .NET
Public Function GetAllUsers() As UserCollection
Dim connection As New SqlConnection(CONNECTION_STRING)
Dim command As New SqlCommand("GetAllUsers", connection)
Dim dr As SqlDataReader = Nothing
Try
connection.Open()
dr = command.ExecuteReader(CommandBehavior.SingleResult)
Dim users As New UserCollection
While dr.Read()
users.Add(PopulateUser(dr))
End While
Return users
Finally
If Not dr Is Nothing AndAlso Not dr.IsClosed Then
dr.Close()
End If
connection.Dispose()
command.Dispose()
End Try
End Function

//C#
public UserCollection GetAllUsers() {
SqlConnection connection = new SqlConnection(CONNECTION_STRING);
SqlCommand command =new SqlCommand("GetAllUsers", connection);
SqlDataReader dr = null;
try{
connection.Open();
dr = command.ExecuteReader(CommandBehavior.SingleResult);
UserCollection users = new UserCollection();
while (dr.Read()){
users.Add(PopulateUser(dr));
  }
return users;
}finally{
if (dr != null &amp;&amp; !dr.IsClosed){
dr.Close();
  }
connection.Dispose();
command.Dispose();
 }
}
</PRE>
<P>我们从数据库中获得数据、创建自定义集合，然后通过在结果中循环来创建每个 <B>User</B> 对象并将其添加到集合中。同样要注意 <B>PopulateUser</B> 映射函数是如何重新使用的。</P>
<P><B>添加自定义行为</B></P>
<P>在讨论自定义实体时，我们只是泛泛地提到可以将自定义行为添加到类中。您向实体中添加的功能类型很大程度上取决于您要实现的业务逻辑的类型，但您可能希望在自定义集合中实现某些常见的功能。一个示例就是返回一个基于某个键的实体，例如基于 <B>userId</B> 的用户：</P><PRE class=codeSample>'Visual Basic .NET
Public Function FindUserById(ByVal userId As Integer) As User
For Each user As User In List
If user.UserId = userId Then
Return user
End If
Next
Return Nothing
End Function

//C#
public User FindUserById(int userId) {
foreach (User user in List) {
if (user.UserId == userId){
return user;
  }
 }
return null;
}
</PRE>
<P>另一个示例可能是返回基于特定标准（例如部分用户名）的用户子集：</P><PRE class=codeSample>'Visual Basic .NET
Public Function FindMatchingUsers(ByVal search As String) As UserCollection
If search Is Nothing Then
Throw New ArgumentNullException("search cannot be null")
End If
Dim matchingUsers As New UserCollection
For Each user As User In List
Dim userName As String = user.UserName
If Not userName Is Nothing And userName.StartsWith(search) Then
matchingUsers.Add(user)
End If
Next
Return matchingUsers
End Function

//C#
public UserCollection FindMatchingUsers(string search) {
if (search == null){
throw new ArgumentNullException("search cannot be null");
 }
UserCollection matchingUsers = new UserCollection();
foreach (User user in List) {
string userName = user.UserName;
if (userName != null &amp;&amp; userName.StartsWith(search)){
matchingUsers.Add(user);
  }
 }
return matchingUsers;
}
</PRE>
<P>可以通过 <B>DataTable.Select</B> 以相同的方式使用 <B>DataSets</B>。需要说明的重要一点是，尽管创建自己的功能使您可以完全控制您的代码，但 <B>Select</B> 方法为完成同样的操作提供了一个非常方便且不需要编写代码的方法。但另一方面，<B>Select</B> 需要开发人员了解基础数据库，而且它不是强类型。</P>
<P><B>绑定自定义集合</B></P>
<P>我们看到的第一个示例是将 <B>DataSet</B> 绑定到 ASP.NET 控件。考虑到它很普通，您会高兴地发现自定义集合绑定同样很简单（这是因为 <B>CollectionBase</B> 实现了用于绑定的 <B>Ilist</B>）。自定义集合可以作为任何控件的 <B>DataSource</B>，而 <B>DataBinder.Eval</B> 只能像您使用 <B>DataSet</B> 那样使用：</P><PRE class=codeSample>'Visual Basic .NET
Dim users as UserCollection = DAL.GetallUsers()
repeater.DataSource = users
repeater.DataBind()

//C#
UserCollection users = DAL.GetAllUsers();
repeater.DataSource = users;
repeater.DataBind();

&lt;!-- HTML --&gt;
&lt;asp:Repeater onItemDataBound="r_IDB" ID="repeater" Runat="server"&gt;
&lt;ItemTemplate&gt;
&lt;asp:Label ID="userName" Runat="server"&gt;
&lt;%# DataBinder.Eval(Container.DataItem, "UserName") %&gt;&lt;br /&gt;
&lt;/asp:Label&gt;
&lt;/ItemTemplate&gt;
&lt;/asp:Repeater&gt;
</PRE>
<P>您可以不使用列名称作为 <B>DataBinder.Eval</B> 的第二个参数，而指定您希望显示的属性名称，在本例中为 <B>UserName</B>。</P>
<P>对于在许多数据绑定控件提供的 <B>OnItemDataBound</B> 或 <B>OnItemCreated</B> 中执行处理的人来说，您可能会将 <B>e.Item.DataItem</B> 强制转换成 <B>DataRowView</B>。当绑定到自定义集合时，<B>e.Item.DataItem</B> 则被强制转换成自定义实体，在我们的示例中为 <B>User</B> 类：</P><PRE class=codeSample>'Visual Basic .NET
Protected Sub r_ItemDataBound (s As Object, e As RepeaterItemEventArgs)
Dim type As ListItemType = e.Item.ItemType
If type = ListItemType.AlternatingItem OrElse
?   type = ListItemType.Item Then
Dim u As Label = CType(e.Item.FindControl("userName"), Label)
Dim currentUser As User = CType(e.Item.DataItem, User)
If Not PasswordUtility.PasswordIsSecure(currentUser.Password) Then
ul.ForeColor = Drawing.Color.Red
End If
End If
End Sub

//C#
protected void r_ItemDataBound(object sender, RepeaterItemEventArgs e) {
ListItemType type = e.Item.ItemType;
if (type == ListItemType.AlternatingItem || 
?    type == ListItemType.Item){
Label ul = (Label)e.Item.FindControl("userName");
 User currentUser = (User)e.Item.DataItem;
if (!PasswordUtility.PasswordIsSecure(currentUser.Password)){
ul.ForeColor = Color.Red;
  }
 }
}
</PRE>
<DIV style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px"><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top"><IMG height=9 alt=返回页首 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width=7 border=0></A><A class=topOfPage href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top">返回页首</A></DIV><A name=EIAA></A>
<H2>管理关系</H2>
<P>即使在最简单的系统中，实体之间也存在关系。对于关系数据库，可以通过外键维护关系；而使用对象时，关系只是对另一个对象的引用。例如，根据我们前面的示例，<B>User</B> 对象完全可以具有一个 <B>Role</B>：</P><PRE class=codeSample>'Visual Basic .NET
Public Class User
Private _role As Role
Public Property Role() As Role
Get
Return _role
End Get
Set(ByVal Value As Role)
_role = Value
End Set
End Property
End Class

//C#
public class User {
private Role role;
public Role Role {
get {return role;}
set {role = value;}
 }
}
</PRE>
<P>或者一个 <B>Role</B> 集合：</P><PRE class=codeSample>'Visual Basic .NET
Public Class User
Private _roles As RoleCollection
Public ReadOnly Property Roles() As RoleCollection
Get
If _roles Is Nothing Then
_roles = New RoleCollection
End If
Return _roles
End Get
End Property
End Class

//C#
public class User {
private RoleCollection roles;
public RoleCollection Roles {
get {
if (roles == null){
roles = new RoleCollection();
   }
return roles;
  }
 }
}
</PRE>
<P>在这两个示例中，我们有一个虚构的 <B>Role</B> 类或 <B>RoleCollection</B> 类，它们就是类似于 <B>User</B> 和 <B>UserCollection</B> 类的其他自定义实体或集合类。</P>
<P><B>映射关系</B></P>
<P>真正的问题在于如何映射关系。让我们看一个简单的示例，我们希望根据 <B>userId</B> 及其角色来检索一个用户。首先，我们看一看关系模型：</P>
<DIV style="WIDTH: 353px"><IMG height=205 alt="" src="http://www.microsoft.com/china/msdn/library/webservices/asp.net/art/entity_fig03.gif" width=353 border=0><BR>
<P class=figureCaption><B>图</B><B> 3</B><B>：</B><B>User </B><B>与</B><B> Role </B><B>之间的关系</B></P>
<DIV class=figureRule></DIV></DIV>
<P>这里，我们看到了一个 <B>User</B> 表和一个 <B>Role</B> 表，我们可以将这两个表都以直观的方式映射到自定义实体。我们还有一个 <B>UserRoleJoin</B> 表，它代表了 <B>User</B> 与 <B>Role</B> 之间的多对多关系。 </P>
<P>然后，我们使用存储过程来获取两个单独的结果：第一个代表 <B>User</B>，第二个代表该用户的 <B>Role</B>：</P><PRE class=codeSample>CREATE PROCEDURE GetUserById(
@UserId INT
)AS
SELECT UserId, UserName, [Password]
FROM Users
WHERE UserId = @UserID
SELECT R.RoleId, R.[Name], R.Code
FROM Roles R INNER JOIN
UserRoleJoin URJ ON R.RoleId = URJ.RoleId
WHERE  URJ.UserId = @UserId
</PRE>
<P>最后，我们从关系模型映射到对象模型：</P><PRE class=codeSample>'Visual Basic .NET
Public Function GetUserById(ByVal userId As Integer) As User
Dim connection As New SqlConnection(CONNECTION_STRING)
Dim command As New SqlCommand("GetUserById", connection)
command.Parameters.Add("@UserId", SqlDbType.Int).Value = userId
Dim dr As SqlDataReader = Nothing
Try
connection.Open()
dr = command.ExecuteReader()
Dim user As User = Nothing
If dr.Read() Then
user = PopulateUser(dr)
dr.NextResult()
While dr.Read()
user.Roles.Add(PopulateRole(dr))
End While
End If
Return user
Finally
If Not dr Is Nothing AndAlso Not dr.IsClosed Then
dr.Close()
End If
connection.Dispose()
command.Dispose()
End Try
End Function

//C#
public User GetUserById(int userId) {
SqlConnection connection = new SqlConnection(CONNECTION_STRING);
SqlCommand command = new SqlCommand("GetUserById", connection);
command.Parameters.Add("@UserId", SqlDbType.Int).Value = userId;
SqlDataReader dr = null;
try{
connection.Open();
dr = command.ExecuteReader();
User user = null;
if (dr.Read()){
user = PopulateUser(dr);
dr.NextResult();
while(dr.Read()){
user.Roles.Add(PopulateRole(dr));
   }            
  }
return user;
}finally{
if (dr != null &amp;&amp; !dr.IsClosed){
dr.Close();
  }
connection.Dispose();
command.Dispose();
 }
}
</PRE>
<P><B>User</B> 实例即被创建和填充；我们转移到下一个结果/选择并进行循环，填充 <B>Role</B> 并将它们添加到 <B>User</B> 类的 <B>RolesCollection</B> 属性中。</P>
<DIV style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px"><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top"><IMG height=9 alt=返回页首 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width=7 border=0></A><A class=topOfPage href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top">返回页首</A></DIV><A name=EFAA></A>
<H2>高级内容</H2>
<P>本指南的目的是介绍自定义实体与集合的概念及使用。使用自定义实体是业界广泛采用的做法，因此，也就产生了同样多的模式以处理各种情况。设计模式具有优势的原因有很多。首先，在处理具体的情况时，您可能不是第一次碰到某个给定的问题。设计模式使您可以重新使用给定问题的已经过尝试和测试的解决方案（虽然设计模式并不意味着全盘照抄，但它们几乎总是能够为解决方案提供一个可靠的基础）。相应地，这使您对系统随着复杂性增加而进行缩放的能力充满了信心，不仅因为它是一个广泛使用的方法，还因为它具有详尽的记录。设计模式还为您提供了一个通用的词汇表，使知识的传播和传授更容易实现。</P>
<P>不能说设计模式只适用于自定义实体，实际上许多设计模式都并非如此。但是，如果您找机会试一下，您可能会惊喜地发现许多记载详尽的模式确实适用于自定义实体和映射过程。</P>
<P>最后这一部分专门介绍大型或较复杂的系统可能会碰到的一些高级情况。因为大多数主题都可能值得您单独学习，所以我会尽量为您提供一些入门资料。</P>
<P>Martin Fowler 的 <A href="http://martinfowler.com/books.html" target=_blank>Patterns of Enterprise Application Architecture</A> 就是一个很好的入门材料，它不仅可以作为常见设计模式的优秀参考（具有详细的解释和大量的示例代码），而且它的前 100 页确实可以让您透彻地了解整个概念。另外，Fowler 还提供了一个联机<A href="http://martinfowler.com/eaaCatalog/" target=_blank>模式目录</A>，它对于已经熟悉概念但需要一个便利参考的人士很有用。</P>
<P><B>并发</B></P>
<P>前面的示例介绍的都是从数据库中提取数据并根据这些数据创建对象。总体而言，更新、删除和插入数据等操作是很直观的。我们的业务层负责创建对象、将对象传递给数据访问层，然后让数据访问层处理对象世界与关系世界之间的映射。例如：</P><PRE class=codeSample>'Visual Basic .NET
Public sub UpdateUser(ByVal user As User)
Dim connection As New SqlConnection(CONNECTION_STRING)
Dim command As New SqlCommand("UpdateUser", connection)
' 可以借助可重新使用的函数对此进行反向映射
command.Parameters.Add("@UserId", SqlDbType.Int)
command.Parameters(0).Value = user.UserId
command.Parameters.Add("@Password", SqlDbType.VarChar, 64)
command.Parameters(1).Value = user.Password
command.Parameters.Add("@UserName", SqlDbType.VarChar, 128)
command.Parameters(2).Value = user.UserName
Try
connection.Open()
command.ExecuteNonQuery()
Finally
connection.Dispose()
command.Dispose()
End Try
End Sub

//C#
public void UpdateUser(User user) {
SqlConnection connection = new SqlConnection(CONNECTION_STRING);
SqlCommand command = new SqlCommand("UpdateUser", connection);
// 可以借助可重新使用的函数对此进行反向映射
command.Parameters.Add("@UserId", SqlDbType.Int);
command.Parameters[0].Value = user.UserId;
command.Parameters.Add("@Password", SqlDbType.VarChar, 64);
command.Parameters[1].Value = user.Password; 
command.Parameters.Add("@UserName", SqlDbType.VarChar, 128);
command.Parameters[2].Value = user.UserName;
try{
connection.Open();
command.ExecuteNonQuery();
}finally{
connection.Dispose();
command.Dispose();
 }
}
</PRE>
<P>但在处理并发时就不那么直观了，也就是说，当两个用户试图同时更新相同的数据时会出现什么情况呢？默认的行为（如果您没有执行任何操作）是最后提交数据的人将覆盖以前所有的工作。这可能不是理想的情况，因为一个用户的工作将在未获得任何提示的情况下被覆盖。要完全避免所有冲突，一种方法就是使用消极的并发技术；但此方法需要具有某种锁定机制，这可能很难通过可缩放的方式实现。替代方法就是使用积极的并发技术。让第一个提交的用户控制并通知后面的用户是通常采取的更温和、更用户友好的方法。这可以通过某种行版本控制（例如时间戳）来实现。</P>
<P><B><I>参考资料：</I></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://msdn.microsoft.com/asp.net/default.aspx?pull=/library/en-us/vbcon/html/vbtskPerformingOptimisticConcurrencyChecking.asp" target=_blank>Introduction to Data Concurrency in ADO.NET </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.lhotka.net/Articles.aspx?id=890d3e3c-8a49-486c-ae48-a44e7e1f7844" target=_blank>CSLA.NET's concurrency techniques </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://martinfowler.com/eaaCatalog/unitOfWork.html" target=_blank>Unit of Work design pattern </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://martinfowler.com/eaaCatalog/optimisticOfflineLock.html" target=_blank>Optimistic offline lock design pattern </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://martinfowler.com/eaaCatalog/pessimisticOfflineLock.html" target=_blank>Pessimistic offline lock design pattern </A></P></TD></TR></TBODY></TABLE>
<P><B>性能</B></P>
<P>与合理的灵活性和功能问题相对的是，我们经常担心细小的性能差异。尽管性能的确很重要，但提供适用于一切情况而不是最简单情况的通用原则通常很难。例如，将自定义集合与 <B>DataSet</B> 相比，哪个更快？使用自定义集合，您可以大量使用 <B>DataReader</B>，这是从数据库中提取数据的较快方式。但答案实际上取决于您使用它们的方式以及处理的数据类型，所以一般性的说明没有任何用。更重要的一点是要认识到，不管您能节省多少处理时间，与维护性方面的差异相比都可能微不足道。</P>
<P>当然，并不是说您不可能找到一个既具有高性能又可维护的解决方案。虽然我强调说答案实际上取决于您的使用方式，但的确有一些模式可以帮助您最大程度地提高性能。但是，首先要知道的是自定义实体与集合缓存以及 <B>DataSet</B>，并且能够利用相同的机制（类似于 <B>HttpCache</B>）。<B>DataSet</B> 的优势之一是它能够编写 <B>Select</B> 语句，以便只获取所需的信息。使用自定义实体时，您常常感到不得不填充整个实体以及子实体。例如，如果要通过 <B>DataSet</B> 显示一个 <B>Organization</B> 列表，您可以只提取 <B>OganizationId</B>、<B>Name</B> 和 <B>Address</B> 并将其绑定到重复器。使用自定义实体时，我总觉得还需要获取所有其他的 <B>Organization</B> 信息，如果该组织通过了 ISO 认证，则可能是一个位标记，即所有员工、其他联系信息等的集合。可能其他人没有碰到这个大难题，但幸运的是，如果我们愿意，我们可以对自定义实体进行很好的控制。最常用的方法是使用一种延迟加载模式，它只在首次需要时获取信息（可以很好地封装在属性中）。这种对各个属性的控制提供了通过其他方式无法轻易获得的巨大灵活性（请想象一下在 <B>DataColumn</B> 级别执行类似操作的情况）。</P>
<P><B><I>参考资料：</I></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://martinfowler.com/eaaCatalog/lazyLoad.html" target=_blank>Lazy Load</A> 设计模式 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.lhotka.net/Articles.aspx?id=48548dc3-3b64-4bb3-bc84-9476b8f77600" target=_blank>CSLA.NET lazy load</A></P></TD></TR></TBODY></TABLE>
<P><B>排序与筛选</B></P>
<P>虽然 <B>DataView</B> 对排序和筛选的内置支持需要您了解有关 SQL 和基础数据结构的知识，但它提供的方便确实是自定义集合所不具备的。我们仍然可以排序和筛选，但首先需要编写功能。因为技术不一定是最先进的，所以代码的完整描述不属于本节要讨论的范围。大多数技术都很相似，例如使用筛选器类筛选集合以及使用比较器类进行排序，我认为不存在固定的模式。但是，的确存在一些参考资料： </P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.c-sharpcorner.com/Code/2002/June/CollectionObgOrdering.asp" target=_blank>Generic sort function</A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://tim-price.net/blog/articles/171.aspx" target=_blank>Sorting &amp; Filtering Custom Collections</A> 教程 </P></TD></TR></TBODY></TABLE>
<P><B>代码生成</B></P>
<P>解决概念上的障碍后，自定义实体与集合的主要缺点就是灵活性、抽象和维护性差所导致的代码数量的增加。实际上，您可能会认为我所说的维护成本和错误的降低这一切都抵不上代码的增加。虽然这一观点是成立的（同样，因为任何解决方案都不是完美无缺的），但可以通过设计模式和框架（例如 CSLA.NET）大大缓解此问题。代码生成工具与模式和框架完全不同，这些工具可以大大降低您实际需要编写的代码数量。本指南最初打算专门辟出一节详细介绍代码生成工具，特别是流行的免费 CodeSmith；但现有的许多参考资料都可能超出了我自己对该产品的认识。</P>
<P>在继续之前，我认识到代码生成听起来像天方夜谭一样。但经过正确的使用和理解后，它的确是您工具包中不可缺少的一个强大的武器，即使您没有处理自定义实体也是如此。虽然代码生成的确不仅仅适用于自定义实体，但很多都是专为自定义实体而设计的。原因很简单：自定义实体需要大量重复代码。</P>
<P>简言之，代码生成是如何工作的？构想听起来好像遥不可及甚至反而会降低效率，但您基本上通过编写代码（模板）来生成代码。例如，CodeSmith 附带了许多强大的类，使您可以连接到数据库并获取所有属性：表、列（类型、大小等）和关系。获得这些信息后，我们前面讨论的大部分工作都可以自动完成。例如，开发人员可以选择一个表，然后使用正确的模板自动创建自定义实体（带有正确的字段、属性和构造函数），并获得映射函数、自定义集合以及基本的选择、插入、更新和删除功能。甚至还可以更进一步，实现排序、筛选以及我们提到的其他高级功能。</P>
<P>CodeSmith 还附带了许多现成的模板，可以作为很好的学习资料。最后，CodeSmith 还为实现 CSLA.NET 框架提供了许多模板。我最初只花了几个小时来学习基本概念、熟悉 CodeSmith 的功能，但它为我节省的时间已经多得无法计算了。另外，如果所有的开发人员都使用相同的模板，代码的高度一致性将使您能够轻松地继续其他人的工作。</P>
<P><B><I>参考资料：</I></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://msdn.microsoft.com/asp.net/default.aspx?pull=/library/en-us/dnhcvs04/html/vs04e5.asp" target=_blank>Code Generation with CodeSmith </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.ericjsmith.com/codesmith/" target=_blank>CodeSmith 主页 </A></P></TD></TR></TBODY></TABLE>
<P><B>O/R </B><B>映射器</B></P>
<P>即使因为对 O/R 映射器知之甚少使我不敢随便对它们发表议论，但它们自身的潜在价值使其不容忽视。代码生成器生成基于模板的代码，供您复制并粘贴到您自己的源代码中，而 O/R 映射器则在运行时通过某种配置机制动态生成代码。例如，在 XML 文件中，您可以指定某个表的列 X 映射到某个实体的属性 Y。您仍然需要创建自定义实体，但是集合、映射和其他数据访问函数（包括存储过程）都是动态创建的。从理论上讲，O/R 映射器几乎可以完全解决自定义实体存在的问题。随着关系世界和对象世界的差异越来越明显以及映射过程越来越复杂，O/R 映射器的价值就变得越发不可限量了。O/R 映射器的两个缺点据说就是不够安全和性能较差（至少在 .NET 环境中是这样）。根据我所阅读的资料，我确信它们并不是不够安全，虽然在有些情况下性能较差，但在另外一些情况下却表现突出。O/R 映射器并不适合所有情况，但如果您要处理复杂的系统，则应尝试一下它们的功能。</P>
<P><B><I>参考资料：</I></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.martinfowler.com/eaaCatalog/mapper.html" target=_blank>Mapper</A> 设计模式 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.martinfowler.com/eaaCatalog/dataMapper.html" target=_blank>Data Mapper</A> 设计模式 </P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.ormapper.net/" target=_blank>Wilson ORMapper</A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://weblogs.asp.net/fbouma/category/3053.aspx" target=_blank>Frans Bouma 关于 O/R 映射的帖子</A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.llblgen.com/defaultgeneric.aspx" target=_blank>LLBGenPro</A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://nhibernate.sourceforge.net/" target=_blank>NHibernate</A></P></TD></TR></TBODY></TABLE>
<P><B>.NET Framework 2.0 </B><B>的功能</B></P>
<P>即将面世的 .NET Framework 2.0 版将改变我们在本指南中讨论的一些实施细节。这些改变将减少支持自定义实体所需的代码数量，并有助于处理映射问题。</P>
<P><B>泛型</B></P>
<P>议论颇多的泛型之所以存在，主要原因之一就是为了向开发人员提供现成的强类型的集合。我们避开 <B>Arraylist</B> 等现有集合是因为它们属于弱类型。泛型提供了与当前集合同样的方便性，而且它们属于强类型。这是通过在声明时指定类型来实现的。例如，我们可以替换 <B>UserCollection</B> 而不需要增加代码，然后只需创建一个 <B>List&lt;T&gt;</B> 泛型的新实例并指定我们的 <B>User</B> 类即可：</P><PRE class=codeSample>'Visual Basic .NET
Dim users as new IList(of User)

//C#
IList&lt;User&gt; users = new IList&lt;user&gt;();
</PRE>
<P>声明后，我们的 <B>user</B> 集合就只能处理 <B>User</B> 类型的对象了，这为我们提供了编译时检查和优化的所有优点。</P>
<P><B><I>参考资料：</I></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.15seconds.com/issue/031024.htm" target=_blank>Introducing .NET Generics </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://msdn.microsoft.com/asp.net/default.aspx?pull=/library/en-us/dnvs05/html/csharp_generics.asp" target=_blank>An Introduction to C# Generics </A></P></TD></TR></TBODY></TABLE>
<P><B>可以为空的类型</B></P>
<P>可以为空的类型实际上就是由于其他原因而非上述原因而使用的泛型。处理数据库时面临的挑战之一就是正确一致地处理支持 <B>NULL</B> 的列。在处理字符串和其他类（称为引用类型）时，您只需为代码中的某个变量指定 <B>nothing</B>/<B>null</B>：</P><PRE class=codeSample>'Visual Basic .NET
if dr("UserName") Is DBNull.Value Then
user.UserName = nothing
End If

//C#
if (dr["UserName"] == DBNull.Value){
user.UserName = null;
}
</PRE>
<P>也可以什么都不做（默认情况下，引用类型为 <B>nothing</B>/<B>null</B>）。这对值类型（例如<B>整数</B>、<B>布尔值</B>、<B>小数</B>等）并不完全一样。您当然也可以为这些值指定 <B>nothing</B>/<B>null</B>，但这样将会指定一个默认值。如果您只声明整数，或者为其指定 <B>nothing</B>/<B>null</B>，变量的值实际上将为 <B>0</B>。这使其很难映射回数据库：值究竟为 <B>0</B> 还是 <B>null</B>？可以为空的类型允许值类型具有具体的值或者为空，从而解决了这个问题。例如，如果我们要在 <B>userId</B> 列中支持 <B>null</B> 值（并不是很符合实际情况），我们会首先将 <B>userId</B> 字段和对应的属性声明为可以为空的类型：</P><PRE class=codeSample>'Visual Basic .NET
Private _userId As Nullable(Of Integer)
Public Property UserId() As Nullable(Of Integer)
Get
Return _userId
End Get
Set(ByVal value As Nullable(Of Integer))
_userId = value
End Set
End Property


//C#
private Nullable&lt;int&gt; userId;
public Nullable&lt;int&gt; UserId {
get { return userId; }
set { userId = value; }
}
</PRE>
<P>然后利用 <B>HasValue</B> 属性判断是否指定了 <B>nothing</B>/<B>null</B>：</P><PRE class=codeSample>'Visual Basic .NET
If UserId.HasValue Then
Return UserId.Value
Else
Return DBNull.Value
End If

//C#
if (UserId.HasValue) {
return UserId.Value;
} else {
return DBNull.Value;
}
</PRE>
<P><B><I>参考资料：</I></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://blogs.msdn.com/ericgu/archive/2004/05/27/143221.aspx" target=_blank>Nullable types in C# </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.panopticoncentral.net/archive/2004/06/04/1180.aspx" target=_blank>Nullable types in VB.NET </A></P></TD></TR></TBODY></TABLE>
<P><B>迭代程序</B></P>
<P>我们前面讨论的 <B>UserCollection</B> 示例只展示了自定义集合中可能需要的基本功能。有一个操作无法通过所提供的实现来完成，即通过一个 <B>foreach</B> 循环在集合中循环。要完成此操作，您的自定义集合必须具有实现 <B>IEnumerable</B> 接口的枚举数支持类。这是一个非常直观且重复性较强的过程，但却引入了更多的代码。C# 2.0 引入了新的 <B>yield</B> 关键字来为您处理此接口的实现细节。Visual Basic .NET 中当前没有与新的 <B>yield</B> 关键字等效的关键字。 </P>
<P><B><I>参考资料：</I></B></P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.dotnetfun.com/Articles/csharp/2.0/WhatsNew20Iterators.aspx" target=_blank>What's new In C# 2.0 - Iterators </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://www.ondotnet.com/pub/a/dotnet/2004/06/07/liberty.html" target=_blank>C# Iterators </A></P></TD></TR></TBODY></TABLE>
<DIV style="MARGIN-TOP: 3px; MARGIN-BOTTOM: 10px"><A href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top"><IMG height=9 alt=返回页首 src="http://www.microsoft.com/library/gallery/templates/MNP2.Common/images/arrow_px_up.gif" width=7 border=0></A><A class=topOfPage href="http://www.microsoft.com/china/msdn/library/webservices/asp.net/CustEntCls.mspx#top">返回页首</A></DIV><A name=ECAA></A>
<H2>小结</H2>
<P>请勿轻率地做出向自定义实体与集合转换的决定。这里有许多需要考虑的因素。例如，您对 OO 概念的熟悉程度、可用来熟悉新方法的时间以及您打算部署它的环境。虽然总体上它们有很大的优点，但并不一定适合您的特定情况。即使适合您的情况，它们的缺点也可能会打消您使用它们的念头。还要记住有许多可替代的解决方案。Jimmy Nilsson 在他的 <I>Choosing Data Containers for .NET</I> 中概述了其中的某些替代方案，此专栏系列包括 5 部分（<A href="http://www.informit.com/articles/article.asp?p=31099" target=_blank>1</A>、<A href="http://www.informit.com/articles/article.asp?p=31325" target=_blank>2</A>、<A href="http://www.informit.com/articles/article.asp?p=31457" target=_blank>3</A>、<A href="http://www.informit.com/articles/article.asp?p=31672" target=_blank>4</A>、<A href="http://www.informit.com/articles/article.asp?p=99034" target=_blank>5</A>）。</P>
<P>自定义实体使您获得了面向对象的编程的丰富功能，并帮助您构建了可靠、可维护的 N 层体系结构的框架。本指南的目的之一是让您从构成系统的业务实体，而不是一般的 <B>DataSet</B> 和 <B>DataTable</B> 的角度来考虑您的系统。我们还讨论了一些关键的问题，不管您选择的途径（即设计模式）、对象世界与关系世界的差异（<A href="http://www.agiledata.org/essays/impedanceMismatch.html" target=_blank>了解详细信息</A>）以及 N 层体系结构是什么，您都应注意这些问题。请记住，您之前花费的时间会在系统的整个生命周期内为您带来更多的回报。</P>
<P><B>相关书籍</B></P>
<TABLE cellSpacing=0 cellPadding=0 border=0>
<TBODY>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://shopping.msn.com/search/detail.aspx?pcId=4650&amp;prodId=1627168&amp;ptnrid=141&amp;ptnrdata=0" target=_blank>Microsoft ASP.NET Coding Strategies with the Microsoft ASP.NET Team</A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://shopping.msn.com/search/detail.aspx?pcId=12231&amp;prodId=2180604&amp;ptnrid=141&amp;ptnrdata=0" target=_blank>Expert C# Business Objects </A></P></TD></TR>
<TR>
<TD class=listBullet vAlign=top>•</TD>
<TD class=listItem>
<P><A href="http://shopping.msn.com/search/detail.aspx?pcId=4319&amp;prodId=1876448&amp;ptnrid=141&amp;ptnrdata=0" target=_blank>Expert One-on-One Visual Basic .NET Business Objects </A></P></TD></TR></TBODY></TABLE>
<P><SUP>1</SUP>http://www.hanselman.com/blog/PermaLink.aspx?guid=d88f7539-10d8-4697-8c6e-1badb08bb3f5</P>
<P><A href="http://www.microsoft.com/info/cpyright.mspx" target=_blank>© 2005 Microsoft Corporation 版权所有。保留所有权利。使用规定</A>。</P><img src ="http://www.blogjava.net/Daniel2005/aggbug/21246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2005-11-24 10:57 <a href="http://www.blogjava.net/Daniel2005/articles/21246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET中Web DataGrid的使用指南</title><link>http://www.blogjava.net/Daniel2005/articles/20976.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 22 Nov 2005 07:58:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/20976.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/20976.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/20976.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/20976.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/20976.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<P>很久以前就想写一些关于DataGrid/DataList的东西，但是一直以来，一方面自感所学未深，另一方面，总觉无从下笔，一拖再拖，离刚开始的念头已距一年有余。</P>
<P>DataGrid/DataList在ASP.NET中的重要性，想必就不用我再强调了，凡显示Table类型的数据，大多会使用这两个控件(当然，如果谁还像ASP那样写ASP.NET，那我也没有办法)，所以，每个人可能都有自己的领悟，这篇文章，算是抛砖引玉，为大家做个铺垫。 </P>
<P><STRONG>一、方法<BR><BR>1、DataBind</STRONG></P>
<P>很简单、最常用的方法。绑定数据用。需要注意的只有一点：执行了这个方法后，DataGrid(由于DataGrid和DataList极为相似，所以下面的介绍虽然是针对DataGrid，但与DataList也相差不远)里面所有的显示绑定数据的控件，都会显示DataSource里的数据，其余控件也将初始化成.aspx里设计的状态。<BR><BR><STRONG>二、属性</STRONG></P>
<P><STRONG>1、DataSource</STRONG></P>
<P>有DataBind的地方，就应该有DataSource。如果没有指定DataSource而执行DataBind，那DataGrid将什么也不会显示。<BR>DataSource一般是DataSet、DataTable或者DataView。当然也可以绑定DataReader或者其他实现IEnumerable的类。</P>
<P><STRONG>2、DataKeyField，DataKeys</STRONG></P>
<P>当你在DataGrid中定位一行之后，肯定想知道这行在数据表里的位置，至少有五种方法可以做到这一点，设置DataGrid的DataKeyField就是这几种方法之一。</P>
<P>DataKeyField一般设置为数据表的Unique字段(否则就没意义了)，通过DataKey可以得到这一行对应的关键字段的值。<BR>DataKeys是DataKey的集合，通过行的索引来读取相应行的DataKey。</P>
<P><STRONG>3、EditItemIndex，SelectedIndex，CurrentPageIndex，SelectedItem</STRONG></P>
<P>这些属性都很好理解，看名字就知道是什么意思，需要注意的是，设置了EditItemIndex或者CurrentPageIndex后需要重新执行DataBind方法(当然，前面提到过，还需要设置DataSource)。</P>
<P><STRONG>4、Columns</STRONG></P>
<P>没什么好解释的，Columns就是Columns，列的集合，可以设置列的属性，包括Visible、HeaderText、FooterText、SortExpression等。<BR>严重注意：自动生成的列，是不包含在Columns中的。只有在.aspx中显示声明的列和在代码中添加的列才会被包含在其中。</P>
<P><STRONG>5、Items</STRONG></P>
<P>俗话说，最后的都是最重要的，把Items作为最后一个属性来介绍，正式基于这样的理由。<BR>Items是DataGridItem的集合，可以遍历当前DataGrid中显示数据的DataGridItem。<BR></P>
<P><STRONG>5.1、DataGridItem</STRONG></P>
<P>每一个DataGridItem就是DataGrid中显示的一行，其中包括：</P>
<P>Header DataGrid 控件的标题部分</P>
<P>Item DataGrid 控件中的项</P>
<P>AlternatingItem DataGrid 控件中的交替项</P>
<P>SelectedItem DataGrid 控件中的选定项(由SelectedIndex设置，通过SelectedItem属性或者Items[SelectedIndex]来读取)</P>
<P>EditItem DataGrid 控件中处于编辑状态的项(由EditItemIndex设置，通过Items[EditItemIndex]来读取)</P>
<P>Separator DataGrid 控件中项之间的分隔符</P>
<P>Footer DataGrid 控件的脚注部分</P>
<P>Pager DataGrid 控件的页选择节</P>
<P>注意，DataGrid的Items属性中不会包含Header、Footer、Pager这三类DataGridItem的。</P>
<P><STRONG>5.1.1、DataGridItem的属性</STRONG></P>
<P>ItemIndex —— 得到行在Items中的索引</P>
<P>ItemType —— 返回行的类型，也就是上面列出的Header、Item、...、Pager</P>
<P>Cells —— 返回行包含的所有TableCell(不管是显示声明的，还是自动生成的，不管是可以看见的，还是隐藏掉的)，通过TableCell，可以读取Cell中显示的文本、包含的控件</P>
<P>严重注意：只有BoundColumn列和自动生成列，才可以通过TableCell.Text属性读取显示的文本。HyperLinkColumn、ButtonColumn、EditCommandColumn都需要将目标控件转换成相应的控件。</P>
<P>比如：<BR>假设DataGrid的第一列声明如下</P>
<DIV class=code>＜asp:HyperLinkColumn DataTextField="au_id" HeaderText="au_id" DataNavigateUrlField="au_id" DataNavigateUrlFormatString="Edit.aspx?id={0}"＞＜/asp:HyperLinkColumn＞</DIV>
<P>读取的时候可以用：</P>
<DIV class=code>//Items[0]表示第一行，Cells[0]表示第一列，Controls[0]表示Cell中的第一个控件(也只有这个控件可以用)<BR>HyperLink link = (HyperLink)DataGrid1.Items[0].Cells[0].Controls[0]);<BR>Response.Write(link.Text);</DIV>
<P>至于模板列(TemplateColumn)，当然也可以通过DataGrid1.Items.Cells[j].Controls[n]来获取，然后转换成原来的控件类型再操作，但是还有个更好的办法，就是用FindControl来查找控件。</P>
<P>FindControl是System.Web.UI.Control的方法，可以根据子控件ID来查找子控件</P>
<P>比如：<BR>假设DataGrid的某一列声明如下</P>
<DIV class=code>＜asp:TemplateColumn＞<BR>＜ItemTemplate＞<BR>＜asp:TextBox Runat="server" ID="txtID" Text=＜%# DataBinder.Eval(Container.DataItem,"au_id") %＞＞<BR>＜/asp:TextBox＞<BR>＜/ItemTemplate＞<BR>＜/asp:TemplateColumn＞</DIV>
<P>读取方法：</P>
<DIV class=code>TextBox txt = (TextBox)DataGrid1.Items[1].FindControl("txtID");<BR>Response.Write(txt.Text);</DIV>
<P>注意：DataList中是没有Cell的<BR></P>
<P><STRONG>三、事件</STRONG></P>
<P><STRONG>1、ItemCommand、CancelCommand、DeleteCommand、EditCommand、UpdateCommand</STRONG></P>
<P>也就是DataGrid中，点击Button、LinkButton后执行的事件，执行的事件取决于按钮的CommandName。其实最主要的一个是ItemCommand，而后面四个都只是ItemCommand的一小部分，比如一个按钮的CommandName为"Cancel"，当返回后，首先执行的是ItemCommand事件，然后才是CancelCommand事件。</P>
<P><STRONG>2、PageIndexChanged</STRONG></P>
<P>如果你的DataGrid是分页的，那当你在DataGrid上点击Pager上的1、2、3或者＜、＞时，就会激发这个事件。</P>
<P>在这个事件里面，你可以用e.NewPageIndex来读取要改变的页，然后赋值给DataGrid的CurrentPageIndex属性，最后不要忘了，还要设置DataSource，还要执行DataBind。</P>
<P>注意：DataList中没有这个事件，如果需要在DataList中分页，可以一段一段的读取数据，然后把当前段的数据绑定到DataList上。</P>
<P><STRONG>3、ItemDataBound，ItemCreated</STRONG></P>
<P>首先要说的是这两个事件的发生时间。</P>
<P>ItemDataBound嘛，只要执行了DataBind方法，就会马上激发这个事件。</P>
<P>ItemCreated呢，如果页面是第一次访问(Page.IsPostBack = false)，那在第一次执行DataBind的时候，会先激发ItemCreated事件，也就是说，执行了DataBind后，首先会用ItemCreated来建立Header行，然后用ItemDataBound来绑定Header行，再用ItemCreated来建立第一行，再调用ItemDataBound来绑定第一行，也就是说ItemCreated和ItemDataBound是交替执行的。</P>
<P>页面返回时，也会执行ItemCreated事件，在Page_Load之前，但是这时候就不会再执行ItemDataBound事件了。</P>
<P>所以，如果你想在DataGrid里动态添加什么控件，就需要在ItemCreated事件中，而不是在ItemDataBound事件中。 </P>
<P><STRONG>四、代码片断</STRONG></P>
<P><STRONG>1、DataGrid显示双层表头</STRONG></P>
<P>假设你的DataGrid有三列，现在想将前两列作为"大类1"，第三列作为"大类2"，现在，你可以在ItemDataBound事件中加入下面的代码：</P>
<DIV class=code>if (e.Item.ItemType == ListItemType.Header)<BR>{<BR>e.Item.Cells[0].ColumnSpan = 2;<BR>e.Item.Cells[0].Text = "大类1＜/td＞＜td＞大类2＜/td＞＜/tr＞＜tr＞＜td＞" + e.Item.Cells[0].Text;<BR>}<BR>用这个方法可以为任意添加新行。</DIV>
<P><STRONG>2、设置绑定列或者自动生成列的编辑框宽度</STRONG></P>
<P>请在你的ItemDataBound事件中加入一下代码：</P>
<DIV class=code>if (e.Item.ItemType == ListItemType.EditItem)<BR>{<BR>for (int i = 0; i &lt; e.Item.Cells.Count; i++)<BR>{<BR>TextBox txt = (TextBox)e.Item.Cells.Controls[0];<BR>txt.Width = Unit.Pixel(50);<BR>}<BR>}<BR>
<P><STRONG>3、处理在DataGrid中的DropDownList的事件</STRONG></P>
<P>DropDownList没有CommandName属性，所以不能用ItemCommand事件，不过你可以这样试试：</P>
<P>在DataGrid的模板列中加入的DropDownList控件</P>
<DIV class=code>＜asp:DropDownList runat="server" id="ddl" AutoPostBack="True" OnSelectedIndexChanged="ddl_SelectedIndexChanged" /＞</DIV>
<P>然后你在.aspx.cs中加入一个函数</P>
<DIV class=code>protected void ddl_SelectedIndexChanged(object sender, System.EventArgs e) //一定要声明成protected或者public，不能是private的。<BR>{<BR>//在这里就可以加入其他代码<BR>}</DIV>
<P><STRONG>3.1、在上面的事件中怎样得到本行其他Cell的值呢？</STRONG></P>
<P>我们知道，DataGrid完全是一个Table结构的控件，DataGrid包含DataGridItem，每个DataGridItem又包含TableCell，那么，我们就可以在TableCell的某个控件中，利用控件的Parent来得到TableCell，再利用TableCell的Parent，就可以得到DataGridItem了。</P>
<DIV class=code>protected void ddl_SelectedIndexChanged(object sender, System.EventArgs e) //一定要声明成protected或者public，不能是private的。<BR>{<BR>DropDownList ddl = (DropDownList)sender;<BR>TableCell cell = (TableCell)ddl.Parent;<BR>DataGridItem item = (DataGridItem)cell.Parent;<BR>Response.Write(item.Cells[0].Text);<BR>}</DIV>
<P><STRONG>4、怎样得到Header、Footer、Pager里的控件</STRONG></P>
<P>方法一：在ItemCreated或者ItemDataBound中，具体代码就不在多写了</P>
<P>方法二：遍历DataGrid的所有Item(注意，不是遍历DataGrid1.Items下的Item)</P>
<DIV class=code>foreach (DataGridItem item in DataGrid1.Controls[0].Controls)<BR>{<BR>if (item.ItemType == ListItemType.Header)<BR>{<BR>//用item.FindControl查找相应的控件<BR>}<BR>}</DIV>
<P>大家可能会注意到，这里有个DataGrid1.Controls[0].Controls，这表示，DataGrid1下，有一个子控件，这个子控件是DataGridTable类型，他下面才是DataGridItem集合</P>
<P>在DataList中，下面的子控件直接就是DataListItem了，而没有Table：</P>
<DIV class=code>foreach (DataListItem item in DataList1.Controls)<BR>{<BR>//....<BR>} </DIV></DIV><img src ="http://www.blogjava.net/Daniel2005/aggbug/20976.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2005-11-22 15:58 <a href="http://www.blogjava.net/Daniel2005/articles/20976.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP中如何调用存储过程</title><link>http://www.blogjava.net/Daniel2005/articles/20871.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Tue, 22 Nov 2005 01:08:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/20871.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/20871.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/20871.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/20871.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/20871.html</trackback:ping><description><![CDATA[&nbsp;1, 这也是最简单的方法,两个输入参数，无返回值：<BR>set connection = server.createobject("adodb.connection")<BR>connection.open someDSN <BR>Connection.Execute "procname varvalue1, varvalue2"<BR><BR>'将所有对象清为nothing，释放资源<BR>connection.close<BR>set connection = nothing<BR><BR><BR>2, 如果要返回 Recordset 集:<BR>set connection = server.createobject("adodb.connection")<BR>connection.open someDSN <BR>set rs = server.createobject("adodb.recordset")<BR>rs.Open "Exec procname varvalue1, varvalue2",connection<BR><BR>'将所有对象清为nothing，释放资源<BR>rs.close<BR>connection.close<BR>set rs = nothing<BR>set connection = nothing<BR><BR><BR>3, 以上两种方法都不能有返回值，（Recordset除外），如果要得到返回值，需要用Command的方法。<BR>首先说明，返回值有两种。一种是在存储过程中直接return一个值，就象C和VB的函数返回值那样；<BR>另一种是可以返回多个值，存储这些值的变量名称需要在调用参数中先行指定。<BR>这个例子要处理多种参数，输入参数，输出参数，返回记录集以及一个直接返回值（够全了吧？）<BR>存储过程如下：<BR><BR>use pubs<BR>GO<BR><BR>-- 建立存储过程<BR>create procedure sp_PubsTest<BR><BR>-- 定义三个参数变量，注意第三个，特别标记是用于输出<BR>@au_lname varchar (20), <BR>@intID int,<BR>@intIDOut int OUTPUT<BR><BR>AS<BR><BR>SELECT @intIDOut = @intID + 1<BR><BR>SELECT * <BR>FROM authors <BR>WHERE au_lname LIKE @au_lname + '%'<BR><BR>--直接返回一个值<BR>RETURN @intID + 2<BR><BR><BR>调用该存储过程的asp程序如下：<BR><BR>&lt;%@ Language=VBScript %&gt;<BR>&lt;%<BR>Dim CmdSP<BR>Dim adoRS<BR>Dim adCmdSPStoredProc<BR>Dim adParamReturnValue<BR>Dim adParaminput<BR>Dim adParamOutput<BR>Dim adInteger<BR>Dim iVal<BR>Dim oVal<BR>Dim adoField<BR>Dim adVarChar<BR><BR>‘这些值在 VB 中是预定义常量，可以直接调用，但在 VBScript 中没有预定义<BR>adCmdSPStoredProc = 4<BR>adParamReturnValue = 4<BR>adParaminput = 1<BR>adParamOutput = 2<BR>adInteger = 3<BR>adVarChar = 200<BR><BR>iVal = 5<BR>oVal = 3<BR><BR>'建一个command对象<BR>set CmdSP = Server.CreateObject("ADODB.Command")<BR><BR>'建立连结<BR>CmdSP.ActiveConnection = "Driver={SQL Server};server=(local);Uid=sa;Pwd=;Database=Pubs"<BR><BR>'定义command 对象调用名称 <BR>CmdSP.CommandText = "sp_PubsTest"<BR><BR>'设置command调用类型是存储过程 (adCmdSPStoredProc = 4)<BR>CmdSP.CommandType = adCmdSPStoredProc<BR><BR>'往command 对象中加参数<BR>'定义存储过程有直接返回值，并且是个整数，省缺值是4<BR>CmdSP.Parameters.Append CmdSP.CreateParameter("RETURN_VALUE", adInteger, adParamReturnValue, 4)<BR>'定义一个字符型输入参数<BR>CmdSP.Parameters.Append CmdSP.CreateParameter("@au_lname", adVarChar, adParaminput, 20, "M")<BR>'定义一个整型输入参数<BR>CmdSP.Parameters.Append CmdSP.CreateParameter("@intID", adInteger, adParamInput, , iVal)<BR>'定义一个整型输出参数<BR>CmdSP.Parameters.Append CmdSP.CreateParameter("@intIDOut", adInteger, adParamOutput, oVal)<BR><BR>'运行存储过程，并得到返回记录集<BR>Set adoRS = CmdSP.Execute<BR><BR><BR>'把每个记录打印出来，其中的字段是虚拟的，可以不用管<BR>While Not adoRS.EOF<BR><BR>for each adoField in adoRS.Fields<BR>Response.Write adoField.Name &amp; "=" &amp; adoField.Value &amp; "&lt;br&gt;" &amp; vbCRLF<BR>Next<BR>Response.Write "&lt;br&gt;"<BR>adoRS.MoveNext<BR>Wend<BR><BR>'打印两个输出值：<BR>Response.Write "&lt;p&gt;@intIDOut = “ &amp; CmdSP.Parameters("@intIDOut").Value &amp; "&lt;/p&gt;"<BR>Response.Write "&lt;p&gt;Return value = " &amp; CmdSP.Parameters("RETURN_VALUE").Value &amp; "&lt;/p&gt;"<BR><BR><BR>'大扫除<BR>Set adoRS = nothing<BR>Set CmdSP.ActiveConnection = nothing<BR>Set CmdSP = nothing<BR>%&gt;<BR><img src ="http://www.blogjava.net/Daniel2005/aggbug/20871.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2005-11-22 09:08 <a href="http://www.blogjava.net/Daniel2005/articles/20871.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在VB.NET中当鼠标移入DataGird时背景色发生变化！</title><link>http://www.blogjava.net/Daniel2005/articles/20299.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Thu, 17 Nov 2005 10:52:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/20299.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/20299.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/20299.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/20299.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/20299.html</trackback:ping><description><![CDATA[<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;只须在DataGrid的ItemDataBound事件中加入以下代码！！！！<BR>Private Sub dgRides_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DataGridItemEventArgs) Handles dgRides.ItemDataBound<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If e.Item.ItemType = ListItemType.AlternatingItem Or e.Item.ItemType = ListItemType.Item Then</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Item.Attributes.Add("onmouseover", "currentcolor=this.style.backgroundColor;this.style.backgroundColor='LightSeaGreen'")<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; e.Item.Attributes.Add("onmouseout", "this.style.backgroundColor=currentcolor")</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; End If<BR>&nbsp;&nbsp;&nbsp; End Sub</P><img src ="http://www.blogjava.net/Daniel2005/aggbug/20299.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2005-11-17 18:52 <a href="http://www.blogjava.net/Daniel2005/articles/20299.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Asp无组件上传进度条解决方案</title><link>http://www.blogjava.net/Daniel2005/articles/20234.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Thu, 17 Nov 2005 06:31:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/20234.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/20234.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/20234.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/20234.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/20234.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 
<H3>一、无组件上传的原理</H3>
<P>我还是一点一点用一个实例来说明的吧，客户端HTML如下。要浏览上传附件，我们通过&lt;input type="file"&gt;元素，但是一定要注意必须设置form的enctype属性为"multipart/form-data"： <PRE class=code><CODE>
&lt;form method="post" action="upload.asp" enctype="multipart/form-data"&gt;
 &lt;label&gt;
  &lt;input type="file" name="file1" /&gt;
 &lt;/label&gt;
 &lt;br /&gt;
 &lt;input type="text" name="filename" value="default filename"/&gt;
 &lt;br /&gt;
 &lt;input type="submit" value="Submit"/&gt;
 &lt;input type="reset" value="Reset"/&gt;
&lt;/form&gt;
</CODE>
</PRE>在后台asp程序中，以前获取表单提交的ASCII 数据，非常的容易。但是如果需要获取上传的文件，就必须使用Request对象的BinaryRead方法来读取。BinaryRead方法是对当前输入流进行指定字节数的二进制读取，有点需要注意的是，一旦使用BinaryRead 方法后，再也不能使用Request.Form 或 Request.QueryString 集合了。结合Request对象的TotalBytes属性，可以将所有表单提交的数据全部变成二进制，不过这些数据都是经过编码的。首先让我们来看看这些数据是如何编码的，有无什么规律可循，编段代码，在代码中我们将BinaryRead读取的二进制转化为文本，输出出来，在后台的upload.asp中（注意该示例不要上传大文件，否则可能会造成浏览器死掉）： <PRE class=code>&lt;%
Dim biData, PostData
Size = Request.TotalBytes
biData = Request.BinaryRead(Size)
PostData = BinaryToString(biData,Size)
Response.Write "&lt;pre&gt;" &amp; PostData &amp; "&lt;/pre&gt;"  '使用pre，原样输出格式
' 借助RecordSet将二进制流转化成文本
Function BinaryToString(biData,Size) 
 Const adLongVarChar = 201
 Set RS = CreateObject("ADODB.Recordset")
 RS.Fields.Append "mBinary", adLongVarChar, Size
 RS.Open
 RS.AddNew
  RS("mBinary").AppendChunk(biData)
 RS.Update
 BinaryToString = RS("mBinary").Value
 RS.Close
End Function 
%&gt;
</PRE>
<P></P>
<P>简单起见，上传一个最简单的文本文件(G:\homepage.txt，内容为"宝玉：http://www.webuc.net")来试验一下，文本框filename中保留默认值"default filename"，提交看看输出结果： <PRE class=code>-----------------------------7d429871607fe
Content-Disposition: form-data; name="file1"; filename="G:\homepage.txt"
Content-Type: text/plain
宝玉：http://www.webuc.net
-----------------------------7d429871607fe
Content-Disposition: form-data; name="filename"
default filename
-----------------------------7d429871607fe--
</PRE>可以看出来对于表单中的项目，是用过"-----------------------------7d429871607fe"这样的边界来分隔成一块一块的，每一块的开始都有一些描述信息，例如：Content-Disposition: form-data; name="filename"，在描述信息中，通过name="filename"可以知道表单项的name。如果有filename="G:\homepage.txt"这样的内容，说明是一个上传的文件，如果是一个上传的文件，那么描述信息会多一行Content-Type: text/plain来描述文件的Content-Type。描述信息和主体信息之间是通过换行来分隔的。 
<P></P>
<P>嗯，基本上清晰了，根据这个规律我们就知道该怎么来分离数据，再对分离的数据进行处理了，不过差点忽略一个问题，就是边界值(上例中的"-----------------------------7d429871607fe")是怎么知道的？每次上传这个边界值是不一样的，还好还好asp中可以通过Request.ServerVariables( "HTTP_CONTENT_TYPE")来获之，例如上例中HTTP_CONTENT_TYPE内容为："multipart/form-data; boundary=---------------------------7d429871607fe"，有了这个，我们不仅可以判断客户端的form中有无使用enctype="multipart/form-data"(如果没有使用，那么下面就没必要执行啦)，还可以获取边界值boundary=---------------------------7d429871607fe。（注意：这里获取的边界值比上面的边界值开头要少"--"，最好补充上。） </P>
<P>至于如何分析数据的过程我就不多赘述了，无非就是借助InStr,Mid等这样的函数来分离出来我们想要的数据。</P>
<H3>二、分块上传，记录进度</H3>
<P>要实时反映进度条，实质就是要实时知道当前服务器获取了多少数据？再回想一下我们实现上传的过程，我们是通过Request.BinaryRead(Request.TotalBytes)来实现的，在Request的过程中我们无法得知当前服务器获取了多少数据。所以只能通过变通的方法了，如果我们可以将获取的数据分成一块一块的，然后根据已经上传的块数我们就可以算出来当前上传了多大了！也就是说，如果我1K为1块，那么上传1MB的输入流就分成1024块来获取，例如我当前已经获取了100块，那么就表明当前上传了100K。当我提出分块的时候很多人觉得不可思议，因为他们都忽略BinaryRead方法不仅是可以读取指定大小，而且可以连续读取的。</P>
<P>写个例子来验证一下分块读取的完整性，在刚才的例子基础上（注意该示例不要上传大文件，否则可能会造成浏览器死掉）： <PRE class=code>&lt;%
Dim biData, PostData, TotalBytes, ChunkBytes
ChunkBytes = 1 * 1024     ' 分块大小为1K
TotalBytes = Request.TotalBytes  ' 总大小
PostData = ""         ' 转化为文本类型后的数据
ReadedBytes = 0        ' 初始化为0
' 分块读取
Do While ReadedBytes &lt; TotalBytes
 biData = Request.BinaryRead(ChunkBytes)  ' 当前块
 PostData = PostData &amp; BinaryToString(biData,ChunkBytes) ' 将当前块转化为文本并拼接
 ReadedBytes = ReadedBytes + ChunkBytes ' 记录已读大小
 If ReadedBytes &gt; TotalBytes Then ReadedBytes = TotalBytes
Loop
Response.Write "&lt;pre&gt;" &amp; PostData &amp; "&lt;/pre&gt;"  ' 使用pre，原样输出格式
' 将二进制流转化成文本
Function BinaryToString(biData,Size) 
 Const adLongVarChar = 201
 Set RS = CreateObject("ADODB.Recordset")
 RS.Fields.Append "mBinary", adLongVarChar, Size
 RS.Open
 RS.AddNew
  RS("mBinary").AppendChunk(biData)
 RS.Update
 BinaryToString = RS("mBinary").Value
 RS.Close
End Function 
%&gt;
</PRE>试验一下上传刚才的文本文件，输出结果证明这样分块读取的内容是完整的，并且在While循环中，我们可以在每次循环时将当前状态记录到Application中，然后我们就可以通过访问该Application动态获取上传进度条。 
<P></P>
<P>另：上例中是通过字符串拼接的，如果是要拼接二进制数据，可以通过ADODB.Stream对象的Write方法，示例代码如下： <PRE class=code>Set bSourceData = createobject("ADODB.Stream")
bSourceData.Open
bSourceData.Type = 1 'Binary
Do While ReadedBytes &lt; TotalBytes
 biData = Request.BinaryRead(ChunkBytes)
 bSourceData.Write biData ' 直接使用write方法将当前文件流写入bSourceData中
 ReadedBytes = ReadedBytes + ChunkBytes
 If ReadedBytes &gt; TotalBytes Then ReadedBytes = TotalBytes
 Application("ReadedBytes") = ReadedBytes
Loop
</PRE>
<P></P>
<H3>三、保存上传的文件</H3>通过Request.BinaryRead获取提交数据，分离出上传文件后，根据数据类型的不同，保存方式也不同：<BR>
<UL>
<LI>对于二进制数据，可以直接通过ADODB.Stream对象的SaveToFile方法，将二进制流保存成为文件。 
<LI>对于文本数据，可以通过TextStream对象的Write方法，将文本数据保存到文件中。 </LI></UL>
<P>对于文本数据和二进制数据，是可以方便的相互转换的，对于上传小文件来说，两者基本上没什么差别。但是两种方式保存时还是有一些差别的，对于ADODB.Stream对象，必须将所有数据全部装载完才可以保存成文件，所以使用这种方式如果上传大文件将很占用内存，而对于TextStream对象，可以在文件创建好后，一次Write一部分，分多次Write，这样的好处是不会占用服务器内存空间，结合上面分析的分块获取数据原理，我们可以每获取一块上传数据就将之Write到文件中。我曾做过试验，同样本机上传一个200多MB的文件，使用第一种方式内存一直在涨，到最后直接提示计算机虚拟内存不足，最可恨是即使进度条表示文件已经上传完，但是最终文件还是没有保存上。而使用后一种方法，上传过程中内存基本上无什么变化。</P>
<H3>四、未解决的难题</H3>
<P>我在博客园上看到Bestcomy描述他的Asp.Net上传组件是可以和Sever.SetTimeOut无关的，而在Asp中我是没能做到，对于上传大文件，就只有将Server.SetTimeOut设置为一个很大的值才可以。不知道有没有比较好的解决方法。</P>
<P>如果我们在保存文件时，使用TextStream对象的Write方法，那么如果用户上传时中断了文件传输，已经上传的那部分文件还是在的，如果可以断点续传就好了。关键问题是Request.BinaryRead方法虽然可以分块读取，但是却不能跳过某一段读取！</P>
<H3>五、结束语</H3>
<P>原理基本上是说清楚了，但是实际代码要比这复杂的多，要考虑很多问题，最麻烦在分析数据那部分，对于每一块获取的数据，要分析是不是属于描述信息，是表单项目还是上传的文件，文件是否已经上传结束…… </P>
<P>相信根据上面的描述，您也可以开发出您自己功能强大的无组件上传组件。我想更多的人关心的只是代码，而不会自己动手去写的，也许没有时间，也许水平还不够，更多的只是已经成为了一种习惯……我在CSDN上见过太多技术八股文——一段说明，然后全是代码。授人以鱼不若授人以渔，给你一个代码，也许你并不会去思考为什么，直接拿去用，当下次碰到类似的问题的时候，还是不知道为什么，希望此文能让更多人学到点什么，最重要是“悟”到点什么！ </P>
<P>完整代码整理完善中……</P><img src ="http://www.blogjava.net/Daniel2005/aggbug/20234.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2005-11-17 14:31 <a href="http://www.blogjava.net/Daniel2005/articles/20234.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DataGrid同时具有分页和排序功能及注意点</title><link>http://www.blogjava.net/Daniel2005/articles/20176.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Thu, 17 Nov 2005 01:10:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/20176.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/20176.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/20176.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/20176.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/20176.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当DataGrid同时具有分页和排序功能时应注意在重新绑定数据源时，MyDataGrid.CurrentPageIndex=0; <BR>下面给实现以上功能的原码，也就不多缀了aspx中包含有DataGrid和控制其数据源变化的dropdownlist <BR>DataGrid代码 <BR>&lt;asp:datagrid id="MyDataGrid" runat="server" BorderColor="#CCCCCC" Font-Size="100%" HorizontalAlign="Center" <BR>AutoGenerateColumns="False" OnDeleteCommand="MyDataGrid_Delete" OnSortCommand="Sort_Grid" OnPageIndexChanged="MyDataGrid_PageIndexChanged" <BR>DataKeyField="ACC_NO" PagerStyle-Position="Bottom" PagerStyle-HorizontalAlign="Center" PagerStyle-Mode="NextPrev" <BR>PageSize="10" AllowSorting="True" AllowPaging="True" CellPadding="4" Width="100%"&gt; <BR>&lt;AlternatingItemStyle BackColor="#E9E9E6"&gt;&lt;/AlternatingItemStyle&gt; <BR>&lt;HeaderStyle Font-Bold="True" Wrap="False" ForeColor="White" BackColor="#999999"&gt;&lt;/HeaderStyle&gt; <BR>&lt;Columns&gt; <BR>&lt;asp:ButtonColumn Text="口" CommandName="Delete"&gt;&lt;/asp:ButtonColumn&gt; <BR>&lt;asp:BoundColumn DataField="NO" SortExpression="NO" ReadOnly="True" HeaderText="序号"&gt;&lt;/asp:BoundColumn&gt; <BR>&lt;asp:BoundColumn DataField="ID" SortExpression="ID" HeaderText="ID"&gt;&lt;/asp:BoundColumn&gt; <BR>&lt;asp:BoundColumn DataField="NAME" SortExpression="NAME" HeaderText="名称"&gt;&lt;/asp:BoundColumn&gt; <BR>&lt;asp:BoundColumn DataField="C_NAME" SortExpression="C_NAME" HeaderText="各科名称"&gt;&lt;/asp:BoundColumn&gt; <BR>&lt;asp:BoundColumn DataField="FLG" SortExpression="FLG" HeaderText="项目"&gt;&lt;/asp:BoundColumn&gt; <BR>&lt;/Columns&gt; <BR>&lt;PagerStyle NextPageText="下10件" PrevPageText="返回" HorizontalAlign="Center"&gt;&lt;/PagerStyle&gt; <BR>&lt;/asp:datagrid&gt; <BR><BR><BR>dropdownlist代码 <BR>&lt;asp:dropdownlist id="ddlWk" Runat="server" AutoPostBack="True" Enabled="False"&gt; <BR>&lt;asp:ListItem Value="0"&gt;东京&lt;/asp:ListItem&gt; <BR>&lt;asp:ListItem Value="3"&gt;九州&lt;/asp:ListItem&gt; <BR>&lt;asp:ListItem Value="8"&gt;北海道&lt;/asp:ListItem&gt; <BR>&lt;asp:ListItem Value="9"&gt;四国&lt;/asp:ListItem&gt; <BR>&lt;/asp:dropdownlist&gt; <BR><BR><BR><BR>aspx.cs文件代码核心如下： <BR>private void Page_Load(object sender, System.EventArgs e) <BR>{ <BR>if(!IsPostBack) <BR>{ <BR>Session["WP"] ="0"; <BR>ddlWk_getS(); <BR>BindGrid(); <BR>} <BR>} <BR>private void ddlWk_getS() <BR>{ <BR>switch (Session["WP"].ToString()) <BR>{ <BR>case "0":ddlWk.SelectedIndex=0; <BR>break; <BR>case "3":ddlWk.SelectedIndex=1; <BR>break; <BR>case "8":ddlWk.SelectedIndex=2; <BR>break; <BR>case "9":ddlWk.SelectedIndex=3; <BR>break; <BR>default:ddlWk.SelectedIndex=0; <BR>break; <BR>} <BR>} <BR>protected void BindGrid() <BR>{ <BR>MyDataGrid.DataSource=GetData().Tables["vCO"].DefaultView; <BR>MyDataGrid.DataBind(); <BR>//COUNT.Text=MyDataGrid.Columns.Count.ToString(); <BR>} <BR><BR>/// &lt;summary&gt; <BR>/// 返回Data <BR>/// &lt;/summary&gt; <BR>///&lt;returns&gt;&lt;/returns&gt; <BR>private DataSet GetData() <BR>{ <BR>string strConn=(String) ((NameValueCollection) Context.GetConfig("system.web/database"))["strConn"]; <BR>using (SqlConnection conn = new SqlConnection(strConn)) <BR>{ <BR>SqlCommand cmd = new SqlCommand("sp_C",conn); <BR>cmd.CommandType=CommandType.StoredProcedure; <BR>cmd.Parameters.Add("@place",SqlDbType.VarChar,2); <BR>cmd.Parameters["@place"].Value=Session["WP"].ToString(); <BR>conn.Open(); <BR><BR>SqlDataAdapter da = new SqlDataAdapter(); <BR>da.SelectCommand=cmd; <BR>DataSet ds=new DataSet(); <BR>da.Fill(ds,"vCO"); <BR>Count.Text="ヒット："+ds.Tables["vCO"].Rows.Count.ToString()+"件"; <BR>return ds; <BR>} <BR><BR>} <BR>/// &lt;summary&gt; <BR>///从DataSet中除一 <BR>/// &lt;/summary&gt; <BR>/// &lt;param name="sender"&gt;&lt;/param&gt; <BR>/// &lt;param name="E"&gt;&lt;/param&gt; <BR>protected void MyDataGrid_Delete(Object sender, DataGridCommandEventArgs E) <BR>{ <BR>String strID=MyDataGrid.DataKeys[(int)E.Item.ItemIndex].ToString(); <BR>//删除操作 <BR>} <BR>/// &lt;summary&gt; <BR>/// 分页操作 <BR>/// &lt;/summary&gt; <BR>/// &lt;param name="sender"&gt;&lt;/param&gt; <BR>/// &lt;param name="e"&gt;&lt;/param&gt; <BR>protected void MyDataGrid_PageIndexChanged(object source, DataGridPageChangedEventArgs e) <BR>{ <BR>MyDataGrid.CurrentPageIndex=e.NewPageIndex; <BR>BindGrid(); <BR>} <BR>/// &lt;summary&gt; <BR>/// 排序 <BR>/// &lt;/summary&gt; <BR>/// &lt;param name="sender"&gt;&lt;/param&gt; <BR>/// &lt;param name="e"&gt;&lt;/param&gt; <BR>protected void Sort_Grid(object sender, DataGridSortCommandEventArgs e) <BR>{ <BR>DataView dv= new DataView(GetData().Tables["vCO"]); <BR>dv.Sort= e.SortExpression.ToString(); <BR>MyDataGrid.DataSource=dv; <BR>MyDataGrid.DataBind(); <BR>} <BR><BR>#region Web override protected void OnInit(EventArgs e) <BR>{ <BR>// // <BR>InitializeComponent(); <BR>base.OnInit(e); <BR>} <BR><BR>/// &lt;summary&gt; /// &lt;/summary&gt; <BR>private void InitializeComponent() <BR>{ <BR>this.ddlWk.SelectedIndexChanged += new System.EventHandler(this.ddlWk_SelectedIndexChanged); <BR>this.Load += new System.EventHandler(this.Page_Load); <BR><BR>} <BR>#endregion <BR><BR>private void ddlWk_SelectedIndexChanged(object sender, System.EventArgs e) <BR>{ <BR>Session["WP"]=ddlWk.SelectedValue; <BR>MyDataGrid.CurrentPageIndex=0;//没有这一句，当该页码超出其他数据源的范围时会出错 <BR>BindGrid(); <BR>Response.Write( "&lt;script language=''javascript''&gt;parent.menuframe.location.reload();&lt;/script&gt;"); <BR><BR>} <BR><img src ="http://www.blogjava.net/Daniel2005/aggbug/20176.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2005-11-17 09:10 <a href="http://www.blogjava.net/Daniel2005/articles/20176.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>（ASP.NET）用动态属性和DataView实现DataGrid的双向排序</title><link>http://www.blogjava.net/Daniel2005/articles/20175.html</link><dc:creator>泌鲁沙夫</dc:creator><author>泌鲁沙夫</author><pubDate>Thu, 17 Nov 2005 01:09:00 GMT</pubDate><guid>http://www.blogjava.net/Daniel2005/articles/20175.html</guid><wfw:comment>http://www.blogjava.net/Daniel2005/comments/20175.html</wfw:comment><comments>http://www.blogjava.net/Daniel2005/articles/20175.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Daniel2005/comments/commentRss/20175.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Daniel2005/services/trackbacks/20175.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; DataGrid是ASP.NET中非常重要的一个控件。它能方便的让我们实现编辑、排序功能；但是排序功能默认的是升序（ASC），能不能让DataGrid同时实现升降序排列呢？这篇文章将给你一个比较好的解决方法。&nbsp;下面的例子将告诉你如何给DataGrid动态添加...&nbsp;&nbsp;<a href='http://www.blogjava.net/Daniel2005/articles/20175.html'>阅读全文</a><img src ="http://www.blogjava.net/Daniel2005/aggbug/20175.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Daniel2005/" target="_blank">泌鲁沙夫</a> 2005-11-17 09:09 <a href="http://www.blogjava.net/Daniel2005/articles/20175.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>