﻿<?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-网摘-文章分类-ASP.NET</title><link>http://www.blogjava.net/jvict/category/34372.html</link><description /><language>zh-cn</language><lastBuildDate>Sun, 16 May 2010 00:56:53 GMT</lastBuildDate><pubDate>Sun, 16 May 2010 00:56:53 GMT</pubDate><ttl>60</ttl><item><title>OWC做电子表格和图表的试验 [转]</title><link>http://www.blogjava.net/jvict/articles/320211.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 06 May 2010 07:36:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/320211.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/320211.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/320211.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/320211.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/320211.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文：http://www.cnblogs.com/salonliudong/archive/2008/05/23/1206180.html&nbsp;连续这么多天持续写SQL，晚上找资料研究一下Microsoft Office Web Components（续上一篇Excel的文章）调节一下自己，和上一篇文章的主题一样，这篇主要研究OWC做报表的方法。先看一下示例的效果：...&nbsp;&nbsp;<a href='http://www.blogjava.net/jvict/articles/320211.html'>阅读全文</a><img src ="http://www.blogjava.net/jvict/aggbug/320211.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-05-06 15:36 <a href="http://www.blogjava.net/jvict/articles/320211.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OWC-Excel电子表格应用收藏</title><link>http://www.blogjava.net/jvict/articles/320206.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 06 May 2010 07:09:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/320206.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/320206.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/320206.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/320206.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/320206.html</trackback:ping><description><![CDATA[<p><a href="http://blog.csdn.net/RainyLin/archive/2008/09/08/2899754.aspx">原文：http://blog.csdn.net/RainyLin/archive/2008/09/08/2899754.aspx</a><br />
<br />
1、引入OWC组件。（右键单击工程名在下拉菜单中选择&#8220;add Reference...&#8221;，在弹出界面选择"COM"，选择"Microsoft Office web components11.0",点击&#8220;ok&#8221;, 即可。），完成以上后就可以在工程的Reference下看到&#8220;OWC11&#8221;了。<br />
2、在页面中添加&#8220;using Microsoft.Office.Interop.Owc11；&#8221;；<br />
3、现在就可以在页面中添加一个相应的对象了。例如Spreadsheet: &lt;object id="Spreadsheet1" classid=""&gt;&lt;/Object&gt;" 就可以了。当然也可以在code部份new一个对象：&#8220; Microsoft.Office.Interop.Owc11.Spreadsheet dd = new Microsoft.Office.Interop.Owc11.Spreadsheet();（在code中还没研究会怎么个用法。）&#8221;;<br />
4、这一步是用js写的。只是初步形成一个有数据的表格。在js code中添加一个load()，load中添加:<br />
Spreadsheet1.Activesheet.Cells(1,1).Value="第一格";<br />
Spreadsheet1.Activesheet.Cells(2,1).Value="第二格";&nbsp; <br />
Spreadsheet1.Activesheet.Cells(3,1).Value="第三格"; <br />
然后在body中加入 onload="return load()" 即：&lt;body onload="return load()"&gt; ;<br />
生成即可。<br />
上面写的是最简单的一个sample。<br />
整体代码如下：<br />
&nbsp;</p>
<p>&lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication2._Default" %&gt;</p>
<p>&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;</p>
<p>&nbsp;&lt;html xmlns="http://www.w3.org/1999/xhtml" &gt;</p>
<p>&lt;head id="Head1" runat="server"&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;title&gt;Untitled Page&lt;/title&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; &lt;script language="javascript"&gt;&nbsp; </p>
<p>&nbsp; </p>
<p>&nbsp;&nbsp; </p>
<p>&nbsp;function&nbsp;&nbsp; onload()&nbsp;&nbsp; {&nbsp; </p>
<p>&nbsp;alert("start");&nbsp; </p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp; var&nbsp;&nbsp; Spreadsheet1&nbsp;&nbsp; =&nbsp;&nbsp; document.all("Spreadsheet1");&nbsp; </p>
<p>&nbsp;&nbsp; alert(Spreadsheet1);</p>
<p>&nbsp;&nbsp; Spreadsheet1.ActiveSheet.Cells(1,1).Value="0.13"</p>
<p>&nbsp;&nbsp; Spreadsheet1.ActiveSheet.Cells(1,2).Value="0.23"</p>
<p>&nbsp;&nbsp; Spreadsheet1.ActiveSheet.Cells(1,3).Value="0.33"</p>
<p>&nbsp;&nbsp; Spreadsheet1.ActiveSheet.Cells(1,4).Value="0.43"</p>
<p>&nbsp;&nbsp;&nbsp; Spreadsheet1.ActiveSheet.Cells(2,1).Value="2.13"</p>
<p>&nbsp;&nbsp; Spreadsheet1.ActiveSheet.Cells(2,2).Value="2.23"</p>
<p>&nbsp;&nbsp; Spreadsheet1.ActiveSheet.Cells(2,3).Value="2.33"</p>
<p>&nbsp;&nbsp; Spreadsheet1.ActiveSheet.Cells(3,4).Value="2.43"</p>
<p>&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp; alert(Spreadsheet1.XMLData);</p>
<p>&nbsp;alert("End");&nbsp; </p>
<p>&nbsp;}&nbsp; </p>
<p>&nbsp;&lt;/script&gt;&nbsp; </p>
<p>&lt;/head&gt;</p>
<p>&lt;body onload="return onload()"&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;form id="form1" runat="server"&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;div&gt;</p>
<p>&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; &lt;/div&gt;</p>
<p>&nbsp;&nbsp;&nbsp; &lt;/form&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; &lt;OBJECT&nbsp;&nbsp; id="Spreadsheet1"&nbsp;&nbsp; classid="clsid:0002E559-0000-0000-C000-000000000046"&nbsp;&nbsp; name="Spreadsheet1" style="width:100%;height:421px" &gt;&nbsp; </p>
<p>&nbsp;&nbsp; </p>
<p>&nbsp;&lt;/OBJECT&gt;</p>
<p>&lt;/body&gt;</p>
<p>&lt;/html&gt;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 技术要点<br />
1.1.&nbsp;&nbsp;&nbsp; Excel试验：<br />
A.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel嵌入网页的方法。</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在后台用流的方式返回给前台页面展现；</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在后台讲Excel格式数据定好保存到本地，在前台页面用html标签加载展示；</p>
<p>B.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel显示格式的控制。</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel单元格格式设置，默认为常规类型；</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 上下标格式的控制；</p>
<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格水平垂直对齐方式；</p>
<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格边框设置；</p>
<p>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格合并；</p>
<p>6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 字体设置，包括字体的颜色、大小、粗体、斜体、字体、下划线等；</p>
<p>7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 冻结行列；</p>
<p>8.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 公式栏的显示与隐藏；</p>
<p>9.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 行标题和列表题的显示与隐藏；</p>
<p>10.&nbsp;&nbsp;&nbsp; 网格的显示与隐藏；</p>
<p>11.&nbsp;&nbsp;&nbsp; 水平滚动条和垂直滚动条的显示与隐藏；</p>
<p>12.&nbsp;&nbsp;&nbsp; Sheet页的显示与隐藏；</p>
<p>C.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 向Excel中填充数据，并导出为临时文件。</p>
<p>1.2.&nbsp;&nbsp;&nbsp; OWC试验：<br />
A.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OWC组件在web页面展示的方法。</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将OWC中Sheet导出为本地Excel文件，再将导出的文件呈现到Web页面；</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 后台把配置好的Sheet直接以流文件方式返回到Web页面展现；</p>
<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用html标签将OWC展现在Web页面，加载后台程序导出到本地的文件（xml、html、csv格式）来显示数据；</p>
<p>B.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在OWC中的电子表格类中填充数据的方法。</p>
<p>C.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OWC中显示数据格式的控制。</p>
<p>1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 电子表格外观控制：工具栏的显示、Office图标的显示、列标题的显示、行标题的显示、水平滚动条的显示、垂直滚动条的显示、网格的显示、网格颜色设置；</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格水平对齐方式；</p>
<p>3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格垂直对齐方式；</p>
<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格合并；</p>
<p>5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格字体设置：字体、字形、字号、字体颜色、字体加粗、下划线（多种样式）；</p>
<p>6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格边框设置；</p>
<p>2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 主要模块<br />
2.1.&nbsp;&nbsp;&nbsp; Excel<br />
1、Excel嵌入网页的方法：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A、将后台定制好的Excel文件在后台用流的方式返回给前台页面展现，代码如下：</p>
<p>Response.ClearContent();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ClearHeaders();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ContentType = "application/vnd.ms-excel";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.AddHeader("Content-Disposition", "inline;filename='我的文件'");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.WriteFile(FileName);//FileName为Excel文件所在地址</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Flush();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Close();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行效果：整个页面都充满了Excel。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; B、在前台页面框架中直接加在，代码：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;iframe id="myExcelHtml" src ="Nomarl.xls" width = "600" height ="300" align ="middle"&gt; &lt;/iframe&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 运行效果：可随意控制Excel在页面的显示位置。</p>
<p>2、 Excel显示格式控制。</p>
<p>A、Excel单元格格式设置，默认为常规类型；</p>
<p>代码：</p>
<p>Excel.Range r = mySheet.get_Range(mySheet.Cells[1, 1], mySheet.Cells[DT.Rows.Count + 2, DT.Columns.Count - 3]);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置单元格格式为文本类型，文本类型可设置上下标</p>
<p>r.NumberFormat = "@";</p>
<p>//设置单元格格式为数值类型，小数点后2位</p>
<p>r.NumberForma = "0.00_ "</p>
<p>&nbsp;&nbsp;&nbsp; //设置单元格格式为货币类型，小数点后2位</p>
<p>&nbsp;r.NumberForma = "￥#,##0.00;￥-#,##0.00"</p>
<p>&nbsp;&nbsp;&nbsp; //设置单元格格式为会计专用类型，小数点后2位</p>
<p>&nbsp;r.NumberForma = _"_ ￥* #,##0.00_ ;_ ￥* -#,##0.00_ ;_ ￥* ""-""??_ ;_ @_ "</p>
<p>&nbsp;&nbsp;&nbsp; //设置单元格格式为日期类型</p>
<p>&nbsp;r.NumberForma = "yyyy-m-d"</p>
<p>&nbsp;&nbsp;&nbsp; //设置单元格格式为时间类型</p>
<p>&nbsp;r.NumberForma = "[$-F400]h:mm:ss AM/PM"</p>
<p>&nbsp;&nbsp;&nbsp; //设置单元格格式为百分比类型，小数点后2位</p>
<p>&nbsp;r.NumberForma = "0.00%"</p>
<p>&nbsp;&nbsp;&nbsp; //设置单元格格式为分数类型，分母为一位数</p>
<p>&nbsp;r.NumberForma = "# ?/?"</p>
<p>&nbsp;&nbsp;&nbsp; //设置单元格格式为科学技术类型，小数位数为2</p>
<p>&nbsp;r.NumberForma = "0.00E+00"</p>
<p>&nbsp;&nbsp;&nbsp; //设置单元格格式为特殊类型</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; r.NumberForma = "000000"</p>
<p>B、上下标格式的控制；</p>
<p>代码：</p>
<p>//控制输出样式为下标</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[i + 3, DT.Columns.Count - 3], mySheet.Cells[i + 3, DT.Columns.Count - 3]).get_Characters(a.Length + 1, b.Length).Font.Subscript = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //控制输出样式为上标</p>
<p>&nbsp;mySheet.get_Range(mySheet.Cells[i + 3, DT.Columns.Count - 3], mySheet.Cells[i + 3, DT.Columns.Count - 3]).get_Characters(a.Length + b.Length + 1, c.Length).Font.Superscript = true;</p>
<p>C、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格水平垂直对齐方式；</p>
<p>代码：</p>
<p>//单元格水平，垂直居中</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r.HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; r.VerticalAlignment = Excel.XlVAlign.xlVAlignCenter;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 上面代码中，枚举XLHAlign的值还有：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 右对齐</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignRight,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 左对齐.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignLeft,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 两端对齐.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignJustify,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 分散对齐(缩进)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignDistributed,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 居中对齐</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignCenter,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 依照数据类型对齐,常规</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignGeneral,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 填充</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignFill,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 跨列对齐.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignCenterAcrossSelection = 7,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 枚举XLVAlign的值还有：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 靠上对齐</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlVAlignTop,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //两端对齐.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlVAlignJustify = -4130,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //分散对齐.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlVAlignDistributed,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //居中对齐.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlVAlignCenter,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //靠下对齐.</p>
<p>&nbsp;xlVAlignBottom = -4107,</p>
<p>D、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单元格边框设置；</p>
<p>代码：</p>
<p>//设置边框</p>
<p>&nbsp;Excel.Range r = mySheet.get_Range(mySheet.Cells[1, 1], mySheet.Cells[DT.Rows.Count + 2, DT.Columns.Count - 3]);</p>
<p>r.Borders.LineStyle = Excel.XlLineStyle.xlContinuous;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 枚举XlLineStyle中还有下面线形：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //没边框线</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlLineStyleNone,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //双线.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDouble,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //点状线.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDot,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //虚线.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDash,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //连续线.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlContinuous,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //点线交互型</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDashDot,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //两点一线型</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDashDotDot,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //斜线.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlSlantDashDot,</p>
<p>E、单元格合并</p>
<p>用get_Range方法获取要合并的单元格，再设置MergeCells属性的值进行合并。</p>
<p>代码：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //合并单元格</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.get_Range(myExcel.Cells[1, 1], myExcel.Cells[1,4]).MergeCells = true;</p>
<p>F、字体设置</p>
<p>先用get_Range方法选中要设置字体的某个单元格或者或者直接用get_Characters方法直接选中要设置的字符进行设置；</p>
<p>代码：</p>
<p>//加粗字体</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.get_Range(myExcel.Cells[1, 1], myExcel.Cells[1, 1]).Font.Bold = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体大小</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.get_Range(myExcel.Cells[1,1],myExcel.Cells[1,1]).Font.Size = 16;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体的颜色</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.get_Range(myExcel.Cells[1, 1], myExcel.Cells[1, 1]).Font.ColorIndex = 3;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.get_Range(myExcel.Cells[1, 1], myExcel.Cells[1, 1]).Font.Name = "隶书";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置成斜体</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.get_Range(myExcel.Cells[1, 1], myExcel.Cells[1, 1]).Font.Italic = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置下划线</p>
<p>myExcel.get_Range(myExcel.Cells[1, 1], myExcel.Cells[1, 1]).Font.Underline = true;</p>
<p>G、冻结行列</p>
<p>用get_Range方法获取单元格，再设置其Freezepanes属性为true，就把该单元格右上方的行和列都冻结了，取消冻结将其值设为false即可。</p>
<p>//冻结行列</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.get_Range(myExcel.Cells[3,1],myExcel.Cells[3,1]).Activate();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.ActiveWindow.FreezePanes = true;</p>
<p>H、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 公式输入栏的隐藏</p>
<p>//设置是否显示Excel公式输入栏，默认为true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.DisplayFormulaBar = false;</p>
<p>I、 列标题与行标题的隐藏</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置是否显示行和列的标题，默认为true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.ActiveWindow.DisplayHeadings = false;</p>
<p>J、网格的隐藏</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置是否显示网格，默认为true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.ActiveWindow.DisplayGridlines = false;</p>
<p>K、&nbsp; 水平、垂直滚动条的隐藏</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置是否显示水平滚动条</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.ActiveWindow.DisplayHorizontalScrollBar = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置是否显示垂直滚动条</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.ActiveWindow.DisplayVerticalScrollBar = false;</p>
<p>L、Sheet页的隐藏</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置是否显示Sheet页</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.ActiveWindow.DisplayWorkbookTabs = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 经过格式设置以后，展示在页面上的效果如下图：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />
3、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 向Excel中填充数据，并保存为临时文件</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 代码：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Application myExcel = new Excel.Application();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打开模板文件</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.Application.Workbooks.Open(mode.FullName, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing, missing);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //选中有数据的Cells</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Workbook myBook = myExcel.Workbooks[1];</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Worksheet mySheet = (Excel.Worksheet)myBook.Worksheets[1];</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Range r = mySheet.get_Range(mySheet.Cells[1, 1], mySheet.Cells[DT.Rows.Count + 2, DT.Columns.Count - 3]);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; r.Select();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //不单独显示Excel，最后在IE中显示</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.Visible = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //第一行为报表的标题</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.Cells[1, 1] = "用模板导出的报表";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //逐行写入数据，数组中第一行为报表的列标题</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; DT.Columns.Count - 3; i++)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.Cells[2, 1 + i] = DT.Columns[i].Caption; ;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>//在当前目录下指定一个临时文件</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string FileName = Server.MapPath("~") + """Temp.xls";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (File.Exists(FileName))</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File.Delete(FileName);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.Save(FileName);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.Cells.Clear() ;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置不出现保存提示框</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myBook.Saved = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myExcel.Application.Workbooks.Close();</p>
<p>2.2.&nbsp;&nbsp;&nbsp; OWC组件<br />
1、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OWC组建在Web页面的展现方法；</p>
<p>A、将OWC中Sheet导出为本地Excel文件，再将导出的文件呈现到Web页面；</p>
<p>代码如下：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.Export(FileName, OWC11.SheetExportActionEnum.ssExportActionNone, OWC11.SheetExportFormat.ssExportHTML);//Sheet为OWC11中SpreadsheetClass类的对象</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ClearContent();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ClearHeaders();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ContentType = "application/vnd.ms-excel";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.AddHeader("Content-Disposition", "inline;filename='我的文件'");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.WriteFile(FileName);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Flush();</p>
<p>Response.Close();</p>
<p>B、后台把配置好的Sheet直接以文件方法返回到Web页面展现；</p>
<p>代码如下：</p>
<p>Response.Clear();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Buffer = true;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ContentEncoding = System.Text.Encoding.Default;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Response.Charset = "utf-8";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ContentType = "application/vnd.ms-excel";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write(Sheet.HTMLData);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.EnableViewState = false;</p>
<p>Response.End();</p>
<p>C、用html标签将OWC展现在Web页面，加载后台程序导出到本地的文件（xml、html、csv格式）来显示数据；</p>
<p>代码如下：</p>
<p>&lt;object classid="clsid:0002E559-0000-0000-C000-000000000046" width="600" id="Spreadsheet1"height="200"&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="DataType" value="HTMLURL"/&gt;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param name="HTMLURL" value="&lt;%=FileName%&gt;"/&gt;</p>
<p>&lt;/object&gt;</p>
<p>2、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为OWC中的SpreadSheet类中填充数据的方法：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 获取Sheet的Cell或者ActiveCell，直接给里面填充数据，代码如下：</p>
<p>OWC11.SpreadsheetClass Sheet = new OWC11.SpreadsheetClass();</p>
<p>//第一行为报表的标题</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.ActiveCell[1, 1] = "用模板导出的报表";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //逐行写入数据，数组中第一行为报表的列标题</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; DT.Columns.Count - 3; i++)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.Cells[2, 1 + i] = DT.Columns[i].Caption; ;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //为报表填充数据并设置显示上下标格式</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; DT.Rows.Count; i++)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int j = 0; j &lt; DT.Columns.Count - 4; j++)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.ActiveCell[3 + i, 1 + j] = DT.Rows[i][j];</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string a = DT.Rows[i][DT.Columns.Count - 4].ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string b = DT.Rows[i][DT.Columns.Count - 3].ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string c = DT.Rows[i][DT.Columns.Count - 2].ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.ActiveCell[3 + i,DT.Columns.Count - 3] = a + b + c;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.Columns.AutoFit();</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>3、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OWC中数据显示格式的控制：</p>
<p>A、 电子表格外观控制：</p>
<p>是否显示工具栏默认值为 true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.DisplayToolbar = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 取消显示Office图标</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.DisplayOfficeLogo = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是否显示列标题，默认是true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.DisplayColumnHeadings = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是否显示行标题，默认是true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.DisplayRowHeadings = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是否显示水平滚动条，默认为true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.DisplayHorizontalScrollBar = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 是否显示垂直滚动条，默认为true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.DisplayVerticalScrollBar = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 电子表格是否显示网格，默认为true</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.DisplayGridlines = false;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 设置行的颜色</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 1; i &lt; DT.Columns.Count - 2; i += 2)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.get_Range(Sheet.Rows.Cells[i, 1], Sheet.Rows.Cells[i, DT.Columns.Count - 3]).Interior.set_ColorIndex(2);</p>
<p>}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 做了上面的设置，效果如下图：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />
B、 单元格水平对齐</p>
<p>用Get_Range方法获取要设置的单元格，用set_HorizontalAlignment方法设置对齐方式；</p>
<p>代码如下：</p>
<p>//单元格水平居中</p>
<p>Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[DT.Rows.Count + 2, DT.Columns.Count - 3]).set_HorizontalAlignment(OWC11.XlHAlign.xlHAlignCenter);</p>
<p>枚举XLHAlign的值分别是：</p>
<p>&nbsp;&nbsp; //右对齐：</p>
<p>xlHAlignRight,</p>
<p>//左对齐：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignLeft,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //居中对齐：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignCenter,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //常规</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlHAlignGeneral1,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //填充对齐：</p>
<p>xlHAlignFill</p>
<p>C、 单元格垂直对齐</p>
<p>用Get_Range方法获取要设置的单元格，用set_VerticalAlignment方法设置对齐方式；</p>
<p>代码如下：</p>
<p>//单元格垂直居中</p>
<p>Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[DT.Rows.Count + 2, DT.Columns.Count - 3]).set_VerticalAlignment(OWC11.XlVAlign.xlVAlignCenter);</p>
<p>枚举XLHAlign的值分别是：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; // 靠上对齐</p>
<p>xlVAlignTop,</p>
<p>// 居中对齐</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlVAlignCenter,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 靠下对齐</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlVAlignBottom</p>
<p>D、 单元格合并；</p>
<p>用get_Range方法先获取要合并的单元格，再用set_MergeCells方法进行合并。</p>
<p>代码如下：</p>
<p>//标题行合并单元格</p>
<p>Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[1, DT.Columns.Count - 3]).set_MergeCells(true);</p>
<p>E、 字体设置；</p>
<p>用get_Range方法先获取要合并的单元格，设置该单元格字体：字体、字形、字号、字体颜色、字体加粗、带下划线（下划线有多种样式）等。</p>
<p>代码如下：</p>
<p>//标题行加粗字体</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[1, 1]).Font.set_Bold(true);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体大小&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[1, 1]).Font.set_Size(16);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体颜色</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[1, 1]).Font.set_ColorIndex(3);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[1, 1]).Font.set_Name("隶书");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体为斜体</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[1, 1]).Font.set_Italic(true);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体下划线</p>
<p>&nbsp;Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[1, 1]).Font.set_Underline(OWC11.XlUnderlineStyle.xlUnderlineStyleDouble);</p>
<p>枚举XLUnderlineStyle的值分别为：</p>
<p>xlUnderlineStyleNone,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlUnderlineStyleDouble,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlUnderlineStyleSingle,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlUnderlineStyleSingleAccounting,</p>
<p>xlUnderlineStyleDoubleAccounting,</p>
<p>F、 添加边框</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用get_Range方法先获取要添加边框的单元格，用Borders.set_LineStyle方法设置边框的类型即可。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 代码如下：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //画边线</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Sheet.get_Range(Sheet.Cells[1, 1], Sheet.Cells[DT.Rows.Count + 2, DT.Columns.Count - 3]).Borders.set_LineStyle(OWC11.XlLineStyle.xlContinuous);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 边框类型有一下几种：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlLineStyleNone,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDot,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDash,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlContinuous,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDashDot,</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlDashDotDot,</p>
<p>运行效果如下：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />
3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 限制条件说明<br />
3.1.&nbsp;&nbsp;&nbsp; Excel<br />
服务端需要安装Microsoft Office Excel 2003，Microsoft Office Excel 2003 SP1和Visual Studio 2005 Tools for Office Runtime（vstor.exe），客户端需要安装Microsoft Office Excel 2003，Microsoft Internet Explorer 5.01 (Service Pack 2) 或更高版本。</p>
<p>3.2.&nbsp;&nbsp;&nbsp; OWC<br />
服务端和客户端都必须安装 Microsoft Office Web Components，它可随 Office 2003 一起安装，或者，如果用户的公司具有 Office 2003 站点许可证，则可以通过公司的 Intranet 下载 Office Web 组件，用户还必须使用 Microsoft Internet Explorer 5.01 (Service Pack 2) 或更高版本。</p>
<p>4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 结果分析<br />
4.1.&nbsp;&nbsp;&nbsp; Excel<br />
Excel是一款功能强大、操作方便的电子表格处理软件，使用Excel做报表可以满足我们报表的所有需求，包括：表格的样式、尺寸、颜色的设置；字体样式、颜色、大小、对齐方式、上下标的设置；表头设置、表头冻结、单元格合并；数据统计；打印等。另外在程序实现上还有一下优点：</p>
<p>1、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用VBA简化程序设计过程。VBA应用程序是&#8220;寄生于&#8221;Excel应用程序上的，因此，Excel的一些基本功能和函数等都可以在VBA中直接使用。</p>
<p>2、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以充分利用Excel中的宏。Excel中的宏录制器允许记录一系列的操作，并且将这些操作转换为VBA代码，因此，一方面可以利用宏录制器来建立应用程序的基础，另一方面，在不能确定如何编写一系列的步骤时，可以进行录制，再查看代码。</p>
<p>3、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 与数据库交互。Excel能够使用多种类型的数据库，能够对数据库中的数据进行访问，同样也能够将Excel分析的结构导入到数据库中。</p>
<p>但同时，用Excel做报表也有一些不足，由于IE安全策略，当网站尝试下载除图片、音乐、纯文本文件以外其他格式文件时，IE将弹出一条&#8220;文件下载&#8221;的安全警告，因为要下载的文件上可能包含计算机代码(可能是程序或计算机病毒)，这样我们在IE上展现Excel报表时，会出现如下图提示，美中不足。<br />
&nbsp; </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 解决方案：</p>
<p>1、 将Excel封装在ActiveX里面，这样可以避免每次打开系统甚至每次刷新页面的时候弹出&#8220;文件下载&#8221;的对话框，但是在第一次打开的时候需要下载安装ActiveX。</p>
<p>2、 在客户端机器上进行设置：打开&#8220;我的电脑&#8221;&#224;&#8220;工具&#8221;（菜单）&#224;&#8220;文件类型&#8221;（属性页），在&#8220;已注册的文件类型&#8221;中选择&#8220;扩展名&#8221;为&#8220;XLS&#8221;，&#8220;文件类型&#8221;为&#8220;Microsoft Excel 工作表&#8221;，点击&#8220;高级&#8221;按钮后，如下图：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><br />
在&#8220;编辑文件类型&#8221;对话框中，&#8220;下载后确认打开&#8221;复选框不被选中表示直接打开，被选中表示弹出对话框，去掉勾点击确定。这样设置会影响客户端机器电子邮件.XLS格式附件的下载。</p>
<p>4.2.&nbsp;&nbsp;&nbsp; OWC<br />
OWC是Office Web Compents的缩写，即Microsoft的Office Web组件，包含SpreadSheet组件、Chart组件、PioTable组件和Data Source组件。我们报表使用的是SpreadSheet组件，使用它可以友好、方便的将电子表格展现在web页面，它同样可以满足我们一下需求：表格的样式、尺寸、背景颜色的设置；字体样式、颜色、大小、对齐方式的设置；表头设置、表头冻结、单元格合并；数据的统计；打印等。</p>
<p>在程序实现上OWC和Excel是相通的，程序设计过程也简单，可以直接调用Excel的方法，在不确定代码如何实现时也可以录制宏，查看代码。</p>
<p>缺点是没法实现上下标数据的显示，既是将带有上下标格式数据的Excel导入OWC的电子表格，上下标格式也失效，此问题暂没找到解决方法。</p>
<p>5.&nbsp;&nbsp; 参考文档<br />
1、《Microsoft Office Excel 2003 Visual Basic参考》。</p>
<p>2、《Microsoft Office Excel 2003电子表格组件帮助》。</p>
<p><br />
本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/RainyLin/archive/2008/09/08/2899754.aspx</p>
<img src ="http://www.blogjava.net/jvict/aggbug/320206.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-05-06 15:09 <a href="http://www.blogjava.net/jvict/articles/320206.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用owc生成excel并且显示在页面 [转]</title><link>http://www.blogjava.net/jvict/articles/320204.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 06 May 2010 06:47:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/320204.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/320204.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/320204.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/320204.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/320204.html</trackback:ping><description><![CDATA[<p><a href="http://blog.csdn.net/lonely7345/archive/2007/12/08/1924063.aspx">原文：http://blog.csdn.net/lonely7345/archive/2007/12/08/1924063.aspx</a><br />
<br />
主要利用OWC生成Excel,画表头和显示从数据库读出来的数据,然后显示在前台页面上,无需客户端安装office,只需要安装owc.</p>
<p>后面利用OWC操作EXCEL,并且生成文件的操作</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SpreadsheetClass xlsheet = new SpreadsheetClass();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 设置标题#region&nbsp; 设置标题<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //写标题<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //合并单元格<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[1, 1], xlsheet.Cells[1,30]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[1, 1] = "采购执行情况一览表";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //字体加粗<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[1, 1], xlsheet.Cells[1, 30]).Font.set_Bold(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //单元格文本水平居中对齐<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[1, 1], xlsheet.Cells[1, 30]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体大小<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[1, 1], xlsheet.Cells[1,30]).Font.set_Size(14);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 设置列#region&nbsp; 设置列<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2,1],xlsheet.Cells[3,1]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 1] = "序号";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 1], xlsheet.Cells[3,1]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 2], xlsheet.Cells[3, 2]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 2] = "项目号";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 2], xlsheet.Cells[3, 2]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 3], xlsheet.Cells[3, 3]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 3] = "包号";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 3], xlsheet.Cells[3, 3]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 4], xlsheet.Cells[3, 4]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 4] = "包预算";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 4], xlsheet.Cells[3, 4]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 5], xlsheet.Cells[3, 5]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 5] = "包计划请购日期";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 5], xlsheet.Cells[3, 5]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 6], xlsheet.Cells[3, 6]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 6] = "包计划签约日期";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 6], xlsheet.Cells[3,6]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 7], xlsheet.Cells[3, 7]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 7] = "包计划运输日期";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 7], xlsheet.Cells[3, 7]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 8], xlsheet.Cells[3, 8]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 8] = "包计划检验日期";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 8], xlsheet.Cells[3, 8]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 9], xlsheet.Cells[3, 9]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 9] = "项目经理";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 9], xlsheet.Cells[3, 9]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 10], xlsheet.Cells[3, 10]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2,10] = "采购经理";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 10], xlsheet.Cells[3, 10]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 11], xlsheet.Cells[3, 11]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 11] = "采购工程师";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 11], xlsheet.Cells[3, 11]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 12], xlsheet.Cells[3, 12]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 12] = "包状态";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 12], xlsheet.Cells[3, 12]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 13], xlsheet.Cells[3, 13]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 13] = "合同号";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 13], xlsheet.Cells[3, 13]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 14], xlsheet.Cells[3, 14]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 14] = "供应商";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 14], xlsheet.Cells[3, 14]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 15], xlsheet.Cells[3, 15]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 15] = "合同签定日";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 15], xlsheet.Cells[3, 15]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 16], xlsheet.Cells[3, 16]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 16] = "合同金额";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 16], xlsheet.Cells[3, 16]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 17], xlsheet.Cells[3, 17]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 17] = "合同控制价";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 17], xlsheet.Cells[3, 17]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 18], xlsheet.Cells[3, 18]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 18] = "出厂资料交付时间";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 18], xlsheet.Cells[3, 18]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 19], xlsheet.Cells[3, 19]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 19] = "出厂前检验时间";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 19], xlsheet.Cells[3, 19]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 20], xlsheet.Cells[3, 20]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 20] = "性能试验时间";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 20], xlsheet.Cells[3, 20]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 21], xlsheet.Cells[2, 24]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 21] = "交货时间";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 21], xlsheet.Cells[2, 24]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 21] = "1";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 22] = "2";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 23] = "3";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 24] = "4";</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 25], xlsheet.Cells[2, 30]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[2, 25] = "付款条件";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[2, 25], xlsheet.Cells[2, 30]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 25] = "1";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 26] = "2";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 27] = "3";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 28] = "4";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 29] = "5";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[3, 30] = "6";</p>
<p>#endregion</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 写入数据#region&nbsp; 写入数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int row = 4;//从第四行开始</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IList list = this.m_ProcurementPackageManager.GetAllObjectsList();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (ProcurementPackage package in list)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row,1] = i.ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 2] = package.Project.ProjectCode;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 3] = package.PackageCode;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 4] = package.PriceBudget;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 5] = ConvertDateTimeToString(package.PlanRequestDate);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 6] = ConvertDateTimeToString(package.PlanSignDate); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 7] = ConvertDateTimeToString(package.PlanTransportDate);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 8] = ConvertDateTimeToString(package.PlanCheckDate);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 9] = this.m_ProcurementPackageManager.GetPackageGroupUser(package.UniqueID, PackageGroupEnum.ProjectManager);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 10] = this.m_ProcurementPackageManager.GetPackageGroupUser(package.UniqueID, PackageGroupEnum.PurchasingManager);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 11] = this.m_ProcurementPackageManager.GetPackageGroupUser(package.UniqueID, PackageGroupEnum.ProcurementEngineer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row, 12] = package.FlagDSC;</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int j&nbsp; = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (ContractMaster contract in package.ContractList)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 13] = contract.UniCode;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 14] = contract.ShortList.LongList.CompanyName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 15] = ConvertDateTimeToString(contract.SignDate);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 16] = contract.TotalAmount;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 17] = contract.ControlPrice;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 18] = ConvertDateTimeToString(contract.FactoryDataDeliveryTime);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 19] = ConvertDateTimeToString(contract.FactoryInspectionTime);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 20] = ConvertDateTimeToString(contract.PerformanceTestTime);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 21] = ConvertDateTimeToString(contract.DeliveryTime1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 22] = ConvertDateTimeToString(contract.DeliveryTime2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 23] = ConvertDateTimeToString(contract.DeliveryTime3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 24] = ConvertDateTimeToString(contract.DeliveryTime4);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 25] = contract.PaymentTerm1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 26] = contract.PaymentTerm2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 27] = contract.PaymentTerm3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 28] = contract.PaymentTerm4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 29] = contract.PaymentTerm5;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[row + j, 30] = contract.PaymentTerm6;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; j++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int m = 1; m &lt;= 12; m++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[row, m], xlsheet.Cells[row + j-1, m]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[row, m], xlsheet.Cells[row + j-1, m]).set_HorizontalAlignment(XlHAlign.xlHAlignCenter);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[row, m], xlsheet.Cells[row + j-1, m]).set_VerticalAlignment(XlVAlign.xlVAlignCenter);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; row++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 生成文件#region&nbsp; 生成文件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string sFileUrl = Convert.ToString(this.SessionInfo.GetIniKeyValue("UploadDir", "UpLoadDir"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string fileUrl = Server.MapPath(sFileUrl) + "\";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.Export(fileUrl + "_TestOWC.html", SheetExportActionEnum.ssExportActionNone, SheetExportFormat.ssExportHTML);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(Exception&nbsp; ee)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new Exception(ee.Message);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion<br />
这样其实有一个问题,要控制生成的报表在不同的文件夹下面,否则会不同的人调用相同的报表.由于在最后并没有采用这种方案,所以也没有时间考虑这些了</p>
<p>前台用Activex显示Excel</p>
<p>&nbsp; &lt;object classid="clsid:0002E559-0000-0000-C000-000000000046"&nbsp;&nbsp;&nbsp; width="1000"&nbsp;&nbsp; id="Spreadsheet1"&nbsp;&nbsp; height="300"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DataType" value="HTMLURL"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="HTMLURL" value="&lt;%=Agent.ServerURL %&gt;ebChainUpLoad/_TestOWC.html"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="AllowPropertyToolbox" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="AutoFit" value="0"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="Calculation" value="-4105"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="Caption" value="采购执行情况一览表"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayColumnHeadings" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayGridlines" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayHorizontalScrollBar" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayOfficeLogo" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayPropertyToolbox" value="0"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayRowHeadings" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayTitleBar" value="0"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayToolbar" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayVerticalScrollBar" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DisplayWorkbookTabs" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="EnableEvents" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="MaxHeight" value="80%"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="MaxWidth" value="100%"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="MoveAfterReturn" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="MoveAfterReturnDirection" value="-4121"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="RightToLeft" value="0"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="ScreenUpdating" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="LockedDown" value="0"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="ConnectedToChart" value="0"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="DefaultQueryOnLoad" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;param name="EnableUndo" value="-1"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;table width='100%' cellpadding='0' cellspacing='0' border='0' height='8'&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;tr&gt;&lt;td bgColor='#336699' height='25' width='10%'&gt;&amp;nbsp;&lt;/td&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;td bgColor='#666666'width='85%'&gt;&lt;font face='宋体' color='white' size='4'&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;b&gt;&amp;nbsp; 缺少 Microsoft Office Web Components&lt;/b&gt;&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;td bgColor='#cccccc' width='15'&gt;&amp;nbsp;&lt;/td&gt;&lt;td bgColor='#cccccc' width='500px'&gt;&lt;br&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;font face='宋体' size='2'&gt;此网页要求 Microsoft Office Web Components。&lt;p align='center'&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;a href='C:/IUware Online/Microsoft Office Professional Enterprise Edition 2003/files/owc11/setup.exe'&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 单击此处安装 Microsoft Office Web Components。&lt;/a&gt;.&lt;/p&gt;&lt;/font&gt;&lt;p&gt;&lt;font face='宋体' size='2'&gt; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 此网页同时要求 Microsoft Internet Explorer 5.01 或更高版本。&lt;/p&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;p align='center'&gt;&lt;a href='http://www.microsoft.com/windows/ie/default.htm'&gt; 单击此处安装最新的 Internet Explorer&lt;/a&gt;.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/font&gt;&lt;br&gt;&amp;nbsp;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/object&gt;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/lonely7345/archive/2007/12/08/1924063.aspx</p>
<img src ="http://www.blogjava.net/jvict/aggbug/320204.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-05-06 14:47 <a href="http://www.blogjava.net/jvict/articles/320204.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET中用OWC操作Excel</title><link>http://www.blogjava.net/jvict/articles/320183.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 06 May 2010 03:55:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/320183.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/320183.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/320183.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/320183.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/320183.html</trackback:ping><description><![CDATA[<p><a href="http://hi.baidu.com/xiaoheilong/blog/item/9fe0d800464eaf19738b6550.html">原文：http://hi.baidu.com/xiaoheilong/blog/item/9fe0d800464eaf19738b6550.html</a><br />
<br />
string connstr = System.Configuration.ConfigurationManager.ConnectionStrings["DqpiHrConnectionString"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlConnection conn = new SqlConnection(connstr);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlDataAdapter sda = new SqlDataAdapter(sql1.Text, conn);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataSet ds = new DataSet();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn.Open();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sda.Fill(ds);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; conn.Close();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; OWC10.SpreadsheetClass xlsheet;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet= new OWC10.SpreadsheetClass();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DataRow dr;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int i = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int ii=0;ii&lt;ds.Tables[0].Rows.Count;ii++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dr = ds.Tables[0].Rows[ii];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //合并单元格<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i+1, 1], xlsheet.Cells[i+1, 8]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i + 5, 1], xlsheet.Cells[i + 5, 3]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i + 5, 4], xlsheet.Cells[i + 5, 6]).set_MergeCells(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i + 5, 7], xlsheet.Cells[i + 5, 8]).set_MergeCells(true);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 1, 1] = dr["姓名"].ToString() + "自然情况";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //字体加粗<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i + 1, 1], xlsheet.Cells[i + 1, 14]).Font.set_Bold(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //单元格文本水平居中对齐<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i + 1, 1], xlsheet.Cells[i + 1, 14]).set_HorizontalAlignment(OWC10.XlHAlign.xlHAlignCenter);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置字体大小<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i + 1, 1], xlsheet.Cells[i + 1, 14]).Font.set_Size(14);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置列宽<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i + 1, 8], xlsheet.Cells[i + 1, 8]).set_ColumnWidth(20);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //画边框线<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.get_Range(xlsheet.Cells[i + 1, 1], xlsheet.Cells[i+5, 8]).Borders.set_LineStyle(OWC10.XlLineStyle.xlContinuous);</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //写入数据&nbsp;&nbsp;&nbsp; (这里由DS生成)</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 2, 1] = "姓名";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 2, 2] = dr["姓名"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 2, 3] = "曾用名";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 2, 4] = dr["曾用名"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 2, 5] = "出生年月";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 2, 6] = DateTime.Parse(dr["出生年月"].ToString()).Year.ToString() + "-" + DateTime.Parse(dr["出生年月"].ToString()).Month.ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 2, 7] = " 参加工作时间";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 2, 8] = DateTime.Parse(dr["参加工作时间"].ToString()).Year.ToString() + "-" + DateTime.Parse(dr["参加工作时间"].ToString()).Month.ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 3, 1] = "性别";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 3, 2] = dr["性别"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 3, 3] = "民族";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 3, 4] = dr["民族"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 3, 5] = "政治面貌";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 3, 6] = dr["政治面貌"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 3, 7] = "职称";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 3, 8] = dr["职称"].ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 4, 1] = "学历";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 4, 2] = dr["学历"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 4, 3] = "学位";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 4, 4] = dr["学位"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 4, 5] = "职务";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 4, 6] = dr["职务"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 4, 7] = "档案号码";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //Excel不支持0开头输入，加上姓氏首字母正好是编号全称<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 4, 8] = dr["姓氏首字母"].ToString() + dr["档案号码"].ToString();</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 5, 1] = "现从事专业：" + dr["现从事专业"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 5, 4] = "工作单位：" + dr["工作单位"].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.ActiveSheet.Cells[i + 5, 7] = "身份证：" + dr["身份证号"].ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; i += 6;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string D = DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Day.ToString() +<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString() + DateTime.Now.Second.ToString()+<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; DateTime.Now.Millisecond.ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xlsheet.Export(Server.MapPath("./")+"<a href="file://%22+D+%22.xls/">\\"+D+".xls</a>", OWC10.SheetExportActionEnum.ssExportActionNone, OWC10.SheetExportFormat.ssExportXMLSpreadsheet);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write("&lt;script&gt;window.open('"+D+".xls')&lt;/script&gt;");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<img src ="http://www.blogjava.net/jvict/aggbug/320183.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-05-06 11:55 <a href="http://www.blogjava.net/jvict/articles/320183.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OWC操作excel</title><link>http://www.blogjava.net/jvict/articles/320180.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 06 May 2010 03:11:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/320180.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/320180.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/320180.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/320180.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/320180.html</trackback:ping><description><![CDATA[<p>一、用OWC <br />
什么是OWC？ <br />
　　OWC是Office Web Compent的缩写，即Microsoft的Office Web组件，它为在Web中绘制图形提供 </p>
<p>了灵活的同时也是最基本的机制。在一个intranet环境中，如果可以假设客户机上存在特定的浏览器和一 </p>
<p>些功能强大的软件（如IE5和Office 2000），那么就有能力利用Office Web组件提供一个交互式图形开 </p>
<p>发环境。这种模式下，客户端工作站将在整个任务中分担很大的比重。 <br />
有关的详细介绍也可在本站找到。 <br />
&lt;%Option Explicit <br />
Class ExcelGen <br />
Private objSpreadsheet </p>
<p>Private iColOffset </p>
<p>Private iRowOffset <br />
Sub Class_Initialize() <br />
Set objSpreadsheet = Server.CreateObject("OWC.Spreadsheet") <br />
iRowOffset = 2 <br />
iColOffset = 2 <br />
End Sub </p>
<p>Sub Class_Terminate() <br />
Set objSpreadsheet = Nothing &#8217;Clean up <br />
End Sub </p>
<p>Public Property Let ColumnOffset(iColOff) <br />
If iColOff &gt; 0 then <br />
iColOffset = iColOff <br />
Else <br />
iColOffset = 2 <br />
End If <br />
End Property </p>
<p>Public Property Let RowOffset(iRowOff) <br />
If iRowOff &gt; 0 then <br />
iRowOffset = iRowOff <br />
Else <br />
iRowOffset = 2 <br />
End If <br />
End Property Sub GenerateWorksheet(objRS) <br />
&#8217;Populates the Excel worksheet based on a Recordset&#8217;s contents <br />
&#8217;Start by displaying the titles <br />
If objRS.EOF then Exit Sub <br />
Dim objField, iCol, iRow <br />
iCol = iColOffset <br />
iRow = iRowOffset <br />
For Each objField in objRS.Fields <br />
objSpreadsheet.Cells(iRow, iCol).value = objField.Name <br />
objSpreadsheet.Columns(iCol).AutoFitColumns <br />
&#8217;设置Excel表里的字体 <br />
objSpreadsheet.Cells(iRow, iCol).Font.Bold = True <br />
objSpreadsheet.Cells(iRow, iCol).Font.Italic = False <br />
objSpreadsheet.Cells(iRow, iCol).Font.Size = 10 <br />
objSpreadsheet.Cells(iRow, iCol).Halignment = 2 &#8217;居中 <br />
iCol = iCol + 1 <br />
Next &#8217;objField <br />
&#8217;Display all of the data <br />
Do While Not objRS.EOF <br />
iRow = iRow + 1 <br />
iCol = iColOffset <br />
For Each objField in objRS.Fields <br />
If IsNull(objField.value) then <br />
objSpreadsheet.Cells(iRow, iCol).value = "" <br />
Else <br />
objSpreadsheet.Cells(iRow, iCol).value = objField.value <br />
objSpreadsheet.Columns(iCol).AutoFitColumns <br />
objSpreadsheet.Cells(iRow, iCol).Font.Bold = False <br />
objSpreadsheet.Cells(iRow, iCol).Font.Italic = False <br />
objSpreadsheet.Cells(iRow, iCol).Font.Size = 10 <br />
End If <br />
iCol = iCol + 1 <br />
Next &#8217;objField <br />
objRS.MoveNext <br />
Loop <br />
End Sub Function SaveWorksheet(strFileName) </p>
<p>&#8217;Save the worksheet to a specified filename <br />
On Error Resume Next <br />
Call objSpreadsheet.ActiveSheet.Export(strFileName, 0) <br />
SaveWorksheet = (Err.Number = 0) <br />
End Function <br />
End Class </p>
<p>Dim objRS <br />
Set objRS = Server.CreateObject("ADODB.Recordset") <br />
objRS.Open "SELECT * FROM xxxx", "Provider=SQLOLEDB.1;Persist Security </p>
<p>Info=True;User ID=xxxx;Password=xxxx;Initial Catalog=xxxx;Data source=xxxx;" <br />
Dim SaveName <br />
SaveName = Request.Cookies("savename")("name") <br />
Dim objExcel <br />
Dim ExcelPath <br />
ExcelPath = "Excel\" &amp; SaveName &amp; ".xls" <br />
Set objExcel = New ExcelGen <br />
objExcel.RowOffset = 1 <br />
objExcel.ColumnOffset = 1 <br />
objExcel.GenerateWorksheet(objRS) <br />
If objExcel.SaveWorksheet(Server.MapPath(ExcelPath)) then <br />
&#8217;Response.Write "&lt;html&gt;&lt;body bgcolor=&#8217;gainsboro&#8217; text=&#8217;#000000&#8217;&gt;已保存为Excel文件. </p>
<p>&lt;a href=&#8217;" &amp; server.URLEncode(ExcelPath) &amp; "&#8217;&gt;下载&lt;/a&gt;" <br />
Else <br />
Response.Write "在保存过程中有错误!" <br />
End If <br />
Set objExcel = Nothing <br />
objRS.Close <br />
Set objRS = Nothing <br />
%&gt; </p>
<p><br />
二、用Excel的Application组件在客户端导出到Excel或Word <br />
注意：两个函数中的&#8220;data&#8220;是网页中要导出的table的 id <br />
&lt;input type="hidden" name="out_word" onclick="vbscript:buildDoc" value="导出到word" class="notPrint"&gt; <br />
&lt;input type="hidden" name="out_excel" onclick="AutomateExcel();" value="导出到excel" class="notPrint"&gt; </p>
<p>导出到Excel代码 <br />
&lt;SCRIPT LANGUAGE="javascript"&gt; <br />
&lt;!-- <br />
function AutomateExcel() <br />
{ <br />
// Start Excel and get Application object. <br />
var oXL = new ActiveXObject("Excel.Application"); <br />
// Get a new workbook. <br />
var oWB = oXL.Workbooks.Add(); <br />
var oSheet = oWB.ActiveSheet; <br />
var table = document.all.data; <br />
var hang = table.rows.length; </p>
<p>var lie = table.rows(0).cells.length; </p>
<p>// Add table headers going cell by cell. <br />
for (i=0;i&lt;hang;i++) <br />
{ <br />
for (j=0;j&lt;lie;j++) <br />
{ <br />
oSheet.Cells(i+1,j+1).value = table.rows(i).cells(j).innerText; <br />
} </p>
<p>} <br />
oXL.Visible = true; <br />
oXL.UserControl = true; <br />
} <br />
//--&gt; <br />
&lt;/SCRIPT&gt; <br />
导出到Word代码 <br />
&lt;script language="vbscript"&gt; <br />
Sub buildDoc <br />
set table = document.all.data <br />
row = table.rows.length <br />
column = table.rows(1).cells.length </p>
<p>Set objWordDoc = CreateObject("Word.Document") </p>
<p>objWordDoc.Application.Documents.Add theTemplate, False <br />
objWordDoc.Application.Visible=True </p>
<p>Dim theArray(20,10000) <br />
for i=0 to row-1 <br />
for j=0 to column-1 <br />
theArray(j+1,i+1) = table.rows(i).cells(j).innerTEXT <br />
next <br />
next <br />
objWordDoc.Application.ActiveDocument.Paragraphs.Add.Range.InsertBefore("综合查询结果集") //显示表格标题 </p>
<p>objWordDoc.Application.ActiveDocument.Paragraphs.Add.Range.InsertBefore("") <br />
Set rngPara = objWordDoc.Application.ActiveDocument.Paragraphs(1).Range <br />
With rngPara <br />
.Bold = True //将标题设为粗体 <br />
.ParagraphFormat.Alignment = 1 //将标题居中 <br />
.Font.Name = "隶书" //设定标题字体 <br />
.Font.Size = 18 //设定标题字体大小 <br />
End With <br />
Set rngCurrent = objWordDoc.Application.ActiveDocument.Paragraphs(3).Range <br />
Set tabCurrent = ObjWordDoc.Application.ActiveDocument.Tables.Add(rngCurrent,row,column) </p>
<p>for i = 1 to column </p>
<p>objWordDoc.Application.ActiveDocument.Tables(1).Rows(1).Cells(i).Range.InsertAfter theArray(i,1) <br />
objWordDoc.Application.ActiveDocument.Tables(1).Rows(1).Cells(i).Range.ParagraphFormat.alignment=1 <br />
next <br />
For i =1 to column <br />
For j = 2 to row <br />
objWordDoc.Application.ActiveDocument.Tables(1).Rows(j).Cells(i).Range.InsertAfter theArray(i,j) <br />
objWordDoc.Application.ActiveDocument.Tables(1).Rows(j).Cells(i).Range.ParagraphFormat.alignment=1 <br />
Next <br />
Next </p>
<p>End Sub <br />
&lt;/SCRIPT&gt; </p>
<p><br />
三、直接在IE中打开，再存为EXCEL文件。 <br />
把读出的数据用&lt;table&gt;格式，在网页中显示出来，同时，加上下一句即可把EXCEL表在客客户端显示。 <br />
&lt;%response.ContentType ="application/vnd.ms-excel"%&gt; <br />
注意：显示的页面中，只把&lt;table&gt;输出，最好不要输出其他表格以外的信息。 </p>
<p><br />
四、导出以半角逗号隔开的csv <br />
用fso方法生成文本文件的方法，生成一个扩展名为csv文件。此文件，一行即为数据表的一行。生成数据表字段用半角逗号隔开。 <br />
有关fso生成文本文件的方法，在此就不做介绍了。相关文档，可本站找到。 </p>
<p>CSV文件介绍 （逗号分隔文件） <br />
选择该项系统将创建一个可供下载的CSV 文件； CSV是最通用的一种文件格式，它可以非常容易地被导入各种PC表格及数据库中。 <br />
请注意即使选择表格作为输出格式，仍然可以将结果下载CSV文件。在表格输出屏幕的底部，显示有 "CSV 文件"选项，点击它即可下载该文件。 <br />
如果您把浏览器配置为将您的电子表格软件与文本（TXT）/逗号分隔文件（CSV） 相关联，当您下载该文件时，该文件将自动打开。下载下来后，如果本地已安装EXCEL，点击此文件，即可自动用EXCEL软件打开此文件。<br />
</p>
<img src ="http://www.blogjava.net/jvict/aggbug/320180.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-05-06 11:11 <a href="http://www.blogjava.net/jvict/articles/320180.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在CentOS下安装SVN</title><link>http://www.blogjava.net/jvict/articles/319293.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sat, 24 Apr 2010 15:21:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/319293.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/319293.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/319293.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/319293.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/319293.html</trackback:ping><description><![CDATA[<div><strong><font size="4"><a href="http://www.xici.net/main.asp?url=/u691726/d79245542.htm">原文：http://www.xici.net/main.asp?url=/u691726/d79245542.htm</a><br />
<br />
1.SVN简介<br />
</font></strong>由于前些年在版本的管理上采用的都是CVS系统，总体上而言还是很优秀的，经过了多年<br />
的项目开发管理经历，在使用CVS系统在管理中大型的软件项目时还是遇到了很多不可克服的<br />
缺陷和局限性，主要表现在如下的几个方向：<br />
&nbsp;&nbsp;&nbsp; <strong>1. 无法进行文件名称的修改活动</strong>，这样一来就会导致必须先删除该文件再上传，丢失了<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 历史信息，要不就必须到服务上将xxx,v文件进行改名（我采用这种方法，不过总是<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 找管理员太不方便了）；<br />
&nbsp;&nbsp;&nbsp; <strong>2. 目录名称没有被管理</strong>，这样就不能进行改名等动作，其实项目的目录结构对于项目的<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 成功起了非常重要的作用，每次也只能到服务器上进行修改；<br />
&nbsp;&nbsp;&nbsp; <strong>3. 项目的分支代价太高</strong>，需要对每一个文件都进行标记，对于大的项目耗时太长，并且<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 基本上不能删除废弃了的分支和标记，因为那样很容易导致项目仓库的损坏，我就遇<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 到了好多次这种让人发狂的情况；<br />
&nbsp;&nbsp;&nbsp; <strong>4. 对于文件二进制和文本的处理经常会出现混乱</strong>，结果就使将二进制文件当作文本上传<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 后内容被扩展导致丢失，因为有些时候二进制文件的扩展名和某些文本文件的扩展名<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 相同了，所以导致CVS识别就会出错。
<p align="left"><br />
<font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以安装并配置subversion（简称svn）系统，使用svn来替换CVS系统，以解决上述问题。</font>
<p align="left"><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span>Subversion有两种运行方式，<strong>一种是基于Apache Http Server</strong>，<strong>另外一种是Subversion Standalone Server</strong>。下面我讲解的是基于Apache Http Server的Subversion，这样做几个好处<br />
<strong>A.能使用WebDAV协议。<br />
</strong></span></font><font size="2"><span><strong>B.能使用浏览器作为客户端工具浏览源码仓库。<br />
C.可以很容易的支持到SSPI（Windows域认证）和LDAP（AD？），这些都是Apache本身就支持的。<br />
D.能得到比较完善的Apache安全认证系统，比如SSL加密连接。<br />
</strong></span></font>
<p>
<p><font size="2"><strong><font size="4">2.svn安装</font></strong><br />
<strong>安装系统</strong>：CentOS<br />
<strong>安装方式</strong>：yum install（这种方式比较简单，如果用源码安装容易产生版本兼容的问题）<br />
<strong>建议</strong>：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</font><font size="2">最好将svn系统安装在Linux操作系统环境下，这样一来系统比较的稳定可靠，同时也可以减少很多的病毒和攻击的服务器日常维护工作量,我将svn安装在了CentOS的服务器版本下。</font>
<p><font size="2"><strong>安装：</strong></font>
<p><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; yum install httpd httpd-devel subversion mod_dav_svn mod_auth_mysql</font>
<p><font size="2"><strong>确定已经安装了svn模块：mod_dav_svn<br />
</strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #cd /etc/httpd/modules<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #ls | grep svn<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mod_authz_svn.so<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mod_dav_svn.so</font>
<p><font size="2"><br />
<strong>如果要确认是否成功的安装了svn可以通过如下的命令进行验证：</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; svn --version</font>
<p><font size="2">显示如下，表示正常：</font>
<p><font size="2">svn, version 1.1.4 (r13838)<br />
&nbsp;&nbsp; compiled Aug 21 2005, 20:56:55</font>
<p><font size="2">Copyright (C) 2000-2004 CollabNet.<br />
Subversion is open source software, see </font><a href="http://subversion.tigris.org/"><font size="2">http://subversion.tigris.org/</font></a><br />
<font size="2">This product includes software developed by CollabNet (</font><a href="http://www.collab.net/"><font size="2">http://www.Collab.Net/</font></a><font size="2">).</font>
<p><font size="2">The following repository access (RA) modules are available:</font>
<p><font size="2">* ra_dav : Module for accessing a repository via WebDAV (DeltaV) protocol.<br />
- handles 'http' schema<br />
- handles 'https' schema<br />
* ra_local : Module for accessing a repository on local disk.<br />
- handles 'file' schema<br />
* ra_svn : Module for accessing a repository using the svn network protocol.<br />
- handles 'svn' schema</font>
<p>
<p><font size="2"><strong><font size="4">3.apache的配置</font><br />
配置/etc/httpd/conf/httpd.conf<br />
</strong>（httpd的安装目录,一般是/etc/httpd或/usr/local/appache2）<br />
</font><font size="2">进入到/etc/conf目录下用vim打开httpd.conf配置文件进行选项的修改：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a. KeepAlive选项（可选）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 该选项可以修改也可以不修改，主要是为了提高http协议访问的性能，可以<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使得svn仓库的访问更快，KeepAlive表示可以保持http的永久性TCP连接，<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 省去了每次都需要进行重建TCP连接的巨大开销，找到如下几个选项并修改：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; KeepAlive On<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MaxKeepAliveRequests 100<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; KeepAliveTimeout 15<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. ServerAdmin/ServerName选项（可选）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对于需要对系统进行管理的可以在ServerAdmin选项设置成为管理员的email<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 地址，这样在出现问题时apache会自动发送邮件到该地址中；而ServerName<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 必须设置为本服务器的域名，如xxx.xxx.cn:80。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为了使客户端能够通过Apache来访问SVN档案库，Apache需要加载一个特殊的模块mod_dav_svn。如果您的Apache是按照与预设目录安装的，mod_dav_svn 模块应该会安装在 Apache 安装位置 (默认路径是 /usr/local/apache2) 的 modules 子目录内。同时在Apache的配置文件httpd.conf（默认路径为/usr/local/apache2/conf）中已经使用LoadModule指令加载了该模块（如果没有，请手动添加）LoadModule 指令的语法很简单， 就是将一个具名模块对映到共享链接库在磁盘上的位置: <br />
LoadModule dav_svn_module&nbsp;&nbsp;&nbsp;&nbsp; modules/mod_dav_svn.so<br />
注意这个指令必须出现在其它的 Subversion 相关指令之前。<br />
</font><font size="2">还要加载mod_authz_svn.so模块<br />
如图：</font>
<p><font size="2"><img height="352" src="http://p.blog.csdn.net/images/p_blog_csdn_net/liuyuan_jq/svn.JPG" width="560" h="352" w="560" init="1" p="100"  alt="" /></font>
<p><font size="2"><strong>测试Apache是否可以正常启动：</strong></font>
<p><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #vim /etc/httpd/conf/httpd.conf -- Edit what you need and save the file<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #service httpd start<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #chkconfig httpd on<br />
在浏览器中访问：<a href="http://localhost/">http://localhost</a>, 如果能看到Apache的页面，则说明Apache已经正常启动。</font>
<p><font size="2"><strong>Apache命令：</strong><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 启动：apachectl -k start<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 关闭：apachectl -k stop<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 重启：apachectl -k restart<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 查看日志：tail -f /etc/httpd/logs/error-log<br />
</font>
<p>
<p align="left"><font size="2"><strong><font size="4">4.svn的配置</font></strong><br />
进入到/etc/httpd/conf.d目录下用vim打开subversion.conf配置文件进行选项的<br />
修改：<br />
<strong>a. module的配置</strong><br />
一定要保证下面的两句话存在于配置文件中，否则无法在如svn的模块，就<br />
无法访问svn的仓库了：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LoadModule dav_svn_module&nbsp;&nbsp;&nbsp;&nbsp; modules/mod_dav_svn.so<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LoadModule authz_svn_module&nbsp;&nbsp; modules/mod_authz_svn.so</font>
<p align="left"><font size="2"><strong>b. 仓库目录配置<br />
</strong>项目仓库就是用于存放项目目录结构的服务器目录，一般情况下Linux的规则时间容易变化的内容存放在/var目录下，所以我们需要在/var目录下创建一个svn目录，这样所有的项目的根目录都作为/var/svn/目录下的一级子目录了，这样以来就可以在一个仓库目录下存放多个项目了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
</font>下面将使用myapp这个仓库来配置Subversion
<p align="left"><font size="2"><span style="color: #808080; font-style: italic"># <span style="font-weight: bold; color: #c20cb9">mkdir</span> -p /var/svn</span><br />
<br />
<span style="color: #808080; font-style: italic"># <span style="font-weight: bold; color: #7a0874">cd</span> /var/svn</span><br />
<br />
<span style="color: #808080; font-style: italic"># svnadmin create myapp</span><br />
<br />
<span style="color: #808080; font-style: italic"># <span style="font-weight: bold; color: #c20cb9">chown</span> -R apache<strong>.</strong>apache myapp</span><br />
<br />
<span style="color: #808080; font-style: italic"># vi /etc/httpd/conf.d/subversion.conf</span></font>
<p align="left"><font size="2">加入以下配置</font>
<p align="justify"><font size="2"><span style="color: #00007f">LoadModule</span> dav_svn_module&nbsp;&nbsp;&nbsp;&nbsp; modules/mod_dav_svn.so<br />
<span style="color: #00007f">LoadModule</span> authz_svn_module&nbsp;&nbsp; modules/mod_authz_svn.so<br />
<br />
&lt;Location /svn&gt;<br />
DAV svn<br />
SVNParentPath /var/svn<br />
<span style="color: #adadad; font-style: italic">#</span><br />
<span style="color: #adadad; font-style: italic">#&nbsp;&nbsp; # Limit write permission to list of valid users.</span><br />
<span style="color: #adadad; font-style: italic">#&nbsp;&nbsp; &lt;LimitExcept GET PROPFIND OPTIONS REPORT&gt;</span><br />
<span style="color: #adadad; font-style: italic">#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # Require SSL connection for password protection.</span><br />
<span style="color: #adadad; font-style: italic">#&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # SSLRequireSSL</span><br />
<span style="color: #adadad; font-style: italic">#</span><br />
<span style="color: #00007f">AuthType</span> Basic<br />
<span style="color: #00007f">AuthName</span> <span style="color: #7f007f">"Authorization Realm"</span><br />
<span style="color: #00007f">AuthUserFile</span> /var/svn/passwd<br />
<span style="color: #00007f">Require</span> valid-<span style="color: #00007f">user</span><br />
<span style="color: #adadad; font-style: italic">#&nbsp;&nbsp; &lt;/LimitExcept&gt;</span><br />
&lt;/Location&gt;</font>
<p>下面建立可访问用户文件
<div style="padding-bottom: 0px">
<div>
<pre><span style="color: #808080; font-style: italic"># htpasswd -c /var/svn/<span style="font-weight: bold; color: #c20cb9">passwd</span> justin</span></pre>
</div>
</div>
<p>要增加用户,则使用下面命令
<div style="padding-bottom: 0px">
<div>
<pre><span style="color: #808080; font-style: italic"># htpasswd /var/svn/<span style="font-weight: bold; color: #c20cb9">passwd</span> other</span></pre>
</div>
</div>
<p>重起Apache
<div style="padding-bottom: 0px">
<div>
<pre><span style="color: #808080; font-style: italic"># service httpd restart</span></pre>
</div>
</div>
<p>Subversion部分安装完成，打开浏览器访问<a href="http://localhost/svn/myapp">http://localhost/svn/myapp</a>即可看到效果。</p>
</div>
<img src ="http://www.blogjava.net/jvict/aggbug/319293.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-04-24 23:21 <a href="http://www.blogjava.net/jvict/articles/319293.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET 安全认证(单点登录）【上集】 </title><link>http://www.blogjava.net/jvict/articles/319231.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Fri, 23 Apr 2010 15:36:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/319231.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/319231.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/319231.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/319231.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/319231.html</trackback:ping><description><![CDATA[<div class="ns_content">原文：http://apps.hi.baidu.com/share/detail/793253
<p style="text-indent: 2em"><br />
代码写 N 久了，总想写得别的。这不，上头说在整合两个项目，做成单一登录（Single Sign On），也有人称之为&#8220;单点登录&#8221;。查阅相关文档后，终于实现了，现在把它拿出来与大家一起分享。或许大家会问：&#8220;这与标题不符呀？&#8221;别急，在下笔之前，我脑子里想到了我刚使用 Form 认证时遇到的一些问题，以及使用过程用到的一些技巧（实乃投机取巧是也 ^_^ ）。此文供大家学习交流之用，欢迎广大劳苦群众拎着鸡蛋、捧着鲜花前来评论。转载请注明原创作者乃寒羽枫是也，不甚感激！</p>
<p style="text-indent: 2em">废话也说的差不多了，言归正传， ASP.NET 的安全认证，共有&#8220;Windows&#8221;&#8220;Form&#8221;&#8220;Passport&#8221;&#8220;None&#8221;四种验证模式。&#8220;Windows&#8221;与&#8220;None&#8221;没有起到保护的作用，不推荐使用；&#8220;Passport&#8221;我又没用过，唉&#8230;&#8230;所以我只好讲讲&#8220;Form&#8221;认证了。我打算分三部分：</p>
<p style="text-indent: 2em">第一部分——怎样实现From 认证；</p>
<p style="text-indent: 2em">第二部分—— Form 认证的实战运用；</p>
<p style="text-indent: 2em">第三部分——实现单点登录（Single Sign On）</p>
<p style="text-indent: 2em">第一部分如何运用 Form 表单认证</p>
<p style="text-indent: 2em">一、新建一个测试项目</p>
<p style="text-indent: 2em">为了更好说明，有必要新建一个测试项目（暂且为&#8220;FormTest&#8221;吧），包含三张页面足矣（Default.aspx、Login.aspx、UserInfo.aspx）。啥？有人不会新建项目，不会新增页面？你问我咋办？我看这么办好了：拖出去，打回原藉，从幼儿园学起&#8230;&#8230;</p>
<p style="text-indent: 2em">二、修改 Web.config</p>
<p style="text-indent: 2em">1、 双击项目中的Web.config（不会的、找不到的打 PP）</p>
<p style="text-indent: 2em">2、 找到下列文字&lt;authenticationmode="Windows"/&gt; 把它改成：</p>
<p style="text-indent: 2em">&lt;authenticationmode="Forms"&gt;</p>
<p style="text-indent: 2em">&lt;formslogi nUrl="Login.aspx"name=".ASPXAUTH"&gt;&lt;/forms&gt;</p>
<p style="text-indent: 2em">&lt;/authentication&gt;</p>
<p style="text-indent: 2em">3、 找到&lt;authorization&gt;&lt;allowusers="*"/&gt;&lt;/authorization&gt;换成</p>
<p style="text-indent: 2em">&lt;authorization&gt;&lt;denyusers="?"&gt;&lt;/deny&gt;&lt;/authorization&gt; </p>
<p style="text-indent: 2em">这里没什么好说的，只要拷贝过去就行。虽说如此，但还是有人会弄错，如下：</p>
<p style="text-indent: 2em">&lt;authenticationmode="Forms"&gt;</p>
<p style="text-indent: 2em">&nbsp;&nbsp; &lt;formslogin Url="Login.aspx"name=".APSX"&gt;&lt;/forms&gt;</p>
<p style="text-indent: 2em">&lt;denyusers="?"&gt;&lt;/deny&gt;</p>
<p style="text-indent: 2em">&lt;/authentication&gt;</p>
<p style="text-indent: 2em">若要问是谁把&lt;denyusers="?"&gt;&lt;/deny&gt;放入&lt;authentication&gt;中的，我会很荣幸地告诉你，那是 N 年前的我：&lt;authentication&gt;与&lt;authorization&gt;都是以auth字母开头又都是以ation结尾，何其相似；英文单词背不下来的我以为他们是一伙的&#8230;&#8230;</p>
<p style="text-indent: 2em">三、编写 .cs 代码——登录与退出</p>
<p style="text-indent: 2em">1、 登录代码：</p>
<p style="text-indent: 2em">a、 书本上介绍的</p>
<p style="text-indent: 2em">&nbsp;&nbsp; private void Btn_Login_Click(object sender, System.EventArgs e)</p>
<p style="text-indent: 2em">&nbsp;&nbsp; {</p>
<p style="text-indent: 2em">if(this.Txt_UserName.Text=="Admin" &amp;&amp; this.Txt_Password.Text=="123456")</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">&nbsp;&nbsp; System.Web.Security.FormsAuthentication.RedirectFromLoginPage(this.Txt_UserName.Text,false);</p>
<p style="text-indent: 2em">&nbsp;&nbsp; }</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">b、 偶找了 N 久才找到的</p>
<p style="text-indent: 2em">private void Btn_Login_Click(object sender, System.EventArgs e)</p>
<p style="text-indent: 2em">&nbsp;&nbsp; {</p>
<p style="text-indent: 2em">if(this.Txt_UserName.Text=="Admin" &amp;&amp; this.Txt_Password.Text=="123456")</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">System.Web.Security.FormsAuthentication.SetAuthCookie(this.Txt_UserName.Text,false);</p>
<p style="text-indent: 2em">&nbsp;&nbsp; Response.Redirect("Default.aspx");</p>
<p style="text-indent: 2em">&nbsp;&nbsp; }</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">以上两种都可发放验证后的Cookie，即通过验证，区别：</p>
<p style="text-indent: 2em">方法 a) 指验证后返回请求页面，俗称&#8220;从哪来就打哪去&#8221;。比如：用户没登录前直接在 IE 地址栏输入http://localhost/FormTest/UserInfo.aspx，那么该用户将看到的是Login.aspx?ReturnUrl=UserInfo.aspx，输入用户名与密码登录成功后，系统将根据&#8220;ReturnUrl&#8221;的值，返回相应的页面</p>
<p style="text-indent: 2em">方法 b) 则是分两步走：通过验证后就直接发放Cookie，跳转页面将由程序员自行指定，此方法多用于Default.aspx 使用框架结构的系统。 </p>
<p style="text-indent: 2em">2、 退出代码：</p>
<p style="text-indent: 2em">private void Btn_LogOut_Click(object sender, System.EventArgs e)</p>
<p style="text-indent: 2em">&nbsp;&nbsp; {</p>
<p style="text-indent: 2em">System.Web.Security.FormsAuthentication.SignOut();</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">四、如何判断验证与否及获取验证后的用户信息</p>
<p style="text-indent: 2em">有的时候，在同一张页面需要判断用户是否已经登录，然后再呈现不同的布局。有人喜欢用Session来判断，我不反对此类做法，在此我只是想告诉大家还有一种方法，且看下面代码：</p>
<p style="text-indent: 2em">if(User.Identity.IsAuthenticated)</p>
<p style="text-indent: 2em">&nbsp;&nbsp; {</p>
<p style="text-indent: 2em">//你已通过验证，知道该怎么做了吧？</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">User.Identity还有两个属性AuthenticationType（验证类型）与Name（用户名称），大家要注意的是Name属性，此处的User.Identity.Name将得到，验证通过（RedirectFromLoginPage或SetAuthCookie）时，我们带入的第一个参数this.Txt_UserName.Text 。这个参数很重要，关系到种种&#8230;&#8230;种种的情况，何出此言，且听下回分解&#8230;&#8230;</p>
<p style="text-indent: 2em">第二部分 Form 认证的实战运用 </p>
<p style="text-indent: 2em">话说上回，简单地说了一下 Form 表单认证的用法。或许大家觉得太简单，对那些大内高手来说应该是&#8220;洒洒水啦&#8221;&#8220;小 Kiss 啦（小意思）&#8221;。今天咱们来点的花样吧：古有六扇门，拒收叶孤城；东门不刮风，吹雪姓西门；缎带作凭证，决战紫禁城。</p>
<p style="text-indent: 2em">五、Web.config 的作用范围</p>
<p style="text-indent: 2em">新建项目时， VS.Net 会在项目根目录建立一个内容固定的 Web.config。除了在项目根目录，你还可以在任一目录下建立 Web.config ，条件就是应用程序级别的节点只能在根目录的 Web.config 中出现。至于哪些是应用程序级别节点呢，这个问题嘛，其实我也不太清楚，呵呵。电脑不是我发明的，微软不是我创建的，C# 更不是我说了算的，神仙也有不知道的，所以我不晓得是正常的。话虽如此，只要它不报错，那就是对的。</p>
<p style="text-indent: 2em">关于 Web.config 设置的作用范围，记住以下两点：</p>
<p style="text-indent: 2em">1、 Web.config 的设置将作用于所在目录的所有文件及其子目录下的所有东东（继承：子随父姓）</p>
<p style="text-indent: 2em">2、 子目录下的 Web.config 设置将覆盖由父目录继承下来的设置（覆盖：县官不如现管）</p>
<p style="text-indent: 2em">给大家提个问题：有没有比根目录Web.config 的作用范围还大的配置文件呢？看完第三部分便知分晓。</p>
<p style="text-indent: 2em">六、学会拒绝与巧用允许</p>
<p style="text-indent: 2em">回到我们在第一回合新建的测试项目&#8220;FormTest&#8221;， 既然要进行验证，按国际惯例，就得有用户名与密码。那，这些用户是管理员自己在数据库建好呢，还是用户注册、管理员审核好呢。只要不是一般的笨蛋，都知道选择后者。你们还别说，我公司还真有个别项目是管理员连到数据库去建帐号的，属于比较特殊的笨蛋，咱们不学他也罢，还是老老实实添加两个页面吧——注册页面（Register.aspx）与审核页面（Auditing.aspx）。</p>
<p style="text-indent: 2em">问题终于就要浮出水面啦，当你做好Register.aspx时，想访问它的时候突然觉得不对劲，怎么又回到了登录页面？你仔细瞧瞧网址，是不是成了：Login.aspx?ReturnUrl=Register.aspx。怎么办，用户就是因为没有帐号才去访问注册页面的呀？（这句纯属废话，有帐号谁还跑去注册。）我时常对我的同事说：&#8220;办法是人想出来滴！！&#8221;</p>
<p style="text-indent: 2em">1、新建一个目录Public，用于存放一些公用的文件，如万年历、脚本呀&#8230;&#8230;</p>
<p style="text-indent: 2em">2、在&#8220;解决方案资源管理器&#8221;中右击点击目录Public，新增一个Web.config</p>
<p style="text-indent: 2em">3、把上述Web.config的内容统统删除，仅留以下即可：</p>
<p style="text-indent: 2em">&lt;?xmlversion="1.0"encoding="utf-8"?&gt;</p>
<p style="text-indent: 2em">&lt;configuration&gt;</p>
<p style="text-indent: 2em">&lt;system.web&gt;</p>
<p style="text-indent: 2em">&lt;authorization&gt;&lt;allow users="*"/&gt;&lt;/authorization&gt;</p>
<p style="text-indent: 2em">&lt;/system.web&gt;</p>
<p style="text-indent: 2em">&lt;/configuration&gt;</p>
<p style="text-indent: 2em">终于切入正题了，不容易呀。根据&#8220;覆盖&#8221;原则，我们知道上述Web.config将替代根目录Web.config中的&lt;authorization&gt;节点设置，即：</p>
<p style="text-indent: 2em">&lt;allowusers="*"/&gt;替换&lt;denyusers="?"&gt;&lt;/deny&gt;</p>
<p style="text-indent: 2em">注解：&#8220;allow&#8221;允许的意思；&#8220;*&#8221;表示所有用户；</p>
<p style="text-indent: 2em">&#8220;deny&#8221;拒绝的意思；&#8220;?&#8221;表示匿名用户；</p>
<p style="text-indent: 2em">因此，处于Public目录下的文件，允许所有人浏览，包括未验证的用户。把Register.aspx拖进来吧，再也不会有人阻止你浏览啦。</p>
<p style="text-indent: 2em">除了注册页面，我们还提到一个审核页面（Auditing.aspx），审核权限一般都在管理员或主管手里，并不想让其他人浏览此页面（真理往往掌握在少数人的手里，这也是没法子的事），怎么办？&#8220;办法是人想出来滴&#8221;呵呵&#8230;&#8230;新建一个管理员的目录ManageSys，在此目录下再新增一个Web.config。内容如下：</p>
<p style="text-indent: 2em">&lt;?xmlversion="1.0"encoding="utf-8"?&gt;</p>
<p style="text-indent: 2em">&lt;configuration&gt;</p>
<p style="text-indent: 2em">&lt;system.web&gt;</p>
<p style="text-indent: 2em">&lt;authorization&gt;</p>
<p style="text-indent: 2em">&lt;allow users="Admin"/&gt;</p>
<p style="text-indent: 2em">&lt;deny users="*"/&gt;</p>
<p style="text-indent: 2em">&lt;/authorization&gt;</p>
<p style="text-indent: 2em">&lt;/system.web&gt;</p>
<p style="text-indent: 2em">&lt;/configuration&gt;</p>
<p style="text-indent: 2em">现在的问题就是怎么才能知道谁是&#8220;Admin&#8221;呢，这个问题就有点象&#8220;我的鞋底有个洞&#8221;——天不知地知，你不知我知。闲话少说（要是有稿费多好，我就有多写几个字的动力，唉&#8230;&#8230;），大家还记得我在第一部分的结尾吗？什么，忘啦！罚你回去看一百遍，记住了再回来。站住，回来！一想到你的记性，我就不放心，第一部分的浏览网址是<a href="http://blog.csdn.net/cityhunter172/archive/2005/11/06/524043.aspx"><font color="#3354ae">http://blog.csdn.net/cityhunter172/archive/2005/11/06/524043.aspx</font></a>，回到此处的网址是<a href="http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx"><font color="#3354ae">http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx</font></a></p>
<p style="text-indent: 2em">好了，不管那些记不好的家伙了，大伙继续往下看。</p>
<p style="text-indent: 2em">System.Web.Security.FormsAuthentication.SetAuthCookie(this.Txt_UserName.Text,false);//通过验证，发放Cookie</p>
<p style="text-indent: 2em">之前我曾强调，要注意，第一个参数很重要，重要到什么程度？说到这，恐怕地球人都知道了——它就是allow与deny的依据。假如此处用户填写的是&#8220;Admin&#8221;即this.Txt_UserName.Text="Admin";那么进入系统后，他就能访问ManageSys目录下的网页了，其它闲杂人等一律拒之门外。</p>
<p style="text-indent: 2em">为巩固上述内容，给大伙留个课外作业：此项目有两部门使用，其中每个部门分别都有些特定的页面仅供本部门用户浏览使用，请问该如何使用Web.config达到效果？同样，答案在第三部分揭晓</p>
<p style="text-indent: 2em">七、分散与集中</p>
<p style="text-indent: 2em">乍看之下，就象是马克思列宁主义、***思想、***理论中的辩证关系，大伙放心，偶是学理科的，只明白&#8220;高举程序员的伟大旗帜，以编写代码为中心&#8221;。停&#8230;&#8230;</p>
<p style="text-indent: 2em">到目前为此，我们的测试项目&#8220;FormTest&#8221;已经拥有两个目录三个Web.config，伴随用户需求的多样化，Web.config也会越来越多，比如常用的文件上传功能等等。众多的Web.config分布在不同的目录里面，维护起来肯定比较烦人。能不能集中起来管理呢，应该咋办哩？&#8220;办法是&#8230;&#8230;&#8221;哟，有人先说出来啦。不错，&#8220;办法的确是人想出来滴&#8221;，我不说，你是不是只有在一边凉伴？开玩笑的，为了让更多的人记住这句话，我打算告诉你集中管理的办法。</p>
<p style="text-indent: 2em">要想集中管理，不得不用到&lt;location&gt;节点与path属性。在本项目中，我们将目录Public与ManageSys下的设置放在根目录下的Web.config里面，如下：</p>
<p style="text-indent: 2em">&lt;?xml version="1.0" encoding="utf-8"?&gt;</p>
<p style="text-indent: 2em">&lt;configuration&gt;</p>
<p style="text-indent: 2em">&lt;location path="Public"&gt;</p>
<p style="text-indent: 2em">&lt;system.web&gt;</p>
<p style="text-indent: 2em">&lt;authorization&gt;</p>
<p style="text-indent: 2em">&lt;allow users="*"/&gt;</p>
<p style="text-indent: 2em">&lt;/authorization&gt;</p>
<p style="text-indent: 2em">&lt;/system.web&gt;</p>
<p style="text-indent: 2em">&lt;/location&gt;</p>
<p style="text-indent: 2em">&lt;location path="ManageSys"&gt;</p>
<p style="text-indent: 2em">&lt;system.web&gt;</p>
<p style="text-indent: 2em">&lt;authorization&gt;</p>
<p style="text-indent: 2em">&lt;allow users="Admin"/&gt;</p>
<p style="text-indent: 2em">&lt;deny users="*"/&gt;</p>
<p style="text-indent: 2em">&lt;/authorization&gt;</p>
<p style="text-indent: 2em">&lt;/system.web&gt;</p>
<p style="text-indent: 2em">&lt;/location&gt;</p>
<p style="text-indent: 2em">&lt;system.web&gt;</p>
<p style="text-indent: 2em">&lt;!--这里放置原来根目录Web.config的内容，就不列出来了--&gt;</p>
<p style="text-indent: 2em">&lt;/system.web&gt;</p>
<p style="text-indent: 2em">&lt;/configuration&gt;</p>
<p style="text-indent: 2em">需要提醒的是</p>
<p style="text-indent: 2em">1、&lt;location&gt;节点的位置是在&lt;configuration&gt;的一个子节点，它与原有的&lt;system.web&gt;属于并列关系</p>
<p style="text-indent: 2em">2、&lt;location&gt;节点只需要放入对应子目录Web.config中的&lt;system.web&gt;的节点内容</p>
<p style="text-indent: 2em">八、额外的保护</p>
<p style="text-indent: 2em">第二部分就要结束了，现在时间已是凌晨4点50分，我容易嘛我。认证的目的就是为了防止他人非法浏览页面，或未经许可使用某些功能。当然，世上没有绝对的安全，如今MD5加密都被我们国人给破解了，就是最好的例证。</p>
<p style="text-indent: 2em">细心的人可能早就发现ASP.NET的安全认证只针对.aspx、.ascx&#8230;&#8230;等ASP.NET文件起作用，而对普通页面与文件却&#8220;视而不见&#8221;，如.htm、.js、.jpg等。通过以下步骤你就可以保护你想保护的文件类型。</p>
<p style="text-indent: 2em">1、打开Internet信息服务(IIS)管理器&#8594;右击本项目虚拟&#8594;属性，如下图</p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (<a href="http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm01.JPG"><font color="#3354ae">http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm01.JPG</font></a>)</p>
<p style="text-indent: 2em">2、点击按钮&#8220;配置&#8221;，出现如下对话框：</p>
<p style="text-indent: 2em">(<a href="http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm02.JPG"><font color="#3354ae">http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm02.JPG</font></a>)</p>
<p style="text-indent: 2em">3、双击.aspx的应用程序扩展&#8594;查看对话框内容，如下图：</p>
<p style="text-indent: 2em">(<a href="http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm03.JPG"><font color="#3354ae">http://blog.csdn.net/images/blog_csdn_net/cityhunter172/85935/r_aspxForm03.JPG</font></a>)</p>
<p style="text-indent: 2em">4、复制&#8220;可执行文件&#8221;的全路径名称后&#8594;点击&#8220;取消&#8221;返回上一层对话框&#8594;点击按钮&#8220;添加&#8221;</p>
<p style="text-indent: 2em">5、粘贴刚才复制的内容（我的系统装在D盘，所以内容为D:"WINDOWS"Microsoft.NET"Framework"v1.1.4322"aspnet_isapi.dll）&#8594;填写后缀名为.htm&#8594;填写动作限制为&#8220;GET,HEAD,POST,DEBUG&#8221;（为方便省事你可选全部）</p>
<p style="text-indent: 2em">6、最后点击&#8220;确定&#8221;&#8594;往项目中添加HtmlPage1.htm&#8594;在IE浏览器的地址栏直接输入http://localhost/FormTest/HtmlPage1.htm&#8594;观看测试效果</p>
<p style="text-indent: 2em">最后送大家一段Web.config设置，发完睡觉，实在是困的不行了。</p>
<p style="text-indent: 2em">&lt;location path="决战紫禁城"&gt;</p>
<p style="text-indent: 2em">&lt;system.web&gt;</p>
<p style="text-indent: 2em">&lt;authorization&gt;</p>
<p style="text-indent: 2em">&lt;allow users="叶孤城"/&gt;</p>
<p style="text-indent: 2em">&lt;allow users="西门吹雪"/&gt;</p>
<p style="text-indent: 2em">&lt;deny users="*"/&gt;</p>
<p style="text-indent: 2em">&lt;/authorization&gt;</p>
<p style="text-indent: 2em">&lt;/system.web&gt;</p>
<p style="text-indent: 2em">&lt;/location&gt;</p>
<p style="text-indent: 2em">&lt;location path="金銮殿屋脊"&gt;</p>
<p style="text-indent: 2em">&lt;system.web&gt;</p>
<p style="text-indent: 2em">&lt;authorization&gt;</p>
<p style="text-indent: 2em">&lt;allow users="腰系缎带之人"/&gt;</p>
<p style="text-indent: 2em">&lt;deny users="*"/&gt;</p>
<p style="text-indent: 2em">&lt;/authorization&gt;</p>
<p style="text-indent: 2em">&lt;/system.web&gt;</p>
<p style="text-indent: 2em">&lt;/location&gt;</p>
<p style="text-indent: 2em">第三部分实现单点登录（SingleSignOn）</p>
<p style="text-indent: 2em">&#8220;等了好久终于等到今天，写了好久终于就快完结，但是网友的反应却让我有一些的伤心。盼了好久终于盼到今天，忍了好久终于把此文撰写，那些受冷落的无奈早就无所谓，累也不说累&#8221;（歌词《今天》新演绎）。看着人家的Blog文章的评论是一条接一条，再瞧瞧自己：&#8220;无人问津呐，真&#8230;无&#8230;奈&#8230;&#8230;唉，没人理我，还是回家吧。&#8221;&#8220;哎，还没开始写，怎么就走了？回去干什么呢？&#8221;回去写作业去啊，上回交待的课外作业你做了没？（注：<a href="http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx"><font color="#3354ae">http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx</font></a>在第二部分第六节布置的课外作业：此项目有两部门使用，其中每个部门分别都有些特定的页面仅供本部门用户浏览使用，请问该如何使用Web.config达到效果？）</p>
<p style="text-indent: 2em">不知有多少人做了作业，其实答案并不难。只需要在验证用户名与密码后，取得该用户的部门名称或部门代码，把它作为判断的依据就行了。最好不要用部门的数字ID，那样不利于以后的维护。</p>
<p style="text-indent: 2em">有一个秘密，一般人我不告诉他。Web.config中的&lt;location&gt;节点的path属性可以是一张具体页面的相对URL路径，如下：&lt;location path="ManageSys/Auditing.aspx"&gt;</p>
<p style="text-indent: 2em">好了，接下来就要揭开&#8220;比根目录Web.config的作用范围还大的配置文件&#8221;之谜啦，它就是藏匿在Windows系统目录下，支配整个.NetFramework配置的传说中的Machine.config！！下面请大家以热烈的掌声，欢迎我们这位神秘侠客的闪亮登场&#8230;&#8230;</p>
<p style="text-indent: 2em">九、Machine.config</p>
<p style="text-indent: 2em">Machine.config，性别不详，年龄未知，家庭出身：XML。深藏于&#8220;云深不知处&#8221;的操作系统目录下的某某地方（注：C:"WINDOWS【或WINNT】"Microsoft.NET"Framework"v1.1.4322【或v1.0.3705】"CONFIG），控制着&#8220;更上一层楼&#8221;的.NETFramework的本机配置。接下来简要的讲解一下它的内容，以及它与Web.config的关系。</p>
<p style="text-indent: 2em">经过&#8220;松下问童子&#8221;，我们好不容易找到这位隐者，打开一看，乖乖，足有3700多行！！&#8220;叫我怎么能不难过，偶只想看看是啥结构，可内容实在是太多太繁琐&#8230;&#8230;&#8221;还记得偶经常对同事说的一句话么：&#8220;办法是人想出来的！&#8221;它不是有三千七百多行吗，那我们就不管三七能否得出二十一啦，把它拷出来先。它不是XML出身吗，那咱们就还其正身，重新命名为&#8220;machine.xml&#8221;。接着用IE浏览器将这位改头换面的隐者打开，把节点与注释一一合拢。这回你看到了吧，是不是很有成就感？你要是想谢谢我，就让我看到你在此文下面的评论吧。多多益善，呵呵。</p>
<p style="text-indent: 2em">Machine.config与Web.config是啥关系？四个字——父子关系。记得我在第二部分第五节讲解Web.config作用范围的时提到两点——继承与覆盖（详见<a href="http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx"><font color="#3354ae">http://blog.csdn.net/cityhunter172/archive/2005/11/13/528463.aspx</font></a>），在此也同样适用。</p>
<p style="text-indent: 2em">1、Machine.config中的设置将作用于运行在本机的所有站点及其虚拟目录，遇到子目录将一直继承下去。</p>
<p style="text-indent: 2em">2、Web.config中的设置将覆盖由Machine.config中继承下来的对应的节点设置</p>
<p style="text-indent: 2em">说到这，再告诉大家一个秘密——&#8220;世上本无秘密，知道的人多了，便成了不是秘密的秘密！&#8221;</p>
<p style="text-indent: 2em">a、Machine.config中的&lt;system.web&gt;节点所有内容都能出现在项目根目录下的Web.config中，也就是说能在Web.config中的内容已经在Machine.config中一一列出；</p>
<p style="text-indent: 2em">b、其中&lt;system.web&gt;节点下的&lt;pages&gt;还能出现在页面上，如：HTML视图下，在WebForm1.aspx的第一行加上&lt;pages&gt;的节点内容validateRequest="false"（此句意思是不对WebForm1.aspx页面文本框输入的值，是否包含&#8220;&lt;&#8221;&#8220;&gt;&#8221;等等具有危险性的代码进行检查，下一节将具体运用到）</p>
<p style="text-indent: 2em">&lt;%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="FromTest.WebForm1" validateRequest="false"%&gt;</p>
<p style="text-indent: 2em">十、单点登录（SingleSignOn）的前提条件</p>
<p style="text-indent: 2em">之前说了这么多关于Machine.config的事，都是为了实现单点登录作铺垫，那何为单点登录（SingleSignOn）？从字面理解就是在一个地方登录，通常运用于ASP.NET分布式环境中（跨单个服务器上的多个应用程序或在网络场中）的Forms身份验证。打个比方，就好比现在Sohu（搜狐）与Chinren（中国校友录）的做法，我在Sohu登录以后就不需要在Chinaren登录了。台湾与香港又把SingleSignOn称之为&#8220;单一登入&#8221;。</p>
<p style="text-indent: 2em">要想实现此功能，首要条件是需要一组用于加密与验证加密的密钥。它们位于Machine.config中，修改&lt;system.web&gt;节点下的&lt;machineKey&gt;节点属性，如下：</p>
<p style="text-indent: 2em">&lt;machineKey</p>
<p style="text-indent: 2em">firstKey="172"</p>
<p style="text-indent: 2em">copyrightKey="Cityhunter172"</p>
<p style="text-indent: 2em">validationKey="AD117F2F286CDCB15A9D1D4535E16DB0248026939**AUTHOR**CITYHUNTER172****WEBSITE**172*MEIBU*COM****MAILTO**CITYHUNTER172@126*COM*****F2F286CDCB15A9D1D4535E16DB0248026939"</p>
<p style="text-indent: 2em">secondKey="meibu"</p>
<p style="text-indent: 2em">decryptionKey="3C89AE62AD117F2F286CDCB15A9D1D4535E16DB0248026939" validation="SHA1"</p>
<p style="text-indent: 2em">thirdKey="com"</p>
<p style="text-indent: 2em">/&gt;</p>
<p style="text-indent: 2em">1、validationKey为用于验证加密数据的密钥。最小长度为40个字符（20字节），最大长度为128个字符（64字节）。</p>
<p style="text-indent: 2em">2、decryptionKey为用于加密数据的密钥。长度只有16个字符（8字节）与48个字符（24字节）两种。</p>
<p style="text-indent: 2em">3、validation为用数据验证使用的加密类型。拥有&#8220;SHA1&#8221;&#8220;MD5&#8221;&#8220;3DES&#8221;三种方法</p>
<p style="text-indent: 2em">4、大伙参照上述&lt;machineKey&gt;试着在WebForm1.aspx运行下列语句：</p>
<p style="text-indent: 2em">this.TextBox2.Text="ht"+"tp"+"://"+firstKey+"."+secondKey+"."+thirdKey</p>
<p style="text-indent: 2em">大家在修改之前请先备份一下Machine.config，到时要是出错可别怪我没提醒你。以上密钥并不是胡乱得来的，接下来向大家介绍生成密钥的方法。</p>
<p style="text-indent: 2em">我们把上一节中提到的WebForm1.aspx拖入本项目的Public目录下，再往页面上拖入一个TextMode=MultiLine的TextBox3与一个Button编写按钮事件与函数：</p>
<p style="text-indent: 2em">privatevoidButton1_Click(objectsender,System.EventArgse)</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">stringdecStr=this.CreateKeyString(int.Parse(this.TextBox1.Text));</p>
<p style="text-indent: 2em">stringvalStr=this.CreateKeyString(int.Parse(this.TextBox2.Text));</p>
<p style="text-indent: 2em">this.TextBox3.Text=string.Format("&lt;machineKeyvalidationKey=""{0}""decryptionKey=""{1}""validation=""SHA1""/&gt;",valStr,decStr);</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">///&lt;summary&gt;</p>
<p style="text-indent: 2em">///生成加密型强随机Key值</p>
<p style="text-indent: 2em">///&lt;/summary&gt;</p>
<p style="text-indent: 2em">///&lt;paramname="i"&gt;Key的有效长度：</p>
<p style="text-indent: 2em">///decryptionKey的有效值为8或24；</p>
<p style="text-indent: 2em">///validationKay的有效值为20至64</p>
<p style="text-indent: 2em">///&lt;/param&gt;</p>
<p style="text-indent: 2em">privatestringCreateKeyString(inti)</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">System.Security.Cryptography.RNGCryptoServiceProvider rng=newSystem.Security.Cryptography.RNGCryptoServiceProvider();//加密随机数生成器</p>
<p style="text-indent: 2em">byte[]bt=new byte[i];</p>
<p style="text-indent: 2em">rng.GetBytes(bt);//用加密型强随机值序列填充字节数组</p>
<p style="text-indent: 2em">System.Text.StringBuilder str=newSystem.Text.StringBuilder();</p>
<p style="text-indent: 2em">for(intj=0;j&lt;i;j++)</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">str.Append(string.Format("{0:X2}",bt[j]));//转换成大写的十六进制文本</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">returnstr.ToString();</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">每次点击按钮生成密钥都不同，大家不妨多点几次。切换至HTML视图，到WebForm1.aspx第一行把validateRequest="false"去掉，然后再多点几次Button1试试，看看会有什么效果，嘿嘿&#8230;&#8230;&#8230;</p>
<p style="text-indent: 2em"></p>
</div>
<img src ="http://www.blogjava.net/jvict/aggbug/319231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-04-23 23:36 <a href="http://www.blogjava.net/jvict/articles/319231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>WEB下使用的OFFICE控件介绍 </title><link>http://www.blogjava.net/jvict/articles/317337.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Fri, 02 Apr 2010 10:07:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/317337.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/317337.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/317337.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/317337.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/317337.html</trackback:ping><description><![CDATA[<h2>原文：<a href="http://www.cnblogs.com/xuneng/archive/2009/11/10/1599890.html">http://www.cnblogs.com/xuneng/archive/2009/11/10/1599890.html</a></h2>
<p>&nbsp;</p>
<h2>WEB下使用的OFFICE控件介绍，另提供一个原创破解</h2>
首先来个名词解释，Office<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=%CD%F8%C2%E7">网络</span>文档控件，就是在<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=%CD%F8%D2%B3">网页</span>中编辑office文档的控件（前提是browser已经安装OFFICE）。<br />
最近一个项目需要用到这个玩意，经过不泄努力的<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=%B0%D9%B6%C8">百度</span>和GOOLE，发现Office网络文档控件资源，目前国产的有以下几款：<br />
<br />
一、iWebOffice2006<br />
江西金格网络科技有限责任公司<br />
<a href="http://www.goldgrid.com/DownLoad/index.asp#Item24" target="_blank">http://www.goldgrid.com/DownLoad/index.asp#Item24</a><br />
我的简单意见：需要安装<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=%B7%FE%CE%F1%C6%F7">服务器</span>端组件，并进行一些COM+组件设置，当然客户端控件也是需要安装的。它的网络通讯都要经过它自己的组件和控件来进行，个人嫌麻烦，不建议使用。<br />
<br />
二、NTKO OFFICE文档控件<br />
重庆软航科技有限公司<br />
<a href="http://www.ntko.com/" target="_blank">http://www.ntko.com/</a><br />
我的简单意见：它的网站上有一年免费使用的版本。这个只需要客户端控件，个人试用效果还可以，建议使用。偶已经破解4.0.0.9版本，可以用到9999年12月31日。但是它有个缺点，就是控件中有2个标题栏，很讨厌。网上传播很广的3.0.0.7破解版也是这样。<br />
<br />
三、WebEditor 文档控件系列<br />
<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=%B9%E3%D6%DD">广州</span>帝龙科技&nbsp; &nbsp;<br />
<a href="http://www.dragongod.com/" target="_blank">Http://www.dragongod.com</a><br />
我的简单意见：其实这个产品和iWebOffice2006很相似，真怀疑它们的来历。不建议使用。<br />
<br />
四、WebOffice网络文档控件<br />
北京点聚信息技术有限公司<br />
<a href="http://www.dianju.com.cn/weboffice.htm" target="_blank">http://www.dianju.com.cn/<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=web">web</span>office.htm</a><br />
我 的简单意见：这个公司的WebOffice控件完全免费，功能也很不错，但是实际测试后发现，和WEB页面的一些元素定位、显示不是很兼容。比如如果给这 个控件定义一个style="display:none"的属性的话，运行结果是这个控件会跳出页面，单独显示一个窗口。但它毕竟是免费的，个人推荐使 用。<br />
<br />
五、soaoffice网络文档控件<br />
北京科翰软件有限公司<br />
<a href="http://www.kehansoft.com/" target="_blank">http://www.kehansoft.com/</a><br />
我的简单意见：这个公司的Office控件使用极其麻烦，因为它不是独立的，是和其他控件捆绑的，需要安装服务器端软件，我是坚决不用的。<br />
<br />
六、双进WORD网络文档控件<br />
南京双进科技咨询有限公司<br />
<a href="http://www.sjtsoft.com/" target="_blank">http://www.sjtsoft.com</a><br />
我的简单意见：没找到演示<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=%CF%C2%D4%D8">下载</span>，而且也只有word支持，不要去试了吧<br />
<br />
七、DSOFramer网络文档控件<br />
<a href="http://www.dsoframer.com/" target="_blank">http://www.dsoframer.com/</a><br />
我的简单意见：这个是免费开源的，很不错，建议使用。特别建议有时间，有兴趣的<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=%C5%F3%D3%D1">朋友</span>去看看。其实这个和点聚公司的那个WebOffice很像的，个人觉得点聚用的就是这个DSOFramer代码。<br />
<br />
除双进以外，以上各个Office网络文档控件的详细介绍、说明及演示代码在官方网站都有下载，我就不说了，这里提供偶自己亲手破解时间限制到9999年12月31号的NTKO OFFICE文档控件4.0.0.9演示版本。<br />
<br />
特别注意啊，这个ocx是没有经过数字签名的，是不能通过IE的ACTIVEX直接下载使用的，可以通过手工注册或者做个数字签名。这个操作就不多说了，网上教程一找一大把。<br />
<br />
另外，各OA系统，ERP软件等与OA有关的软件中一般都包含了Office网络文档控件，而且这些都是OEM的，可以永久免费使用，有兴趣的朋友可以去找找啊。<br />
<br />
关于NTKO OFFICE文档控件，我这里也提供一个&#8220;<span onclick="tagshow(event)" href="http://bbs.diy8.net/tag.php?name=%D6%D0%B9%FA">中国</span>兵器工业信息中心通达科技"的&#8221;Office Anywhere 3.0"OEM的，里面的是4.0.0.6的版本，使用的时候需要在object中加入以下代码：<br />
<br />
&lt;param name="MakerCaption" value="中国兵器工业信息中心通达科技"&gt; <br />
&lt;param name="MakerKey" value="86A1BE7CFEC466B6186E5425AFABB417B6016D68"&gt; <br />
&lt;param name="ProductCaption" value="Office Anywhere 3.0"&gt; <br />
&lt;param name="ProductKey" value="65F867689D7FF5CD02FBE4AA23764306F715A9E2"&gt;&nbsp;&nbsp;<br />
这样就成了OEM正式版的了。 
<img src ="http://www.blogjava.net/jvict/aggbug/317337.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-04-02 18:07 <a href="http://www.blogjava.net/jvict/articles/317337.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>BlogEngine.Net架构与源代码分析系列part1：开篇介绍</title><link>http://www.blogjava.net/jvict/articles/316590.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 25 Mar 2010 13:53:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/316590.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/316590.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/316590.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/316590.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/316590.html</trackback:ping><description><![CDATA[原文：http://tech.ddvip.com/2008-11/122638912191255.html<br />
<br />
最近我要开始这个系列了，这是我的第一个系列。关于BlogEngine.Net我想说的是，它设计的真的很棒，代码简洁但是功能很多，真是麻雀虽小，五脏俱全啊，而且具有了很多Web2.0的特征，甚至它的每一行代码都值得我们去研究一下，它的开发团队很棒。实际上很多国外的个人Blog都是采用BlogEngine.Net加上自定义皮肤实现的，如果您是一个Blog的开发者，这更是您的必备参考！
<p>　　很多兄弟都推荐BlogEngine.Net看一看，甚至www.asp.net也把它放在了很重要的位置。前一阶段我仔细的把它的源代码阅读了一遍，看完以后兴奋的很冲动，心想居然还有这么好的玩意，这个开源项目设计的真的不错。实际上前不久的一个Podcast项目我就是采用了类似BlogEngine.Net这种架构开发的，感觉还是很不错的。最近利用空闲的时间做了一下总结，准备写一个关于BlogEngine.Net系列文章，其实我早就想写一个系列文章，但是一直没有好的想法，对于我比较熟悉的方面发现园子里的兄弟都给写完了，但是关于BlogEngine.Net的文章似乎很少，所以我决定写这个系列，还希望园子中的兄弟们多支持一下啊。</p>
<p>　　开篇声明</p>
<p>　　本系列文章介绍的是BlogEngine.Net 1.4.5版本，这是官方前不久发布的一个版本。大家可以在http://www.codeplex.com/blogengine 下载最新的源代码和相应的说明文档。此外，您还可以在它的官方站点http://www.dotnetblogengine.net/上了解更多的安装和一些扩展开发等问题，还可以下载一些开发者已经做好的皮肤。讲解代码使用C#，基于.Net Framework2.0。</p>
<p>　　BlogEngine.Net简介</p>
<p>　　BlogEngine.NET是一个开源的.NET博客项目。整个项目采用C#开发，它的结构比较简单，但是扩展起来很容易，它的复杂程度较低，易于定制。扩展特性主要体现在以下三个方面：</p>
<p>　　1.Widget小工具</p>
<p>　　2.Extension扩展功能</p>
<p>　　3.自定义个性化Theme</p>
<p>　　最初它是一个单人博客，很容易将它实现成多人博客。codeplex上有一个案例就是基于BlogEngine.Net的多人博客。BlogEngine.Net的主要特性:</p>
<p>　　1.很容易被安装，只要把文件上传到Web服务器就可以运行。因为它默认采用XML存储数据。</p>
<p>　　2.具有很多Blog的新特性并提供了开放接口。例如Ajax评论，支持TrackBack等。</p>
<p>　　3.具有很多Web2.0特性，例如OpenSearch, XFN tags, tag cloud等。</p>
<p>　　4.自定义主题，您可以自己开发很多主题，类似博客园的主题。</p>
<p>　　5.可以配置自己的数据源，例如XML，Sql Server，SQLite等。</p>
<p>　　这个系列文章我将从BlogEngine.Net的架构入手，对于每个相对独立的部分进行一下代码分析并作出相应的总结，对于一些部分我会给出我个人的评价,对于一些比较好的细节部分我也会深入探讨。如果大家有一些反馈我还会及时调整。</p>
<p>　　暂定目录</p>
<p>　　下面是我初步定出的一个目录结构，也反映了系列文章的主要路线，请大家参考，这个目录可能在写的过程中会随时进行调整并加入已经完成文章的链接：</p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122638912191255.html">1.BlogEngine.Net架构与源代码分析系列part1：开篇介绍</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122638933591257.html">2.BlogEngine.Net架构与源代码分析系列part2：业务对象--共同的父类BusinessBase</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122638943691259.html">3.BlogEngine.Net架构与源代码分析系列part3：数据存储--基于Provider模式的实现</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122638956091261.html">4.BlogEngine.Net架构与源代码分析系列part4：Blog全局设置--BlogSettings</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122639003591267.html">5.BlogEngine.Net架构与源代码分析系列part5：对象搜索--IPublishable与Search</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122639019091269.html">6.BlogEngine.Net架构与源代码分析系列part6：开放API--MetaWeblog与BlogImporter</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122639067191272.html">7.BlogEngine.Net架构与源代码分析系列part7：Web2.0特性--Pingback&amp;Trackback</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122639089291277.html">8.BlogEngine.Net架构与源代码分析系列part8：扩展--DataStore分析</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122639102991280.html">9.BlogEngine.Net架构与源代码分析系列part9：开发扩展（上）--Extension与管理上的实现</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122646861991651.html">10.BlogEngine.Net架构与源代码分析系列part10：开发扩展（中）--Widget小工具</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122656483992313.html">11.BlogEngine.Net架构与源代码分析系列part11：开发扩展（下）--自定义Theme</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122656494292316.html">12.BlogEngine.Net架构与源代码分析系列part12：页面共同的基类--BlogBasePage</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122656505292318.html">13.BlogEngine.Net架构与源代码分析系列part13：实现分析（上）--HttpHandlers与HttpModules</a></p>
<p>　　<a href="http://tech.ddvip.com/2008-11/122665169092725.html">14.BlogEngine.Net架构与源代码分析系列part14：实现分析（下）--网站页面上值得参考的部分</a></p>
<p>　　<a href="http://tech.ddvip.com/2009-01/1232354127106377.html">15.BlogEngine.Net架构与源代码分析系列part15：总结篇</a></p>
<p>　　我写这个系列文章的目的有三个。首先将好的东西分享给大家，其次让我更加深入的研究BlogEngine.Net提高自己，最后作为一个备忘录存储在博客园上。</p>
<p>　　分享是一种美。</p>
<p>　　文章来源：<a href="http://thriving-country.cnblogs.com/">http://thriving-country.cnblogs.com/</a></p>
<!-- 分页 --><!-- 分页end -->
<img src ="http://www.blogjava.net/jvict/aggbug/316590.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-03-25 21:53 <a href="http://www.blogjava.net/jvict/articles/316590.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>解决SQL Server 2005 Management Studio Express 简体中文版 界面是英文的</title><link>http://www.blogjava.net/jvict/articles/316582.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 25 Mar 2010 13:12:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/316582.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/316582.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/316582.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/316582.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/316582.html</trackback:ping><description><![CDATA[<div style="list-style-position: inside; font-size: 14px; line-height: 180%">
<p><a href="http://www.cnblogs.com/xuyinjie/articles/1505484.html">原文：http://www.cnblogs.com/xuyinjie/articles/1505484.html</a><br />
<br />
在安装的时候要注意：在安装SQL Server 2005 Express时候需要将公共组件安装在C盘然后再安装SQL Server Management Studio Express中文版本，若将SQL Server 2005 Express时候需要将公共组件安装在其他逻辑盘上再安装SQL Server Management Studio Express时候中文版本时SQL Server Management Studio Express会成文英文版本，而不是中文版了。 这一点大家千万要注意。</p>
<p>&nbsp;</p>
<p>--------------------------------------------------------------------</p>
<p>注：上述说法是正确的，已经测试通过！装在C盘就是中文的，换到其它盘界面就成了英文！</p>
<p>--------------------------------------------------------------------</p>
<p>&nbsp;</p>
<p>再注：哈哈，解决了，很简单，把<br />
C:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\zh-CHS<br />
文件夹复制到用户更改的相应路径下即可，比如D盘：<br />
D:\Program Files\Microsoft SQL Server\90\Tools\Binn\VSShell\Common7\IDE\zh-CHS。<br />
如果对比，可以发现这两个文件夹里文件是不一样的，正是由于相应文件在 用户更改的相应路径下 缺失的缘故。</p>
</div>
<img src ="http://www.blogjava.net/jvict/aggbug/316582.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-03-25 21:12 <a href="http://www.blogjava.net/jvict/articles/316582.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET统计在线用户状态</title><link>http://www.blogjava.net/jvict/articles/316573.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 25 Mar 2010 11:32:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/316573.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/316573.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/316573.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/316573.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/316573.html</trackback:ping><description><![CDATA[<strong>原文：<a href="http://hi.baidu.com/lisky119/blog/item/44357aa1c0351f8047106401.html">http://hi.baidu.com/lisky119/blog/item/44357aa1c0351f8047106401.html</a><br />
<br />
解决用户意外退出在线列表无法及时更新问题 <br />
</strong><br />
<br />
&nbsp;&nbsp;&nbsp; 最近所做的一个项目需要用到的在线用户列表，上网搜索了一下发现现有的解决方案对用户意外退出的处理均不是太理想。一般来说，用户离开系统的方式有三种：主动注销、会话超时、直接关闭浏览器，对于前两种，我们很容易便可将该用户从在线列表中清除，关键是第三种（很多用户都是直接关闭窗口的~~郁闷ing），程序无法捕获窗口关闭的精确时间，只能等到会话超时后在能将该用户清除出在线列表，假设我们设置会话超时时间为60分钟，而用户登陆系统随便浏览一个页面就以关闭浏览器的方式退出的话，我们要在将近1小时后才能从在线列表中将该用户清除出去（想象一下，系统显示n多人在线，可能除了你之外其他的n-1人都关机走人了，汗一个先```），而本文将尝试寻找一个解决方案把这种尴尬降至最低。<br />
&nbsp;&nbsp;&nbsp; 我的大概思路是，给每在线用户增加一个RefreshTime属性，建立一个负责将当前用户的RefreshTime属性设置为当前时间的单独页面（Refresh.aspx），然后在系统的主要页面（也可以是所有页面）中通过xmlhttp不断地请求Refresh.aspx页面，一旦用户关闭了与本系统相关的所有窗口，即以直接关闭浏览器的方式退出系统，那么该用户的RefreshTime属性便不会自动更新了，我们再设置一个自动刷新的超时时间（这个要比会话超时短很多_refreshTimeout），当发现某用户超过_refreshTimeout的时间没有自动刷新，就能判定该用户已经以直接关闭浏览器的方式退出了。<br />
&nbsp;&nbsp;&nbsp; 假设我们设置会话超时时间为60分钟，自动刷新超时时间为1分钟，在客户端通过xmlhttp每隔25秒（之所以不设1分钟，是防止网速慢的时候访问Refresh.aspx超时，个人感觉，不一定正确）访问一次Refresh.aspx页面，在用户登陆、用户注销、检测用户是否在线的时候都执行清理超时用户（包括会话超时和自动刷新超时）操作，这样一来，在线用户列表的统计误差就由60分钟降至1分钟了。<br />
==========================================<br />
<br />
具体实现如下：
<p>1、 新建一个名为ActiveUser的类，存储单个活动用户数据。 <br />
/// &lt;summary&gt;<br />
/// 单个在线用户数据，无法继承此类。<br />
/// &lt;/summary&gt; <br />
public sealed class ActiveUser<br />
{ <br />
private readonly string _ticket;&nbsp;&nbsp;&nbsp; //票据名称<br />
private readonly string _username;&nbsp;&nbsp; //登陆用户名<br />
private readonly string _truename;&nbsp;&nbsp; //登陆用户名<br />
private readonly string _roleid;&nbsp;&nbsp;&nbsp; //角色<br />
private readonly DateTime _refreshtime; //最新刷新时间<br />
private readonly DateTime _activetime; //最新活动时间<br />
private readonly string _clientip;&nbsp;&nbsp; //登陆IP<br />
<br />
public ActiveUser(string Ticket,string UserName,string TrueName,string RoleID,string ClientIP) {<br />
&nbsp;&nbsp; this._ticket=Ticket;<br />
&nbsp;&nbsp; this._username=UserName;<br />
&nbsp;&nbsp; this._truename=TrueName;<br />
&nbsp;&nbsp; this._roleid=RoleID;<br />
&nbsp;&nbsp; this._refreshtime=DateTime.Now;<br />
&nbsp;&nbsp; this._activetime=DateTime.Now;<br />
&nbsp;&nbsp; this._clientip=ClientIP;<br />
}<br />
public ActiveUser(string Ticket,string UserName,string TrueName,string RoleID,DateTime RefreshTime,DateTime ActiveTime,string ClientIP) {<br />
&nbsp;&nbsp; this._ticket=Ticket;<br />
&nbsp;&nbsp; this._username=UserName;<br />
&nbsp;&nbsp; this._truename=TrueName;<br />
&nbsp;&nbsp; this._roleid=RoleID;<br />
&nbsp;&nbsp; this._refreshtime=RefreshTime;<br />
&nbsp;&nbsp; this._activetime=ActiveTime;<br />
&nbsp;&nbsp; this._clientip=ClientIP;<br />
}<br />
<br />
public string Ticket { get{return _ticket;} }<br />
public string UserName { get{return _username;} }<br />
public string TrueName { get{return _truename;} }<br />
public string RoleID { get{return _roleid;} }<br />
public DateTime RefreshTime { get{return _refreshtime;} }<br />
public DateTime ActiveTime { get{return _activetime;} }<br />
public string ClientIP { get{return _clientip;} }<br />
}<br />
</p>
<p>2、 新建一个名为PassPort的类，存储在线用户列表。<br />
/// &lt;summary&gt;<br />
/// PassPort 存储在线用户列表。<br />
/// &lt;/summary&gt;<br />
public class PassPort<br />
{<br />
private static DataTable _activeusers;<br />
private int _activeTimeout;<br />
private int _refreshTimeout;<br />
/// &lt;summary&gt;<br />
/// 初始化在线用户表。<br />
/// &lt;/summary&gt; <br />
private void userstableFormat()<br />
{<br />
&nbsp;&nbsp; if(_activeusers==null) {<br />
&nbsp;&nbsp;&nbsp; _activeusers = new DataTable("ActiveUsers");<br />
&nbsp;&nbsp;&nbsp; DataColumn myDataColumn;<br />
&nbsp;&nbsp;&nbsp; System.Type mystringtype;<br />
&nbsp;&nbsp;&nbsp; mystringtype = System.Type.GetType("System.String");<br />
&nbsp;&nbsp;&nbsp; System.Type mytimetype;<br />
&nbsp;&nbsp;&nbsp; mytimetype = System.Type.GetType("System.DateTime");<br />
&nbsp;&nbsp;&nbsp; myDataColumn = new DataColumn("Ticket",mystringtype);<br />
&nbsp;&nbsp;&nbsp; _activeusers.Columns.Add(myDataColumn);<br />
&nbsp;&nbsp;&nbsp; myDataColumn = new DataColumn("UserName",mystringtype);<br />
&nbsp;&nbsp;&nbsp; _activeusers.Columns.Add(myDataColumn);<br />
&nbsp;&nbsp;&nbsp; myDataColumn = new DataColumn("TrueName",mystringtype);<br />
&nbsp;&nbsp;&nbsp; _activeusers.Columns.Add(myDataColumn);<br />
&nbsp;&nbsp;&nbsp; myDataColumn = new DataColumn("RoleID",mystringtype);<br />
&nbsp;&nbsp;&nbsp; _activeusers.Columns.Add(myDataColumn);&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; myDataColumn = new DataColumn("RefreshTime",mytimetype);<br />
&nbsp;&nbsp;&nbsp; _activeusers.Columns.Add(myDataColumn);<br />
&nbsp;&nbsp;&nbsp; myDataColumn = new DataColumn("ActiveTime",mytimetype);<br />
&nbsp;&nbsp;&nbsp; _activeusers.Columns.Add(myDataColumn);<br />
&nbsp;&nbsp;&nbsp; myDataColumn = new DataColumn("ClientIP",mystringtype);<br />
&nbsp;&nbsp;&nbsp; _activeusers.Columns.Add(myDataColumn);&nbsp;&nbsp; <br />
&nbsp;&nbsp; }<br />
}<br />
public PassPort()<br />
{<br />
&nbsp;&nbsp; userstableFormat(); //初始化在线用户表<br />
&nbsp;&nbsp; //活动超时时间初始化 单位：分钟<br />
&nbsp;&nbsp; try { _activeTimeout=int.Parse(ConfigurationSettings.AppSettings["ActiveTimeout"]); }<br />
&nbsp;&nbsp; catch{ _activeTimeout=60; }&nbsp;&nbsp; <br />
&nbsp;&nbsp; //自动刷新超时时间初始化 单位：分钟<br />
&nbsp;&nbsp; try { _refreshTimeout=int.Parse(ConfigurationSettings.AppSettings["RefreshTimeout"]); }<br />
&nbsp;&nbsp; catch{ _refreshTimeout=1; }&nbsp;&nbsp; <br />
}<br />
//全部用户列表<br />
public DataTable ActiveUsers<br />
{<br />
&nbsp;&nbsp; get{return _activeusers.Copy();}<br />
}<br />
<br />
/// &lt;summary&gt;<br />
/// 新用户登陆。<br />
/// &lt;/summary&gt;<br />
public void Login(ActiveUser user,bool SingleLogin)<br />
{<br />
&nbsp;&nbsp; DelTimeOut(); //清除超时用户<br />
&nbsp;&nbsp; if(SingleLogin){<br />
&nbsp;&nbsp;&nbsp; //若是单人登陆则注销原来登陆的用户<br />
&nbsp;&nbsp;&nbsp; this.Logout(user.UserName,false);<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; DataRow myRow;<br />
&nbsp;&nbsp; try<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; myRow = _activeusers.NewRow();&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; myRow["Ticket"] = user.Ticket.Trim();<br />
&nbsp;&nbsp;&nbsp; myRow["UserName"] = user.UserName.Trim();<br />
&nbsp;&nbsp;&nbsp; myRow["TrueName"] = ""+user.TrueName.Trim();<br />
&nbsp;&nbsp;&nbsp; myRow["RoleID"] = ""+user.RoleID.Trim();<br />
&nbsp;&nbsp;&nbsp; myRow["ActiveTime"] = DateTime.Now;<br />
&nbsp;&nbsp;&nbsp; myRow["RefreshTime"] = DateTime.Now;<br />
&nbsp;&nbsp;&nbsp; myRow["ClientIP"] = user.ClientIP.Trim();<br />
&nbsp;&nbsp;&nbsp; _activeusers.Rows.Add(myRow);<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; catch(Exception e)<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; throw(new Exception(e.Message));<br />
&nbsp;&nbsp; } <br />
&nbsp;&nbsp; _activeusers.AcceptChanges();<br />
&nbsp;&nbsp; <br />
}<br />
/// &lt;summary&gt;<br />
///用户注销，根据Ticket或UserName。<br />
/// &lt;/summary&gt; <br />
private void Logout(string strUserKey,bool byTicket)<br />
{<br />
&nbsp;&nbsp; DelTimeOut(); //清除超时用户<br />
&nbsp;&nbsp; strUserKey=strUserKey.Trim();<br />
&nbsp;&nbsp; string strExpr;&nbsp;&nbsp; <br />
&nbsp;&nbsp; strExpr =byTicket ? "Ticket='" + strUserKey +"'" : "UserName='" + strUserKey + "'";<br />
&nbsp;&nbsp; DataRow[] curUser;<br />
&nbsp;&nbsp; curUser = _activeusers.Select(strExpr);<br />
&nbsp;&nbsp; if (curUser.Length &gt;0 )<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; curUser.Length; i ++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; curUser[i].Delete();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; _activeusers.AcceptChanges();&nbsp;&nbsp; <br />
}<br />
/// &lt;summary&gt;<br />
///用户注销，根据Ticket。<br />
/// &lt;/summary&gt;<br />
/// &lt;param name="strTicket"&gt;要注销的用户Ticket&lt;/param&gt;<br />
public void Logout(string strTicket){<br />
&nbsp;&nbsp; this.Logout(strTicket,true);<br />
}<br />
/// &lt;summary&gt;<br />
///清除超时用户。<br />
/// &lt;/summary&gt;<br />
private bool DelTimeOut()<br />
{&nbsp;&nbsp; <br />
&nbsp;&nbsp; string strExpr;&nbsp;&nbsp; <br />
&nbsp;&nbsp; strExpr = "ActiveTime &lt; '" + DateTime.Now.AddMinutes( 0 - _activeTimeout) + "'or RefreshTime &lt; '"+DateTime.Now.AddMinutes( 0 - _refreshTimeout)+"'";&nbsp;&nbsp; <br />
&nbsp;&nbsp; DataRow[] curUser;<br />
&nbsp;&nbsp; curUser = _activeusers.Select(strExpr);<br />
&nbsp;&nbsp; if (curUser.Length &gt;0 )<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; curUser.Length; i ++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; curUser[i].Delete();&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; _activeusers.AcceptChanges();<br />
&nbsp;&nbsp; return true;<br />
}<br />
/// &lt;summary&gt;<br />
///更新用户活动时间。<br />
/// &lt;/summary&gt;<br />
public void ActiveTime(string strTicket)<br />
{<br />
&nbsp;&nbsp; DelTimeOut();<br />
&nbsp;&nbsp; string strExpr;<br />
&nbsp;&nbsp; strExpr = "Ticket='" + strTicket + "'"; <br />
&nbsp;&nbsp; DataRow[] curUser;<br />
&nbsp;&nbsp; curUser = _activeusers.Select(strExpr);<br />
&nbsp;&nbsp; if (curUser.Length &gt;0 )<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; curUser.Length; i ++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; curUser[i]["ActiveTime"]=DateTime.Now;<br />
&nbsp;&nbsp;&nbsp;&nbsp; curUser[i]["RefreshTime"]=DateTime.Now;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; _activeusers.AcceptChanges();<br />
}<br />
/// &lt;summary&gt;<br />
///更新系统自动刷新时间。<br />
/// &lt;/summary&gt;<br />
public void RefreshTime(string strTicket)<br />
{<br />
&nbsp;&nbsp; DelTimeOut();<br />
&nbsp;&nbsp; string strExpr;<br />
&nbsp;&nbsp; strExpr = "Ticket='" + strTicket + "'"; <br />
&nbsp;&nbsp; DataRow[] curUser;<br />
&nbsp;&nbsp; curUser = _activeusers.Select(strExpr);<br />
&nbsp;&nbsp; if (curUser.Length &gt;0 )<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; for(int i = 0; i &lt; curUser.Length; i ++)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; curUser[i]["RefreshTime"]=DateTime.Now;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; _activeusers.AcceptChanges();<br />
}<br />
private ActiveUser SingleUser(string strUserKey,bool byTicket)<br />
{<br />
&nbsp;&nbsp; strUserKey=strUserKey.Trim();<br />
&nbsp;&nbsp; string strExpr;<br />
&nbsp;&nbsp; ActiveUser myuser;<br />
&nbsp;&nbsp; strExpr =byTicket ? "Ticket='" + strUserKey +"'" : "UserName='" + strUserKey + "'"; <br />
&nbsp;&nbsp; DataRow[] curUser;<br />
&nbsp;&nbsp; curUser = _activeusers.Select(strExpr);<br />
&nbsp;&nbsp; if (curUser.Length &gt;0 )<br />
{<br />
&nbsp;&nbsp;&nbsp; string myTicket=(string)curUser[0]["Ticket"];<br />
&nbsp;&nbsp;&nbsp; string myUser=(string)curUser[0]["UserName"];<br />
&nbsp;&nbsp;&nbsp; string myName=(string)curUser[0]["TrueName"];<br />
&nbsp;&nbsp;&nbsp; string myRoleID=(string)curUser[0]["RoleID"];&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; DateTime myActiveTime=(DateTime)curUser[0]["ActiveTime"];<br />
&nbsp;&nbsp;&nbsp; DateTime myRefreshtime=(DateTime)curUser[0]["RefreshTime"];<br />
&nbsp;&nbsp;&nbsp; string myClientIP =(string)curUser[0]["ClientIP"];<br />
&nbsp;&nbsp;&nbsp; myuser=new ActiveUser(myTicket,myUser,myName,myRoleID,myActiveTime,myRefreshtime,myClientIP); <br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; else<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; myuser=new ActiveUser("","","","","");&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; return myuser;<br />
}<br />
/// &lt;summary&gt;<br />
///按Ticket获取活动用户。<br />
/// &lt;/summary&gt;<br />
public ActiveUser SingleUser_byTicket(string strTicket)<br />
{<br />
&nbsp;&nbsp; return this.SingleUser(strTicket,true);<br />
}<br />
/// &lt;summary&gt;<br />
///按UserName获取活动用户。<br />
/// &lt;/summary&gt;<br />
public ActiveUser SingleUser_byUserName(string strUserName)<br />
{<br />
&nbsp;&nbsp; return this.SingleUser(strUserName,false);<br />
}<br />
/// &lt;summary&gt;<br />
///按Ticket判断用户是否在线。<br />
/// &lt;/summary&gt;<br />
public bool IsOnline_byTicket(string strTicket)<br />
{<br />
&nbsp;&nbsp; return (bool)(this.SingleUser(strTicket,true).UserName!="");<br />
}<br />
/// &lt;summary&gt;<br />
///按UserName判断用户是否在线。<br />
/// &lt;/summary&gt;<br />
public bool IsOnline_byUserName(string strUserName)<br />
{<br />
&nbsp;&nbsp; return (bool)(this.SingleUser(strUserName,false).UserName!="");<br />
}<br />
}</p>
<p>3、 新建一个继承自PlaceHolder名为Refresh的类，执行更新自动刷新时间操作。<br />
<br />
/// &lt;summary&gt;<br />
/// Refresh 执行更新自动刷新时间操作。<br />
/// &lt;/summary&gt;<br />
public class Refresh: PlaceHolder <br />
{<br />
/// &lt;summary&gt;<br />
/// 设置存储Ticket的Session名称，默认为Ticket。<br />
/// &lt;/summary&gt;<br />
public virtual string SessionName<br />
{<br />
&nbsp;&nbsp; get{<br />
&nbsp;&nbsp;&nbsp; object obj1 = this.ViewState["SessionName"];<br />
&nbsp;&nbsp;&nbsp; if (obj1 != null){ return ((string) obj1).Trim(); }<br />
&nbsp;&nbsp;&nbsp; return "Ticket";<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; set{<br />
&nbsp;&nbsp;&nbsp; this.ViewState["SessionName"] = value;<br />
&nbsp;&nbsp; }<br />
}<br />
protected override void Render(HtmlTextWriter writer) <br />
{<br />
&nbsp;&nbsp; string myTicket=(string)this.Page.Session[this.SessionName];<br />
&nbsp;&nbsp; if(myTicket!=null)<br />
&nbsp;&nbsp; {&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; PassPort myPass = new PassPort();<br />
&nbsp;&nbsp;&nbsp; myPass.RefreshTime(myTicket);<br />
&nbsp;&nbsp;&nbsp; writer.Write("OK："+DateTime.Now.ToString());<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; else{<br />
&nbsp;&nbsp;&nbsp; writer.Write("Sorry："+DateTime.Now.ToString());<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; base.Render(writer);<br />
}<br />
}<br />
4、 新建一个继承自PlaceHolder名为Script的类，生成执行xmlhttp的js脚本。。</p>
<p>/// &lt;summary&gt;<br />
/// Script 生成执行xmlhttp的js脚本。<br />
/// &lt;/summary&gt;<br />
public class Script: PlaceHolder<br />
{<br />
/// &lt;summary&gt;<br />
/// 设置js自动刷新的间隔时间，默认为25秒。<br />
/// &lt;/summary&gt;<br />
public virtual int RefreshTime<br />
{<br />
&nbsp;&nbsp; get<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; object obj1 = this.ViewState["RefreshTime"];<br />
&nbsp;&nbsp;&nbsp; if (obj1 != null){return int.Parse(((string) obj1).Trim());}<br />
&nbsp;&nbsp;&nbsp; return 25;<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; set<br />
&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; this.ViewState["RefreshTime"] = value;<br />
&nbsp;&nbsp; }<br />
}<br />
protected override void Render(HtmlTextWriter writer) <br />
{<br />
&nbsp;&nbsp; //从web.config中读取xmlhttp的访问地址<br />
&nbsp;&nbsp; string refreshUrl=(string)ConfigurationSettings.AppSettings["refreshUrl"];<br />
&nbsp;&nbsp; string scriptString = @" &lt;script language=""JavaScript""&gt;"+writer.NewLine;<br />
&nbsp;&nbsp; scriptString += @" window.attachEvent(""onload"", "<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#43;&#116;&#104;&#105;&#115;&#46;&#67;&#108;&#105;&#101;&#110;&#116;&#73;&#68;&#43;&#64;&#37;&#50;&#50;&#95;&#112;&#111;&#115;&#116;&#82;&#101;&#102;&#114;&#101;&#115;&#104;&#41;&#59;&#37;&#50;&#50;&#43;&#119;&#114;&#105;&#116;&#101;&#114;&#46;&#78;&#101;&#119;&#76;&#105;&#110;&#101;">+this.ClientID+@"_postRefresh);"+writer.NewLine</a>;<br />
&nbsp;&nbsp; scriptString += @" var "<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#43;&#116;&#104;&#105;&#115;&#46;&#67;&#108;&#105;&#101;&#110;&#116;&#73;&#68;&#43;&#64;&#37;&#50;&#50;&#95;&#120;&#109;&#108;&#104;&#116;&#116;&#112;&#61;&#110;&#117;&#108;&#108;&#59;&#37;&#50;&#50;&#43;&#119;&#114;&#105;&#116;&#101;&#114;&#46;&#78;&#101;&#119;&#76;&#105;&#110;&#101;">+this.ClientID+@"_xmlhttp=null;"+writer.NewLine</a>;<br />
&nbsp;&nbsp; scriptString += @" function "<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#43;&#116;&#104;&#105;&#115;&#46;&#67;&#108;&#105;&#101;&#110;&#116;&#73;&#68;&#43;&#64;&#37;&#50;&#50;&#95;&#112;&#111;&#115;&#116;&#82;&#101;&#102;&#114;&#101;&#115;&#104;&#40;&#41;&#37;&#55;&#66;&#37;&#50;&#50;&#43;&#119;&#114;&#105;&#116;&#101;&#114;&#46;&#78;&#101;&#119;&#76;&#105;&#110;&#101;">+this.ClientID+@"_postRefresh(){"+writer.NewLine</a>;<br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp; var "<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#43;&#116;&#104;&#105;&#115;&#46;&#67;&#108;&#105;&#101;&#110;&#116;&#73;&#68;&#43;&#64;&#37;&#50;&#50;&#95;&#120;&#109;&#108;&#104;&#116;&#116;&#112;">+this.ClientID+@"_xmlhttp</a> = new ActiveXObject(""Msxml2.XMLHTTP"");"+writer.NewLine;<br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp; "<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#43;&#116;&#104;&#105;&#115;&#46;&#67;&#108;&#105;&#101;&#110;&#116;&#73;&#68;&#43;&#64;&#37;&#50;&#50;&#95;&#120;&#109;&#108;&#104;&#116;&#116;&#112;&#46;&#79;&#112;&#101;&#110;&#40;&#37;&#50;&#50;&#37;&#50;&#50;&#80;&#79;&#83;&#84;">+this.ClientID+@"_xmlhttp.Open(""POST</a>"", """+refreshUrl+@""", false);"+writer.NewLine;<br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp; "<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#43;&#116;&#104;&#105;&#115;&#46;&#67;&#108;&#105;&#101;&#110;&#116;&#73;&#68;&#43;&#64;&#37;&#50;&#50;&#95;&#120;&#109;&#108;&#104;&#116;&#116;&#112;&#46;&#83;&#101;&#110;&#100;&#40;&#41;&#59;&#37;&#50;&#50;&#43;&#119;&#114;&#105;&#116;&#101;&#114;&#46;&#78;&#101;&#119;&#76;&#105;&#110;&#101;">+this.ClientID+@"_xmlhttp.Send();"+writer.NewLine</a>;<br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp; var refreshStr= "<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#43;&#116;&#104;&#105;&#115;&#46;&#67;&#108;&#105;&#101;&#110;&#116;&#73;&#68;&#43;&#64;&#37;&#50;&#50;&#95;&#120;&#109;&#108;&#104;&#116;&#116;&#112;&#46;&#114;&#101;&#115;&#112;&#111;&#110;&#115;&#101;&#84;&#101;&#120;&#116;&#59;&#37;&#50;&#50;&#43;&#119;&#114;&#105;&#116;&#101;&#114;&#46;&#78;&#101;&#119;&#76;&#105;&#110;&#101;">+this.ClientID+@"_xmlhttp.responseText;"+writer.NewLine</a>;<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp; try {"+writer.NewLine;<br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp;&nbsp; var refreshStr2=refreshStr;"+writer.NewLine;<br />
&nbsp;&nbsp; //scriptString += @"&nbsp;&nbsp;&nbsp; alert(refreshStr2);"+writer.NewLine;<br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp; }"+writer.NewLine;<br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp; catch(e) {}"+writer.NewLine;<br />
&nbsp;&nbsp; scriptString += @"&nbsp;&nbsp; setTimeout("""<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#43;&#116;&#104;&#105;&#115;&#46;&#67;&#108;&#105;&#101;&#110;&#116;&#73;&#68;&#43;&#64;&#37;&#50;&#50;&#95;&#112;&#111;&#115;&#116;&#82;&#101;&#102;&#114;&#101;&#115;&#104;&#40;&#41;&#37;&#50;&#50;&#37;&#50;&#50;&#44;&#37;&#50;&#50;&#43;&#116;&#104;&#105;&#115;&#46;&#82;&#101;&#102;&#114;&#101;&#115;&#104;&#84;&#105;&#109;&#101;&#46;&#84;&#111;&#83;&#116;&#114;&#105;&#110;&#103;&#40;&#41;&#43;&#64;&#37;&#50;&#50;&#48;&#48;&#48;&#41;&#59;&#37;&#50;&#50;&#43;&#119;&#114;&#105;&#116;&#101;&#114;&#46;&#78;&#101;&#119;&#76;&#105;&#110;&#101;">+this.ClientID+@"_postRefresh()"","+this.RefreshTime.ToString()+@"000);"+writer.NewLine</a>;<br />
&nbsp;&nbsp; scriptString += @" }"+writer.NewLine;<br />
&nbsp;&nbsp; scriptString += @"&lt;";<br />
&nbsp;&nbsp; scriptString += @"/";<br />
&nbsp;&nbsp; scriptString += @"script&gt;"+writer.NewLine;<br />
&nbsp;&nbsp; writer.Write(writer.NewLine);<br />
&nbsp;&nbsp; writer.Write(scriptString);<br />
&nbsp;&nbsp; writer.Write(writer.NewLine);<br />
&nbsp;&nbsp; base.Render(writer);<br />
}<br />
}</p>
<p>注意以上四个类同属于一个名为OnlineUser的工程，他们的命名空间为OnlineUser，编译生成一个dll。<br />
</p>
<p>===============================================<br />
<br />
下面我简单介绍一下调用方法：<br />
1、 新建一个名为OnlineUserDemo的asp.net web应用程序<br />
2、 在vs的工具箱选项卡上右击，选择[添加/移除项]，浏览定位到OnlineUser.dll，确定即可把Refresh 和Script添加到工具箱。<br />
3、 把自动生成的WebForm1.aspx删除，并设置web.config<br />
&lt;appSettings&gt;<br />
&nbsp;&nbsp; &lt;add key="ActiveTimeout" value="30" /&gt;<br />
&nbsp;&nbsp; &lt;add key="RefreshTimeout" value="1" /&gt;<br />
&nbsp;&nbsp; &lt;add key="refreshUrl" value="refresh.aspx" /&gt;<br />
&lt;/appSettings&gt;<br />
4、 添加一个名为Online.aspx的web窗体，给该窗体添加一个Script控件，一个DataGrid控件（id为DataGrid1），两个HyperLink控件（分别链接到login.aspx和logout.aspx，text属性分别设置为&#8220;登陆&#8221;和&#8220;注销&#8221;），调整好四个控件的位置，转到codebehind，在Page_Load中加入如下代码：<br />
string myTicket=(string)this.Page.Session["Ticket"];<br />
&nbsp;&nbsp; if(myTicket!=null)<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; OnlineUser.PassPort myPassPort= new OnlineUser.PassPort();<br />
&nbsp;&nbsp;&nbsp; if(myPassPort.IsOnline_byTicket(this.Session["Ticket"].ToString()))<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; myPassPort.ActiveTime(this.Session["Ticket"].ToString());<br />
&nbsp;&nbsp;&nbsp;&nbsp; DataGrid1.DataSource=myPassPort.ActiveUsers;<br />
&nbsp;&nbsp;&nbsp;&nbsp; DataGrid1.DataBind();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; else{<br />
&nbsp;&nbsp;&nbsp;&nbsp; //若在线用户列表中找不到当前用户,则定向到注销页面<br />
&nbsp;&nbsp;&nbsp;&nbsp; Response.Redirect("Logout.aspx");<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; else{<br />
&nbsp;&nbsp;&nbsp; Response.Redirect("Login.aspx");<br />
&nbsp;&nbsp; }<br />
5、 添加一个名为login.aspx的web窗体，给该窗体添加一个label控件（id为Label1），设置text属性为&#8220;输入一个用户名&#8221;，再添加一个textbox控件（id为TextBox1）和一个button控件（id为Button1），调整好他们的位置，双击Button1控件转到codebehind，为Button1的Click事件加入如下代码：<br />
if(TextBox1.Text.Trim()=="")<br />
&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp; //不能为空<br />
&nbsp;&nbsp;&nbsp; String scriptString = @"&lt;script language=JavaScript&gt;";<br />
&nbsp;&nbsp;&nbsp; scriptString += @"alert(""输入一个用户名\n"");"; <br />
&nbsp;&nbsp;&nbsp; scriptString += @"history.go(-1);";<br />
&nbsp;&nbsp;&nbsp; scriptString += @"&lt;";<br />
&nbsp;&nbsp;&nbsp; scriptString += @"/";<br />
&nbsp;&nbsp;&nbsp; scriptString += @"script&gt;";<br />
&nbsp;&nbsp;&nbsp; if(!this.Page.IsStartupScriptRegistered("Startup"))<br />
&nbsp;&nbsp;&nbsp;&nbsp; this.Page.RegisterStartupScript("Startup", scriptString);<br />
&nbsp;&nbsp; }<br />
&nbsp;&nbsp; else{<br />
&nbsp;&nbsp;&nbsp; OnlineUser.PassPort myPassPort= new OnlineUser.PassPort();<br />
&nbsp;&nbsp;&nbsp; string myTicket=DateTime.Now.ToString("yyyyMMddHHmmss");<br />
&nbsp;&nbsp;&nbsp; string myUser=TextBox1.Text.Trim();<br />
&nbsp;&nbsp;&nbsp; string myClintIP=this.Request.UserHostAddress;<br />
&nbsp;&nbsp;&nbsp; this.Session["Ticket"]=myTicket;<br />
&nbsp;&nbsp;&nbsp; OnlineUser.ActiveUser myActiveUser=new OnlineUser.ActiveUser(myTicket,myUser,myUser,"test",myClintIP);<br />
&nbsp;&nbsp;&nbsp; myPassPort.Login(myActiveUser,true);<br />
&nbsp;&nbsp;&nbsp; Response.Redirect("Online.aspx");<br />
&nbsp;&nbsp; }<br />
6、 添加一个名为logout.aspx的web窗体，给该窗体添加一个HyperLink控件，指向login.aspx，text属性设置为&#8220;重登陆&#8221;转到codebehind，在Page_Load中加入如下代码：<br />
OnlineUser.PassPort myPassPort= new OnlineUser.PassPort();<br />
myPassPort.Logout(this.Session["Ticket"].ToString());<br />
this.Session["Ticket"]="";<br />
7、 添加一个名为Refresh.txt的文本文件，设置其内容为：<br />
&lt;%@ Register TagPrefix="cc2" Namespace="OnlineUser" Assembly="OnlineUser" %&gt;<br />
&lt;%@ Page %&gt;<br />
&lt;cc2:Refresh id="myRefresh" runat="server"&gt;&lt;/cc2:Refresh&gt;<br />
把Refresh.txt改名为Refresh.aspx<br />
8、 编译生成工程。<br />
===============================================</p>
<p>下面进行功能测试：<br />
1、 打开浏览器，在地址栏输入<br />
http://你机器的IP地址/onlineuserdemo/Login.aspx<br />
2、 输入一个用户名（假设是test1）登陆，自动转到online.aspx页面<br />
3、 找同网段的另外一台机器（设你的机器为a，这台机器为b），重复执行第一步。<br />
4、 输入一个用户名（假设是test2）登陆，自动转到online.aspx页面<br />
5、 在b机器不断刷新online.aspx，若发现test1用户RefreshTime每过25秒自动更新一次而ActiveTime不变（这个时候a机器不要刷新页面啊），则证明a机器的自动刷新生效。<br />
6、 在a机器不断刷新online.aspx，若发现test2用户RefreshTime每过25秒自动更新一次而ActiveTime不变（这个时候b机器不要刷新页面啊），则证明b机器的自动刷新生效。<br />
7、 直接关闭一台机器（假设是a）上的online.aspx浏览窗口，在另一台机器（就是b啦）上刷新online.aspx，若发现1分钟后test1掉线在线用户只剩下test2，证明通过_refreshTimeout清除在线用户成功。<br />
8、 若5、6、7三步正常，则大功告成，否则就再调试调试~~</p>
<img src ="http://www.blogjava.net/jvict/aggbug/316573.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-03-25 19:32 <a href="http://www.blogjava.net/jvict/articles/316573.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>asp.net检测在线用户</title><link>http://www.blogjava.net/jvict/articles/316572.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 25 Mar 2010 11:27:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/316572.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/316572.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/316572.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/316572.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/316572.html</trackback:ping><description><![CDATA[<p><a href="http://hi.baidu.com/freezesoul/blog/item/449b247f9578570828388ac1.html">原文：http://hi.baidu.com/freezesoul/blog/item/449b247f9578570828388ac1.html</a></p>
<p>//online.cs(用户在线检测) <br />
/*程序实现思路： <br />
<br />
该用户有以下几个属性： <br />
name:用户名 <br />
sessionID:用户ID,通过它唯一表示一个用户 <br />
iswhere :附加信息，用户当前所在位置 <br />
lasttime:用户登陆时间 <br />
curtime：本次刷新时间 <br />
<br />
在客户端，使用一个IFRAME，装载一个刷新页面，每隔XX秒更新一下他的名字对应的curtime，就表示他仍然在 <br />
<br />
在服务器端，建立一个守护线程，每隔固定时间就运行一遍，然后判断当前所有用户列表中的时间间隔是否超出了规定的时间，如果超出，则将该用户从在线列表中删除，这样就可以做到检测用户是否在线了，而如果再单独 <br />
写个用户离线后的处理，就可以解决好多人问到的：用户意外吊线后的处理。 <br />
*/ <br />
<br />
#define DEBUG <br />
<br />
using System; <br />
using System.Data; <br />
using System.Data.SqlClient; <br />
using System.Collections ; <br />
using System.Threading ; <br />
using System.Web; <br />
using System.Diagnostics; <br />
<br />
namespace SohoProject <br />
{ <br />
//定义了一个结构 <br />
public struct User <br />
{ <br />
public string name; <br />
public DateTime lasttime; <br />
public DateTime curtime; <br />
public string sessionid; <br />
public string ip; <br />
public string iswhere; <br />
} <br />
<br />
public class OnLineUser <br />
{ <br />
private static DataTable _alluser; <br />
<br />
//只读属性 <br />
public DataTable alluser{ <br />
get{return _alluser;} <br />
} <br />
<br />
public OnLineUser() <br />
{ <br />
if(_alluser==null) <br />
{ <br />
//define user list <br />
// Declare variables for DataColumn and DataRow objects. <br />
_alluser = new DataTable("onlineuser"); <br />
<br />
DataColumn myDataColumn; <br />
<br />
// Create new DataColumn, set DataType, ColumnName and add to DataTable. <br />
myDataColumn = new DataColumn(); <br />
myDataColumn.DataType = System.Type.GetType("System.String"); <br />
myDataColumn.ColumnName = "name"; <br />
myDataColumn.AutoIncrement = false; <br />
myDataColumn.Caption = "name"; <br />
myDataColumn.ReadOnly = false; <br />
myDataColumn.Unique = false; <br />
_alluser.Columns.Add(myDataColumn); <br />
<br />
<br />
// Create sessionid column. <br />
myDataColumn = new DataColumn(); <br />
myDataColumn.DataType = System.Type.GetType("System.String"); <br />
myDataColumn.ColumnName = "sessionid"; <br />
myDataColumn.AutoIncrement = false; <br />
myDataColumn.Caption = "sessionid"; <br />
myDataColumn.ReadOnly = false; <br />
myDataColumn.Unique = true; <br />
_alluser.Columns.Add(myDataColumn); <br />
<br />
// Create ip column. <br />
myDataColumn = new DataColumn(); <br />
myDataColumn.DataType = System.Type.GetType("System.String"); <br />
myDataColumn.ColumnName = "ip"; <br />
myDataColumn.AutoIncrement = false; <br />
myDataColumn.Caption = "ip"; <br />
myDataColumn.ReadOnly = false; <br />
myDataColumn.Unique = false; <br />
_alluser.Columns.Add(myDataColumn); <br />
<br />
// Create iswhere column. <br />
myDataColumn = new DataColumn(); <br />
myDataColumn.DataType = System.Type.GetType("System.String"); <br />
myDataColumn.ColumnName = "iswhere"; <br />
myDataColumn.AutoIncrement = false; <br />
myDataColumn.Caption = "iswhere"; <br />
myDataColumn.ReadOnly = false; <br />
myDataColumn.Unique = false; <br />
_alluser.Columns.Add(myDataColumn); <br />
<br />
// Create iswhere column. <br />
myDataColumn = new DataColumn(); <br />
myDataColumn.DataType = System.Type.GetType("System.DateTime"); <br />
myDataColumn.ColumnName = "lasttime"; <br />
myDataColumn.AutoIncrement = false; <br />
myDataColumn.Caption = "lasttime"; <br />
myDataColumn.ReadOnly = false; <br />
myDataColumn.Unique = false; <br />
_alluser.Columns.Add(myDataColumn); <br />
<br />
// Create iswhere column. <br />
myDataColumn = new DataColumn(); <br />
myDataColumn.DataType = System.Type.GetType("System.DateTime"); <br />
myDataColumn.ColumnName = "curtime"; <br />
myDataColumn.AutoIncrement = false; <br />
myDataColumn.Caption = "curtime"; <br />
myDataColumn.ReadOnly = false; <br />
myDataColumn.Unique = false; <br />
_alluser.Columns.Add(myDataColumn); <br />
} <br />
} <br />
<br />
<br />
//功能说明：将当前用户加入在线列表 <br />
//如果该用户的数据当前仍然在在线列表中，则暂时先不让该用户登陆,提示用户存在 <br />
public bool AddUserToOnLine(User user) <br />
{ <br />
#if DEBUG <br />
(new SohoProject.SohoDebug()).WriteToDoc("开始进入&lt;将当前用户加入在线列表&gt;...."); <br />
(new SohoProject.SohoDebug()).WriteToDoc("\r\n"); <br />
#endif <br />
<br />
<br />
//开始搜索是否已经存在该用户,如果存在则是改变数据,否则添加新的用户 <br />
string strExpr; <br />
strExpr = "sessionid='" + user.sessionid + "'"; <br />
DataRow[] curUser; <br />
// Use the Select method to find all rows matching the filter. <br />
#if DEBUG <br />
(new SohoProject.SohoDebug()).WriteToDoc("搜索字符串:" + strExpr); <br />
(new SohoProject.SohoDebug()).WriteToDoc("\r\n"); <br />
#endif <br />
<br />
<br />
curUser = _alluser.Select(strExpr); <br />
<br />
#if DEBUG <br />
(new SohoProject.SohoDebug()).WriteToDoc(strExpr); <br />
(new SohoProject.SohoDebug()).WriteToDoc(curUser.Length.ToString()); <br />
#endif <br />
<br />
<br />
if (curUser.Length &gt;0 ) <br />
{ <br />
for(int i = 0; i &lt; curUser.Length; i ++) <br />
{ <br />
curUser[i]["curtime"]=DateTime.Now; <br />
curUser[i]["iswhere"]=user.iswhere; <br />
} <br />
} <br />
else <br />
{ <br />
//直接加入新的数据 <br />
DataRow myRow; <br />
try <br />
{ <br />
myRow = _alluser.NewRow(); <br />
// Then add the new row to the collection. <br />
myRow["name"] = user.name; <br />
myRow["ip"] = user.ip; <br />
myRow["iswhere"] = user.iswhere; <br />
myRow["lasttime"] = user.lasttime; <br />
myRow["curtime"] = DateTime.Now; <br />
myRow["sessionid"] = user.sessionid; <br />
_alluser.Rows.Add(myRow); <br />
} <br />
catch(Exception e) <br />
{ <br />
throw(new Exception(e + "--------------------" + e.ToString())) ; <br />
} <br />
} <br />
_alluser.AcceptChanges(); <br />
return true; <br />
} <br />
<br />
<br />
<br />
//功能说明:判断某用户是否在线,本部分暂时不用 <br />
//返回值：TRUE代表在线，FALSE不在 <br />
public Boolean IsUserOnLine(string name) <br />
{ <br />
//需要先判断用户是否已经在用户列表中了 <br />
//开始搜索是否已经存在该用户,如果存在则是改变数据,否则添加新的用户 <br />
string strExpr; <br />
strExpr = "name ='" + name + "'"; <br />
DataRow[] curUser; <br />
// Use the Select method to find all rows matching the filter. <br />
curUser = _alluser.Select(strExpr); <br />
<br />
if (curUser.Length &gt;0 ) <br />
{ <br />
return true; <br />
} <br />
else <br />
{ <br />
return false; <br />
} <br />
} <br />
<br />
//功能说明：更新用户在线时间 <br />
//返回值：最新的在线用户列表 <br />
public Boolean CheckUserOnLine(string name,string iswhere,string sessionid,string ip) <br />
{ <br />
#if DEBUG <br />
(new SohoProject.SohoDebug()).WriteToDoc("开始进入检查用户方法...."); <br />
(new SohoProject.SohoDebug()).WriteToDoc(""); <br />
#endif <br />
<br />
//需要先判断用户是否已经在用户列表中了 <br />
User newuser=new User(); <br />
newuser.name= name; <br />
newuser.iswhere= iswhere; <br />
newuser.lasttime=newuser.curtime=DateTime.Now; <br />
newuser.sessionid=sessionid; <br />
newuser.ip=ip; <br />
<br />
OnLineUser alluser= new OnLineUser(); <br />
alluser.AddUserToOnLine(newuser); <br />
<br />
<br />
#if DEBUG <br />
(new SohoProject.SohoDebug()).WriteToDoc("离开检查用户方法...."); <br />
#endif <br />
<br />
return true; <br />
} <br />
} <br />
<br />
//定义在线用户类 <br />
public class OnLineUser_old <br />
{ <br />
private static ArrayList _alluser ; //定义用户 <br />
<br />
public ArrayList alluser <br />
{ <br />
get{return _alluser;} <br />
set{_alluser=value;} <br />
} <br />
<br />
public OnLineUser_old() //构造函数 <br />
{ <br />
if(_alluser==null) <br />
{ <br />
_alluser=new ArrayList(); <br />
} <br />
} <br />
<br />
//功能说明：将当前用户加入在线列表 <br />
//如果该用户的数据当前仍然在在线列表中，则暂时先不让该用户登陆,提示用户存在 <br />
public bool AddUserToOnLine(User user) <br />
{ <br />
//需要先判断用户是否已经在用户列表中了 <br />
if(_alluser==null) <br />
{ <br />
_alluser.Add(user); <br />
return (true); <br />
} <br />
else <br />
{ <br />
for ( int i = 0 ; i &lt; _alluser.Count ; i ++) <br />
{ <br />
//循环判断用户是否已经存在 SohoProject.User tempuser = (SohoProject.User)_alluser[i] ; <br />
<br />
if( tempuser.sessionid.Equals(user.sessionid)) <br />
{ <br />
//更新用户在线时间 <br />
tempuser.name=user.name; <br />
tempuser.curtime=DateTime.Now; <br />
tempuser.iswhere=user.iswhere; <br />
tempuser.sessionid=user.sessionid; <br />
tempuser.ip=user.ip; <br />
alluser[i]=tempuser; <br />
return(true); <br />
//return(true); //用户已经存在，则直接退出 } <br />
} <br />
_alluser.Add(user); <br />
return (true); <br />
} <br />
} <br />
<br />
//功能说明:判断某用户是否在线,本部分暂时不用 <br />
//返回值：TRUE代表在线，FALSE不在 <br />
public Boolean IsUserOnLine(string name) <br />
{ <br />
//需要先判断用户是否已经在用户列表中了 <br />
if(_alluser==null) <br />
{ <br />
return (false); <br />
} <br />
else <br />
{ <br />
for ( int i = 0 ; i &lt; _alluser.Count ; i ++) <br />
{ <br />
//循环判断用户是否已经存在 SohoProject.User tempuser = (SohoProject.User)_alluser[i] ; <br />
if(tempuser.name.ToLower().Equals(name.ToLower())) <br />
{ <br />
return(true) ; <br />
} <br />
} <br />
return (false); <br />
} <br />
} <br />
<br />
//功能说明：更新用户在线时间 <br />
//返回值：最新的在线用户列表 <br />
public Boolean CheckUserOnLine(string name,string iswhere,string sessionid,string ip) <br />
{ <br />
//需要先判断用户是否已经在用户列表中了 <br />
if(_alluser!=null) <br />
{ <br />
User newuser=new User(); <br />
newuser.name= name; <br />
newuser.iswhere= iswhere; <br />
newuser.lasttime=newuser.curtime=DateTime.Now; <br />
newuser.sessionid=sessionid; <br />
newuser.ip=ip; <br />
<br />
//OnLineUser alluser= new OnLineUser(); <br />
AddUserToOnLine(newuser); <br />
} <br />
return(false); <br />
} <br />
} <br />
<br />
<br />
<br />
/* <br />
下面开始建立守护线程类： <br />
（注：此处，开始写的时候本来想做成单件模式的，不过由于以前没有做过这个东西，所以反而发生 <br />
了很多问题，最后决定放弃而使用现有的格式) <br />
*/ <br />
public class CheckOnline <br />
{ <br />
const int DELAY_TIMES = 10000 ; //定义执行的时间间隔为5秒 <br />
const int DELAY_SECONDS=60; //将用户掉线时间设置为30秒 <br />
<br />
private Thread thread ; //定义内部线程 <br />
private static bool _flag=false; //定义唯一标志 <br />
<br />
public CheckOnline() <br />
{ <br />
if (!_flag) <br />
{ <br />
_flag= true; <br />
this.thread = new Thread(new ThreadStart(ThreadProc)) ; <br />
thread.Name = "online user" ; <br />
thread.Start() ; <br />
} <br />
} <br />
<br />
<br />
internal void ThreadProc() <br />
{ <br />
while(true) <br />
{ <br />
// SohoProject.OnLineUser temp=new SohoProject.OnLineUser(); //定义一个用户对象 <br />
// for (int i=0 ;i&lt; temp.alluser.Count;i++) <br />
// { <br />
// User tmpuser=(User)temp.alluser[i]; <br />
// //我是将该用户的最新时间加上30秒，然后和当前时间比较，小与当前时间， <br />
// //则表示该用户已经吊线，则删除他的记录 <br />
// if(tmpuser.curtime.AddSeconds(DELAY_SECONDS).CompareTo(DateTime.Now)&lt;0) <br />
// { <br />
// temp.alluser.RemoveAt(i); <br />
// } <br />
// } <br />
<br />
<br />
<br />
SohoProject.OnLineUser temp=new SohoProject.OnLineUser(); //定义一个用户对象 <br />
//开始检查是否有用户过期了 string strExpr; <br />
//tmpuser.curtime.AddSeconds(DELAY_SECONDS).CompareTo(DateTime.Now)&lt;0 <br />
strExpr = "curtime &lt; '" + DateTime.Now.AddSeconds( 0 - DELAY_SECONDS) + "'"; <br />
#if DEBUG <br />
(new SohoProject.SohoDebug()).WriteToDoc(strExpr); <br />
#endif <br />
<br />
DataRow[] curUser; <br />
// Use the Select method to find all rows matching the filter. <br />
curUser = temp.alluser.Select(strExpr); <br />
<br />
if (curUser.Length &gt;0 ) <br />
{ <br />
//删除这些记录 <br />
for(int i = 0; i &lt; curUser.Length; i ++) <br />
{ <br />
curUser[i].Delete(); <br />
} <br />
temp.alluser.AcceptChanges(); <br />
} <br />
Thread.Sleep(DELAY_TIMES) ; <br />
} <br />
} <br />
} <br />
} <br />
</p>
<img src ="http://www.blogjava.net/jvict/aggbug/316572.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-03-25 19:27 <a href="http://www.blogjava.net/jvict/articles/316572.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>免费图表控件MsChart教程系列</title><link>http://www.blogjava.net/jvict/articles/316561.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Thu, 25 Mar 2010 09:43:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/316561.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/316561.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/316561.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/316561.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/316561.html</trackback:ping><description><![CDATA[<p><a href="http://blog.csdn.net/liutengt/archive/2009/02/20/3908396.aspx">原文：http://blog.csdn.net/liutengt/archive/2009/02/20/3908396.aspx</a><br />
<br />
昨天在网上看到了微软发布了.NET 3.5框架下的图表控件，第一时间抓下来看了一下，发觉功能很强劲，基本上能想到的图表都可以使用它绘制出来，给图形统计和报表图形显示提供了很好的解决办法，同时支持Web和WinForm两种方式，不过缺点也比较明显，只能在最新的开发环境中使用，需要.Net 3.5 Sp1以及VS 2008的开发环境。 <br />
下面是下载地址：<br />
&nbsp;</p>
<p>下载免费的微软图表控件 <br />
下载VS 2008对图表控件的工具支持 <br />
下载微软图表控件例程 <br />
下载微软图表控件文档 <br />
访问微软图表控件论坛 <br />
&nbsp; <br />
下了它的示例程序后，运行了一下，非常的强大，可以支持各种各样的图形显示，常见的：点状图、饼图、柱状图、曲线图、面积图、排列图等等，同时也支持3D样式的图表显示，不过我觉得最有用的功能还是支持图形上各个点的属性操作，它可以定义图形上各个点、标签、图形的提示信息（Tooltip）以及超级链接、Javascript动作等，而不是像其它图形类库仅生成一幅图片而已，通过这些，加上微软自己的Ajax框架，可以建立一个可以互动的图形统计报表了。</p>
<p>一。安装<br />
&nbsp;&nbsp;&nbsp;&nbsp; 控件的安装相对比较简单，下载完后，先执行&#8220;MSChart.exe&#8221;程序，它会自动检测你的环境，安装到系统目录中去，如果要在VS 2008环境中直接使用，那么需要安装For Vs2008的插件，MSChart_VisualStudioAddOn.exe，还有一个中文语言包MSChartLP_chs.exe。安装完后，打开Vs2008，在建立项目的时候，你就能在工具栏中看到有一个Chart的控件了，如下图：</p>
<p>&nbsp;</p>
<p>二。使用<br />
&nbsp;&nbsp;&nbsp; 安装好后，建立一个.NET3.5的Web项目，像使用普通控件一样拖放到要使用的Web界面即可。初步研究了一下，整个图形控件主要由以下几个部份组成：</p>
<p>1.Annotations --图形注解集合</p>
<p>2.ChartAreas&nbsp; --图表区域集合</p>
<p>3.Legends&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --图例集合</p>
<p>4.Series　　　 --图表序列集合（即图表数据对象集合）</p>
<p>5.Titles　　　　--图标的标题集合</p>
<p>Annotations注解集合<br />
&nbsp;&nbsp;&nbsp;&nbsp; Annotations是一个对图形的一些注解对象的集合，所谓注解对象，类似于对某个点的详细或者批注的说明，比如，在图片上实现各个节点的关键信息，如下图方框和黄色的小方框：</p>
<p>&nbsp;</p>
<p>&nbsp; 一个图形上可以拥有多个注解对象，可以添加十多种图形样式的注解对象，包括常见的箭头、云朵、矩行、图片等等注解符号，通过各个注解对象的属性，可以方便的设置注解对象的放置位置、呈现的颜色、大小、文字内容样式等常见的属性。</p>
<p>ChartAreas图表区域集合<br />
&nbsp;&nbsp;&nbsp; ChartAreas可以理解为是一个图表的绘图区，例如，你想在一幅图上呈现两个不同属性的内容，一个是用户流量，另一个则是系统资源占用情况，那么你要在一个图形上绘制这两种情况，明显是不合理的，对于这种情况，可以建立两个ChartArea，一个用于呈现用户流量，另一个则用于呈现系统资源的占用情况。</p>
<p>&nbsp;&nbsp;&nbsp; 当然了，图表控件并不限制你添加多少个绘图区域，你可以根据你的需要进行添加。对于每一个绘图区域，你可以设置各自的属性，如：X,Y轴属性、背景等。</p>
<p>&nbsp;&nbsp;&nbsp; 需要注意的是，绘图区域只是一个可以作图的区域范围，它本身并不包含要作图形的各种属性数据。</p>
<p>&nbsp;&nbsp;&nbsp; 多绘图区效果图如下，分为上下两个绘图区域，分别表示不同的绘图数据：</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp; Legends图例集合<br />
&nbsp;&nbsp;&nbsp; Legends是一个图例的集合，即标注图形中各个线条或颜色的含义，同样，一个图片也可以包含多个图例说明，比如像上面说的多个图表区域的方式，则可以建立多个图例，每别说明各个绘图区域的信息，具体的图例配置说明此处就不详细说明了，可以参考一下官网的例子，写得丰富的详细了：）也上一张图例的效果图吧~</p>
<p>&nbsp;</p>
<p>Series图表序列<br />
&nbsp;&nbsp;&nbsp;&nbsp; 图表序列，应该是整个绘图中最关键的内容了，通俗点说，即是实际的绘图数据区域，实际呈现的图形形状，就是由此集合中的每一个图表来构成的，可以往集合里面添加多个图表，每一个图表可以有自己的绘制形状、样式、独立的数据等。</p>
<p>&nbsp;&nbsp;&nbsp; 需要注意的是，每一个图表，你可以指定它的绘制区域（见ChartAreas的说明），让此图表呈现在某个绘图区域，也可以让几个图表在同一个绘图区域叠加，如下图：</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>上面两幅图，分别表示了把图表放在不同的绘制区域和放在同一个绘制区域的情况。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 继续回到ChartAreas章节举的例子，同时要显示用户的流量还要显示系统的占用情况，对于这种时候，应该建立两个Series，一个用于呈现用户的流量，另一个则用于呈现系统的占用情况。它们分别属于各自的绘图区域。</p>
<p>Titles标题合集<br />
&nbsp;&nbsp;&nbsp; 根据字面含义即可以理解，是图表的标题配置，同样可以添加多个标题，以及设置标题的样式及文字、位置等属性。多看一下它的属性即能明白各自的含义。</p>
<p>三。其它属性<br />
&nbsp;&nbsp;&nbsp; 相对来说，我觉得比较有用的属性有三个，分别是：Label、Tooltip以及Url链接。</p>
<p>&nbsp;&nbsp;&nbsp; Label即标签的含义，可以在图片的关键位置进行一些关键数字或文字的描述，如下图：</p>
<p>&nbsp;</p>
<p>像上图：X轴和Y轴的文字便是标签，以及图表曲线中的红点上的文字，也是标签，添加了标签，可以让人更容易的对内容进行理解。</p>
<p>&nbsp;&nbsp;&nbsp; Tooltip即提示的含义，用于在各个关键点，如：标签、图形关键点、标题等当鼠标移动上去的时候，提示用户一些相关的详细或说明信息，例如上图，可以给曲线中的每一个点增加Tooltip的属性，写上需要详细说明的内容，比如：详细的销售明细，那么，在鼠标移动到这个点的时候，会自动弹出提示信息。</p>
<p>&nbsp;&nbsp;&nbsp; Tooltip可以支持简单方式以及自定义的方式，简单方式即像平时Html页面设置的title之类的属性效果，而自定义的方式，则可以实现图形、文本等各种复杂的提示信息显示。详细的方式请参考官方例子的：Interactivity and AJAX/Tooltips以及Interactivity and AJAX/Client Side Scripts下面的相关例子。</p>
<p>&nbsp;&nbsp;&nbsp; Url链接，图表控件中，有一大半的控件都有Url及Tooltip的属性，你可以设置此属性，在鼠标点击的时候，代到其它相应的页面去。</p>
<p>&nbsp;&nbsp; 建议大家看看官方例子中的Interactivity and AJAX部份，很精彩：）</p>
<p>例子：建立一个Cpu信息和内存使用的实时统计表<br />
&nbsp;&nbsp;&nbsp; 下面写一个小例子，建立一个系统的内存实时统计图表，使用到了Ajax的方法，以及Windows Api取得系统内存的方法。</p>
<p>&nbsp;&nbsp;&nbsp; 首先，建立一个Aspx页面，拖动一个图表控件到页面，设置图表控件的属性如下：</p>
<p>&nbsp;&nbsp; 其中，MEMORY_INFO,ComputerInfo是一个定义的结构体及调用Win32 API接口的一个访问类。程序分别取得每一个图表对象，每次加载的时候，都重新取得当前的内存和Cpu信息，再在图表上添加一个点，需要注意的是，一定要设置图表控件的EnableViewState属性为True，否则无法记录状态。</p>
<p>Code<br />
&lt;asp:Chart ID="ChartMemory" runat="server" BackColor="LightSteelBlue" <br />
BackGradientStyle="TopBottom" BackSecondaryColor="White" EnableTheming="False" <br />
EnableViewState="True" Height="363px" Width="415px"&gt;<br />
&lt;Legends&gt;<br />
&lt;asp:Legend Alignment="Center" Docking="Bottom" Name="Legend1" Title="图例"&gt;<br />
&lt;/asp:Legend&gt;<br />
&lt;/Legends&gt;<br />
&lt;Titles&gt;<br />
&lt;asp:Title Font="微软雅黑, 16pt" Name="Title1" Text="系统内存监控图表"&gt;<br />
&lt;/asp:Title&gt;<br />
&lt;/Titles&gt;<br />
&lt;Series&gt;<br />
&lt;asp:Series BorderColor="White" BorderWidth="3" ChartArea="ChartArea1" <br />
ChartType="Spline" Legend="Legend1" Name="已使用物理内存" XValueType="Double" <br />
YValueType="Double"&gt;<br />
&lt;/asp:Series&gt;<br />
&lt;asp:Series BorderWidth="3" ChartArea="ChartArea1" ChartType="Spline" <br />
Legend="Legend1" Name="全部占用内存"&gt;<br />
&lt;/asp:Series&gt;<br />
&lt;asp:Series ChartArea="ChartArea2" ChartType="StackedArea" Legend="Legend1" <br />
Name="CPU"&gt;<br />
&lt;/asp:Series&gt;<br />
&lt;/Series&gt;<br />
&lt;ChartAreas&gt;<br />
&lt;asp:ChartArea BackColor="224, 224, 224" BackGradientStyle="LeftRight" <br />
Name="ChartArea1"&gt;<br />
&lt;/asp:ChartArea&gt;<br />
&lt;asp:ChartArea Name="ChartArea2"&gt;<br />
&lt;/asp:ChartArea&gt;<br />
&lt;/ChartAreas&gt;<br />
&lt;/asp:Chart&gt; <br />
&nbsp;一共建立了两个绘图区，一个用于呈现内存使用情况的在ChartArea1区域，另一个则是呈现Cpu使用情况的，放置在ChartArea2区域了。一共有三个图表，分别表示已使用的物理内存、全部占用的物理内存，以及Cpu使用显示的情况。</p>
<p>添加一个Ajax的计时器以及Ajax的ScriptManager，UpdatePanel，把计时器和图表控件都拖进UpdatePanel里面。设置计时器的间隔时间为一秒钟（1000），双击计时器，写如下代码：</p>
<p>Code<br />
static PerformanceCounter pc = new PerformanceCounter("Processor", "% Processor Time", "_Total"); <br />
protected void Timer1_Tick(object sender, EventArgs e)<br />
{ <br />
MEMORY_INFO MemInfo = new MEMORY_INFO();<br />
ComputerInfo.GlobalMemoryStatus(ref MemInfo);<br />
//UseMemory<br />
Series series = ChartMemory.Series[0];<br />
int xCount = series.Points.Count == 0 ? 0 : series.Points.Count - 1;<br />
double lastXValue = series.Points.Count == 0 ? 1 : series.Points[xCount].XValue + 1;<br />
double lastYValue = (double)(MemInfo.dwTotalPhys-MemInfo.dwAvailPhys)/1024/1024;<br />
series.Points.AddXY(lastXValue, lastYValue);<br />
//Total Memory<br />
series = ChartMemory.Series[1];<br />
lastYValue = (double)(MemInfo.dwTotalVirtual+MemInfo.dwTotalPhys-MemInfo.dwAvailPhys - MemInfo.dwAvailVirtual)/1024/1024;<br />
series.Points.AddXY(lastXValue, lastYValue);</p>
<p>//CPU<br />
series = ChartMemory.Series[2];<br />
lastYValue = (double)pc.NextValue();<br />
series.Points.AddXY(lastXValue, lastYValue);</p>
<p>// Remove points from the left chart side if number of points exceeds 100.<br />
while (this.ChartMemory.Series[0].Points.Count &gt; 80)<br />
{<br />
// Remove series points<br />
foreach (Series s in this.ChartMemory.Series)<br />
{<br />
s.Points.RemoveAt(0);<br />
}<br />
}<br />
// Adjust categorical scale<br />
double axisMinimum = this.ChartMemory.Series[0].Points[0].XValue;<br />
this.ChartMemory.ChartAreas[0].AxisX.Minimum = axisMinimum;<br />
this.ChartMemory.ChartAreas[0].AxisX.Maximum = axisMinimum + 99;<br />
} <br />
&nbsp;&nbsp;&nbsp; 附上取得内存信息的类代码：</p>
<p>Code<br />
/// &lt;summary&gt;<br />
///取得计算机的系统信息<br />
/// &lt;/summary&gt;<br />
public class ComputerInfo<br />
{<br />
/// &lt;summary&gt;<br />
/// 取得Windows的目录<br />
/// &lt;/summary&gt;<br />
/// &lt;param name="WinDir"&gt;&lt;/param&gt;<br />
/// &lt;param name="count"&gt;&lt;/param&gt;<br />
[DllImport("kernel32")]<br />
public static extern void GetWindowsDirectory(StringBuilder WinDir, int count);<br />
/// &lt;summary&gt;<br />
/// 获取系统路径<br />
/// &lt;/summary&gt;<br />
/// &lt;param name="SysDir"&gt;&lt;/param&gt;<br />
/// &lt;param name="count"&gt;&lt;/param&gt;<br />
[DllImport("kernel32")]<br />
public static extern void GetSystemDirectory(StringBuilder SysDir, int count);<br />
/// &lt;summary&gt;<br />
/// 取得CPU信息<br />
/// &lt;/summary&gt;<br />
/// &lt;param name="cpuinfo"&gt;&lt;/param&gt;<br />
[DllImport("kernel32")]<br />
public static extern void GetSystemInfo(ref CPU_INFO cpuinfo);<br />
/// &lt;summary&gt;<br />
/// 取得内存状态<br />
/// &lt;/summary&gt;<br />
/// &lt;param name="meminfo"&gt;&lt;/param&gt;<br />
[DllImport("kernel32")]<br />
public static extern void GlobalMemoryStatus(ref MEMORY_INFO meminfo);<br />
/// &lt;summary&gt;<br />
/// 取得系统时间<br />
/// &lt;/summary&gt;<br />
/// &lt;param name="stinfo"&gt;&lt;/param&gt;<br />
[DllImport("kernel32")]<br />
public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo);</p>
<p>public ComputerInfo()<br />
{<br />
}<br />
}</p>
<p>//定义CPU的信息结构 <br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct CPU_INFO<br />
{<br />
public uint dwOemId;<br />
public uint dwPageSize;<br />
public uint lpMinimumApplicationAddress;<br />
public uint lpMaximumApplicationAddress;<br />
public uint dwActiveProcessorMask;<br />
public uint dwNumberOfProcessors;<br />
public uint dwProcessorType;<br />
public uint dwAllocationGranularity;<br />
public uint dwProcessorLevel;<br />
public uint dwProcessorRevision;<br />
}<br />
//定义内存的信息结构 <br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct MEMORY_INFO<br />
{<br />
public uint dwLength;<br />
public uint dwMemoryLoad;<br />
public uint dwTotalPhys;<br />
public uint dwAvailPhys;<br />
public uint dwTotalPageFile;<br />
public uint dwAvailPageFile;<br />
public uint dwTotalVirtual;<br />
public uint dwAvailVirtual;<br />
}<br />
//定义系统时间的信息结构 <br />
[StructLayout(LayoutKind.Sequential)]<br />
public struct SYSTEMTIME_INFO<br />
{<br />
public ushort wYear;<br />
public ushort wMonth;<br />
public ushort wDayOfWeek;<br />
public ushort wDay;<br />
public ushort wHour;<br />
public ushort wMinute;<br />
public ushort wSecond;<br />
public ushort wMilliseconds;<br />
} <br />
&nbsp;&nbsp;&nbsp;&nbsp; 运行的效果图如下：</p>
<p>&nbsp;</p>
<p><br />
&nbsp;</p>
<p>&nbsp;</p>
<p>下面的例子（在Chart Types-&gt;Line Charts-&gt;3D Line and Curve Charts，图表类型-&gt;曲线图-&gt;3D曲线图下）示范了如何做Line, Spline和 StepLine图表：</p>
<p>&nbsp;</p>
<p>下面的例子(在Chart Types-&gt;Pie and Doughnut Charts，图表类型-&gt;饼图和甜圈图下)示范了各种饼图和3D甜圈图选项：</p>
<p>&nbsp;</p>
<p>下面的例子(在Chart Types-&gt;Advanced Financial Charts，图表类型-&gt;高级财务图表下)示范了一些曲线图表：</p>
<p>&nbsp;</p>
<p>除了上面的例子外，你可以下载微软图表控件文档或在图表控件论坛上询问， 以了解更多详情。</p>
<p>这应该给你的标准ASP.NET功能工具箱又提供了一个非常有用（而且免费）的工具，允许你轻松地将更丰富的视觉效果和数据流程场景添加到你的ASP.NET应用中去。</p>
<p>希望本文对你有所帮助，</p>
<p><br />
本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/liutengt/archive/2009/02/20/3908396.aspx</p>
<img src ="http://www.blogjava.net/jvict/aggbug/316561.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2010-03-25 17:43 <a href="http://www.blogjava.net/jvict/articles/316561.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET(C#)利用QQ的IP数据库QQWry.Dat进行精确IP查询 </title><link>http://www.blogjava.net/jvict/articles/266623.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 20 Apr 2009 14:55:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/266623.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/266623.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/266623.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/266623.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/266623.html</trackback:ping><description><![CDATA[<p>原文: http://blog.csdn.net/kongwei521/archive/2008/03/01/2137506.aspx<br />
其他: http://www.cnblogs.com/llainn/articles/1087667.html<br />
<br />
先下载最新的IP数据库QQWry.Dat 到<a href="http://www.cz88.net/">http://www.cz88.net/</a>这个里的右上角下载最新版本的纯真IP数据库 </p>
<p>添加下面这个类</p>
<p>/******************************************************************<br />
** File Name:IPScanner.cs<br />
** Copyright (c) 2004-2005 PPTech Studio(PPTech.Net)<br />
** Creater:Rexsp(MSN:yubo@x263.net)<br />
** Create Date:2004-12-27 20:10:28<br />
** Modifier:<br />
** Modify Date:<br />
** Description:to scan the ip location from qqwry.dat<br />
** Version: IPScanner 1.0.0<br />
******************************************************************/<br />
using System;<br />
using System.IO;<br />
using System.Collections;<br />
using System.Text;<br />
using System.Text.RegularExpressions;<br />
public class IPScanner<br />
{<br />
&nbsp;&nbsp;&nbsp; #region 私有成员<br />
&nbsp;&nbsp;&nbsp; private string dataPath;<br />
&nbsp;&nbsp;&nbsp; private string ip;<br />
&nbsp;&nbsp;&nbsp; private string country;<br />
&nbsp;&nbsp;&nbsp; private string local;</p>
<p>&nbsp;&nbsp;&nbsp; private long firstStartIp = 0;<br />
&nbsp;&nbsp;&nbsp; private long lastStartIp = 0;<br />
&nbsp;&nbsp;&nbsp; private FileStream objfs = null;<br />
&nbsp;&nbsp;&nbsp; private long startIp = 0;<br />
&nbsp;&nbsp;&nbsp; private long endIp = 0;<br />
&nbsp;&nbsp;&nbsp; private int countryFlag = 0;<br />
&nbsp;&nbsp;&nbsp; private long endIpOff = 0;<br />
&nbsp;&nbsp;&nbsp; private string errMsg = null;<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region 构造函数<br />
&nbsp;&nbsp;&nbsp; public IPScanner()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // TODO: 在此处添加构造函数逻辑<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region 公共属性<br />
&nbsp;&nbsp;&nbsp; public string DataPath<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { dataPath = value; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public string IP<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set { ip = value; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public string Country<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return country; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public string Local<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return local; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public string ErrMsg<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get { return errMsg; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region 搜索匹配数据<br />
&nbsp;&nbsp;&nbsp; private int QQwry()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string pattern = @"(((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Regex objRe = new Regex(pattern);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Match objMa = objRe.Match(ip);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (!objMa.Success)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.errMsg = "IP格式错误";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long ip_Int = this.IpToInt(ip);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int nRet = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ip_Int &gt;= IpToInt("127.0.0.0") &amp;&amp; ip_Int &lt;= IpToInt("127.255.255.255"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.country = "本机内部环回地址";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.local = "";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nRet = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else if ((ip_Int &gt;= IpToInt("0.0.0.0") &amp;&amp; ip_Int &lt;= IpToInt("2.255.255.255")) || (ip_Int &gt;= IpToInt("64.0.0.0") &amp;&amp; ip_Int &lt;= IpToInt("126.255.255.255")) || (ip_Int &gt;= IpToInt("58.0.0.0") &amp;&amp; ip_Int &lt;= IpToInt("60.255.255.255")))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.country = "网络保留地址";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.local = "";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nRet = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs = new FileStream(this.dataPath, FileMode.Open, FileAccess.Read);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //objfs.Seek(0,SeekOrigin.Begin);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Position = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buff = new Byte[8];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Read(buff, 0, 8);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; firstStartIp = buff[0] + buff[1] * 256 + buff[2] * 256 * 256 + buff[3] * 256 * 256 * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lastStartIp = buff[4] * 1 + buff[5] * 256 + buff[6] * 256 * 256 + buff[7] * 256 * 256 * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long recordCount = Convert.ToInt64((lastStartIp - firstStartIp) / 7.0);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (recordCount &lt;= 1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; country = "FileDataError";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long rangE = recordCount;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long rangB = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long recNO = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (rangB &lt; rangE - 1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; recNO = (rangE + rangB) / 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.GetStartIp(recNO);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ip_Int == this.startIp)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rangB = recNO;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ip_Int &gt; this.startIp)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rangB = recNO;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rangE = recNO;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.GetStartIp(rangB);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.GetEndIp();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (this.startIp &lt;= ip_Int &amp;&amp; this.endIp &gt;= ip_Int)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.GetCountry();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.local = this.local.Replace("（我们一定要解放台湾！！！）", "");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nRet = 3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.country = "未知";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.local = "";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return nRet;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region IP地址转换成Int数据<br />
&nbsp;&nbsp;&nbsp; private long IpToInt(string ip)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; char[] dot = new char[] { '.' };<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string[] ipArr = ip.Split(dot);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (ipArr.Length == 3)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ip = ip + ".0";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ipArr = ip.Split(dot);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long ip_Int = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long p1 = long.Parse(ipArr[0]) * 256 * 256 * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long p2 = long.Parse(ipArr[1]) * 256 * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long p3 = long.Parse(ipArr[2]) * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long p4 = long.Parse(ipArr[3]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ip_Int = p1 + p2 + p3 + p4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ip_Int;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region int转换成IP<br />
&nbsp;&nbsp;&nbsp; private string IntToIP(long ip_Int)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long seg1 = (ip_Int &amp; 0xff000000) &gt;&gt; 24;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (seg1 &lt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seg1 += 0x100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long seg2 = (ip_Int &amp; 0x00ff0000) &gt;&gt; 16;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (seg2 &lt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seg2 += 0x100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long seg3 = (ip_Int &amp; 0x0000ff00) &gt;&gt; 8;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (seg3 &lt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seg3 += 0x100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long seg4 = (ip_Int &amp; 0x000000ff);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (seg4 &lt; 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; seg4 += 0x100;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ip = seg1.ToString() + "." + seg2.ToString() + "." + seg3.ToString() + "." + seg4.ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return ip;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region 获取起始IP范围<br />
&nbsp;&nbsp;&nbsp; private long GetStartIp(long recNO)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; long offSet = firstStartIp + recNO * 7;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //objfs.Seek(offSet,SeekOrigin.Begin);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Position = offSet;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buff = new Byte[7];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Read(buff, 0, 7);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; endIpOff = Convert.ToInt64(buff[4].ToString()) + Convert.ToInt64(buff[5].ToString()) * 256 + Convert.ToInt64(buff[6].ToString()) * 256 * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; startIp = Convert.ToInt64(buff[0].ToString()) + Convert.ToInt64(buff[1].ToString()) * 256 + Convert.ToInt64(buff[2].ToString()) * 256 * 256 + Convert.ToInt64(buff[3].ToString()) * 256 * 256 * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return startIp;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region 获取结束IP<br />
&nbsp;&nbsp;&nbsp; private long GetEndIp()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //objfs.Seek(endIpOff,SeekOrigin.Begin);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Position = endIpOff;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buff = new Byte[5];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Read(buff, 0, 5);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.endIp = Convert.ToInt64(buff[0].ToString()) + Convert.ToInt64(buff[1].ToString()) * 256 + Convert.ToInt64(buff[2].ToString()) * 256 * 256 + Convert.ToInt64(buff[3].ToString()) * 256 * 256 * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.countryFlag = buff[4];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.endIp;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region 获取国家/区域偏移量<br />
&nbsp;&nbsp;&nbsp; private string GetCountry()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (this.countryFlag)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 1:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; case 2:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.country = GetFlagStr(this.endIpOff + 4);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.local = (1 == this.countryFlag) ? " " : this.GetFlagStr(this.endIpOff + 8);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; default:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.country = this.GetFlagStr(this.endIpOff + 4);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.local = this.GetFlagStr(objfs.Position);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return " ";<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region 获取国家/区域字符串<br />
&nbsp;&nbsp;&nbsp; private string GetFlagStr(long offSet)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int flag = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buff = new Byte[3];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (1 == 1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //objfs.Seek(offSet,SeekOrigin.Begin);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Position = offSet;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flag = objfs.ReadByte();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flag == 1 || flag == 2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Read(buff, 0, 3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (flag == 2)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.countryFlag = 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.endIpOff = offSet - 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offSet = Convert.ToInt64(buff[0].ToString()) + Convert.ToInt64(buff[1].ToString()) * 256 + Convert.ToInt64(buff[2].ToString()) * 256 * 256;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (offSet &lt; 12)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return " ";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objfs.Position = offSet;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return GetStr();<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region GetStr<br />
&nbsp;&nbsp;&nbsp; private string GetStr()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte lowC = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte upC = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string str = "";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buff = new byte[2];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (1 == 1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lowC = (Byte)objfs.ReadByte();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (lowC == 0)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (lowC &gt; 127)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; upC = (byte)objfs.ReadByte();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buff[0] = lowC;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; buff[1] = upC;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Text.Encoding enc = System.Text.Encoding.GetEncoding("GB2312");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str += enc.GetString(buff);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; str += (char)lowC;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return str;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp; #region 获取IP地址<br />
&nbsp;&nbsp;&nbsp; public string IPLocation()<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.QQwry();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.country + this.local;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; public string IPLocation(string dataPath, string ip)<br />
&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.dataPath = dataPath;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.ip = ip;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.QQwry();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.country + this.local;<br />
&nbsp;&nbsp;&nbsp; }<br />
</p>
<p>&nbsp;&nbsp;&nbsp; #endregion<br />
}<br />
&nbsp;&nbsp;&nbsp;#endregion调用方式：</p>
<p>&nbsp;&nbsp; // 测试地址搜索#region 测试地址搜索&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IPScaner objScan = new IPScaner();&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ip="221.224.205.13";&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="mailto:objScan.DataPath=@%22E:\">objScan.DataPath=@"E:\</a>个人资料\IMTools\QQwryUpdate\QQWry.Dat";&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objScan.IP=ip;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string addre=objScan.IPLocation();&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string err=objScan.ErrMsg; </p>
<p>&nbsp;#endregion</p>
<p>下面是我显示IP时实现的方法</p>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // // 测试地址搜索#region 测试地址搜索 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; IPScanner objScan = new IPScanner();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ip = Request.ServerVariables.Get("REMOTE_ADDR");//自动获取用户IP<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objScan.DataPath = @"D:\BoTi\BoTi\IpSql\QQWry.Dat";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; objScan.IP = ip;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string addre = objScan.IPLocation();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.Label1.Text = addre;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string err = objScan.ErrMsg; </p>
<img src ="http://www.blogjava.net/jvict/aggbug/266623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2009-04-20 22:55 <a href="http://www.blogjava.net/jvict/articles/266623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用GridView编辑更新独立的单元格</title><link>http://www.blogjava.net/jvict/articles/255894.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Fri, 20 Feb 2009 14:13:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/255894.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/255894.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/255894.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/255894.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/255894.html</trackback:ping><description><![CDATA[<p><strong><span style="font-size: 14pt; font-family: 宋体"><span style="font-size: 10.5pt; font-family: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-bidi-font-family: 'Times New Roman'; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><a href="http://www.cnblogs.com/liping13599168/articles/996526.html">原文: http://www.cnblogs.com/liping13599168/articles/996526.html</a><br />
<br />
翻译出处：</span><span lang="EN-US" style="font-size: 10.5pt; font-family: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA; mso-fareast-font-family: 宋体"><a href="http://www.codeproject.com/KB/webforms/EditGridviewCells.aspx">http://www.codeproject.com/KB/webforms/EditGridviewCells.aspx</a><br />
</span><br />
<a title="源代码下载" href="http://files.cnblogs.com/liping13599168/EditGridviewCells_src.zip">源代码下载</a><br />
<br />
介绍</span></strong></p>
<p><span style="font-family: 宋体">在</span>asp.net <span style="font-family: 宋体">中，</span>GridView<span style="font-family: 宋体">允许你通过</span>EditIndex<span style="font-family: 宋体">属性来修改数据的一行，同样也必须进行整行更新。</span></p>
<p><span style="font-family: 宋体">你可能不想对整行进行更新，并且常规更新是利用</span>EditItemTemplate<span style="font-family: 宋体">，在它内部放上编辑状态所要显示的控件；而事实上，你可能只对其中一个单元格感兴趣，比如用上</span>DropDownList<span style="font-family: 宋体">来进行单元格筛选，而常规必须整http://www.cnblogs.com/liping13599168/articles/996526.html<br />
行成编辑状态，那怎样才能直接只让一个独立的单元格成编辑状态呢？那就是本篇文章所要做的事情。</span></p>
<p><strong><span style="font-size: 14pt; font-family: 宋体">编辑独立的单元格<br />
</span></strong></p>
<p><span style="font-family: 宋体"><img height="435" alt="Screenshot - EditGridviewCells1.jpg" src="http://www.codeproject.com/KB/webforms/EditGridviewCells/EditGridviewCells1.jpg" width="495" /><br />
本篇提供的源代码中，</span>GridView<span style="font-family: 宋体">的第一列是</span>CommandName<span style="font-family: 宋体">为</span>SingleClick<span style="font-family: 宋体">的</span>asp:ButtonField<span style="font-family: 宋体">的控件，并且它的</span>Visible<span style="font-family: 宋体">置</span>false.</p>
<span style="font-size: 10.5pt; font-family: 宋体">这控件是为了点击</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">GridView</span><span style="font-size: 10.5pt; font-family: 宋体">的某个单元格而触发点击事件：<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">&lt;</span><span style="color: #000000">Columns</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">asp:ButtonField&nbsp;Text</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">SingleClick</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;CommandName</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">SingleClick</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;Visible</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">False</span><span style="color: #000000">"</span>&nbsp;<span style="color: #000000">/&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">Columns</span><span style="color: #000000">&gt;</span></div>
<br />
<p><span style="font-family: 宋体">而在其他的列中，利用</span>ItemTemplate<span style="font-family: 宋体">，在其中都有一个可见的</span>Label<span style="font-family: 宋体">控件，和不可见的</span>TextBox<span style="font-family: 宋体">或者</span>DropdownList<span style="font-family: 宋体">控件。</span></p>
<span style="font-size: 10.5pt; font-family: 宋体">为了方便起见，我将叫这个</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">Label</span><span style="font-size: 10.5pt; font-family: 宋体">为&#8220;非编辑状态控件&#8221;和</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">TextBox</span><span style="font-size: 10.5pt; font-family: 宋体">或者</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">DropdownList</span><span style="font-size: 10.5pt; font-family: 宋体">的&#8220;编辑状态控件&#8221;。<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">&lt;</span><span style="color: #000000">asp:TemplateField&nbsp;HeaderText</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">Task</span><span style="color: #000000">"</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">ItemTemplate</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">asp:Label&nbsp;ID</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">DescriptionLabel</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;runat</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">server</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Text</span><span style="color: #000000">=</span><span style="color: #000000">'</span><span style="color: #000000">&lt;%#&nbsp;Eval("Description")&nbsp;%&gt;</span><span style="color: #000000">'</span><span style="color: #000000">&gt;&lt;/</span><span style="color: #000000">asp:Label</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">asp:TextBox&nbsp;ID</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">Description</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;runat</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">server</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Text</span><span style="color: #000000">=</span><span style="color: #000000">'</span><span style="color: #000000">&lt;%#&nbsp;Eval("Description")&nbsp;%&gt;</span><span style="color: #000000">'</span><span style="color: #000000">&nbsp;Width</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">175px</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visible</span><span style="color: #000000">=</span><span style="color: #000000">"</span><span style="color: #000000">false</span><span style="color: #000000">"</span><span style="color: #000000">&gt;&lt;/</span><span style="color: #000000">asp:TextBox</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">&lt;/</span><span style="color: #000000">ItemTemplate</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&lt;/</span><span style="color: #000000">asp:TemplateField</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<br />
<p><span style="font-family: 宋体">想法是这样的，刚开始</span>GridView<span style="font-family: 宋体">处于显示状态</span>(<span style="font-family: 宋体">也就是&#8220;非编辑状态&#8221;</span>)<span style="font-family: 宋体">，当某一个单元格被点击的时候，它把</span>Label<span style="font-family: 宋体">控件置不可见而编辑控件</span>TextBox<span style="font-family: 宋体">或者</span>DropdownList<span style="font-family: 宋体">置肯见，而</span>EditItemTemplate<span style="font-family: 宋体">不需要用到。</span></p>
<p><span style="font-family: 宋体">在</span>GridView<span style="font-family: 宋体">的</span>RowDataBound<span style="font-family: 宋体">的事件内对每一行中的每个单元格进行遍历，让其拥有点击触发事件的能力。</span></p>
<span style="font-size: 10.5pt; font-family: 宋体">给每个单元的列索引定义上一些属性参数，如</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">onclick</span><span style="font-size: 10.5pt; font-family: 宋体">，</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">style</span><span style="font-size: 10.5pt; font-family: 宋体">等等。<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">protected</span>&nbsp;<span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;GridView1_RowDataBound(</span><span style="color: #0000ff">object</span><span style="color: #000000">&nbsp;sender,&nbsp;GridViewRowEventArgs&nbsp;e)<br />
<img id="Codehighlighter1_77_938_Open_Image" onclick="this.style.display='none'; Codehighlighter1_77_938_Open_Text.style.display='none'; Codehighlighter1_77_938_Closed_Image.style.display='inline'; Codehighlighter1_77_938_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_77_938_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_77_938_Closed_Text.style.display='none'; Codehighlighter1_77_938_Open_Image.style.display='inline'; Codehighlighter1_77_938_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_77_938_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(e.Row.RowType&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;DataControlRowType.DataRow)<br />
<img id="Codehighlighter1_136_936_Open_Image" onclick="this.style.display='none'; Codehighlighter1_136_936_Open_Text.style.display='none'; Codehighlighter1_136_936_Closed_Image.style.display='inline'; Codehighlighter1_136_936_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_136_936_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_136_936_Closed_Text.style.display='none'; Codehighlighter1_136_936_Open_Image.style.display='inline'; Codehighlighter1_136_936_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_136_936_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;得到第一个单元格的LinkButton控件</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LinkButton&nbsp;_singleClickButton&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(LinkButton)e.Row.Cells[</span><span style="color: #000000">0</span><span style="color: #000000">].Controls[</span><span style="color: #000000">0</span><span style="color: #000000">];<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;得到客户端javascript能够引起LinkButton回发事件的脚本</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;_jsSingle&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;ClientScript.GetPostBackClientHyperlink(<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_singleClickButton,&nbsp;</span><span style="color: #000000">""</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;添加事件到每个可编辑的单元格</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;columnIndex&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;_firstEditCellIndex;&nbsp;columnIndex&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.Row.Cells.Count;&nbsp;columnIndex</span><span style="color: #000000">++</span><span style="color: #000000">)<br />
<img id="Codehighlighter1_552_930_Open_Image" onclick="this.style.display='none'; Codehighlighter1_552_930_Open_Text.style.display='none'; Codehighlighter1_552_930_Closed_Image.style.display='inline'; Codehighlighter1_552_930_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_552_930_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_552_930_Closed_Text.style.display='none'; Codehighlighter1_552_930_Open_Image.style.display='inline'; Codehighlighter1_552_930_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_552_930_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;插入列索引参数</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;js&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;_jsSingle.Insert(_jsSingle.Length&nbsp;</span><span style="color: #000000">-</span>&nbsp;<span style="color: #000000">2</span><span style="color: #000000">,&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;columnIndex.ToString());<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;给单元格添加javscript的onclick属性</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.Row.Cells[columnIndex].Attributes[</span><span style="color: #000000">"</span><span style="color: #000000">onclick</span><span style="color: #000000">"</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;js;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;给单元格添加鼠标样式</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.Row.Cells[columnIndex].Attributes[</span><span style="color: #000000">"</span><span style="color: #000000">style</span><span style="color: #000000">"</span><span style="color: #000000">]&nbsp;</span><span style="color: #000000">+=</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">cursor:pointer;cursor:hand;</span><span style="color: #000000">"</span><span style="color: #000000">;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<br />
<span style="font-size: 10.5pt; font-family: 宋体">在</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">GridView</span><span style="font-size: 10.5pt; font-family: 宋体">的</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">RowCommand</span><span style="font-size: 10.5pt; font-family: 宋体">事件，命令参数和事件参数被重新检索，它带给我们选择某一单元格所在的行索引和列索引。</span><br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;_rowIndex&nbsp;</span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">int</span><span style="color: #000000">.Parse(e.CommandArgument.ToString());<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;_columnIndex&nbsp;</span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">int</span><span style="color: #000000">.Parse(Request.Form[</span><span style="color: #000000">"</span><span style="color: #000000">__EVENTARGUMENT</span><span style="color: #000000">"</span><span style="color: #000000">]);</span></div>
<br />
<p><span style="font-family: 宋体">当所选单元格的行索引和列索引已知的情况下，单元格能够很轻松地对编辑状态进行控件的可见转换。</span></p>
<span style="font-size: 10.5pt; font-family: 宋体">被选中的单元格也必须移除点击的事件。<br />
<br />
</span></span></span></span>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #008000">//</span><span style="color: #008000">得到选中单元格的显示控件使它不可见</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">Control&nbsp;_displayControl&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;_gridView.Rows[_rowIndex].Cells[_columnIndex].Controls[</span><span style="color: #000000">1</span><span style="color: #000000">];<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />_displayControl.Visible&nbsp;</span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">false</span><span style="color: #000000">;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;得到选中单元格的编辑控件是它可见</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">Control&nbsp;_editControl&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;_gridView.Rows[_rowIndex].Cells[_columnIndex].Controls[</span><span style="color: #000000">3</span><span style="color: #000000">];<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />_editControl.Visible&nbsp;</span><span style="color: #000000">=</span>&nbsp;<span style="color: #0000ff">true</span><span style="color: #000000">;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;移除选中单元格的点击属性</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;_gridView.Rows[_rowIndex].Cells[_columnIndex].Attributes.Clear();<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<br />
<span style="font-size: 10.5pt; font-family: 宋体">还有一些代码是在事件回发之后在编辑控件上置焦点。如果编辑控件是一个</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">DropDownList</span><span style="font-size: 10.5pt; font-family: 宋体">那么它的</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">SelectedValue</span><span style="font-size: 10.5pt; font-family: 宋体">属性被置上显示控件的值，如果编辑控件是一个</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">TextBox</span><span style="font-size: 10.5pt; font-family: 宋体">那么它的文本被选上将准备进行编辑。</span><br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #008000">//</span><span style="color: #008000">&nbsp;在选中的编辑控件上置焦点</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">ClientScript.RegisterStartupScript(GetType(),&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">SetFocus</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">&lt;script&gt;document.getElementById(</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">'</span><span style="color: #000000">"&nbsp;+&nbsp;_editControl.ClientID&nbsp;+&nbsp;"</span><span style="color: #000000">'</span><span style="color: #000000">).focus();</span><span style="color: #000000">&lt;/</span><span style="color: #000000">script</span><span style="color: #000000">&gt;</span><span style="color: #000000">"</span><span style="color: #000000">);</span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;如果编辑控件是dropdownlist置selectedValue为显示控件的值</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(_editControl&nbsp;</span><span style="color: #0000ff">is</span><span style="color: #000000">&nbsp;DropDownList&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;_displayControl&nbsp;</span><span style="color: #0000ff">is</span><span style="color: #000000">&nbsp;Label)<br />
<img id="Codehighlighter1_276_368_Open_Image" onclick="this.style.display='none'; Codehighlighter1_276_368_Open_Text.style.display='none'; Codehighlighter1_276_368_Closed_Image.style.display='inline'; Codehighlighter1_276_368_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_276_368_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_276_368_Closed_Text.style.display='none'; Codehighlighter1_276_368_Open_Image.style.display='inline'; Codehighlighter1_276_368_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_276_368_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;((DropDownList)_editControl).SelectedValue&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(Label)_displayControl).Text;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;如果编辑控件是TextBox文本选上准备进行编辑</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(_editControl&nbsp;</span><span style="color: #0000ff">is</span><span style="color: #000000">&nbsp;TextBox)<br />
<img id="Codehighlighter1_427_500_Open_Image" onclick="this.style.display='none'; Codehighlighter1_427_500_Open_Text.style.display='none'; Codehighlighter1_427_500_Closed_Image.style.display='inline'; Codehighlighter1_427_500_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_427_500_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_427_500_Closed_Text.style.display='none'; Codehighlighter1_427_500_Open_Image.style.display='inline'; Codehighlighter1_427_500_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_427_500_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;((TextBox)_editControl).Attributes.Add(</span><span style="color: #000000">"</span><span style="color: #000000">onfocus</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">this.select()</span><span style="color: #000000">"</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<br />
<p><span style="font-family: 宋体">在这个例子中，</span>GridView<span style="font-family: 宋体">的</span>RowUpdating<span style="font-family: 宋体">先检查每个单元格，看是否处于编辑模式下。如果处于编辑模式的单元格被找到，那么数据更新将被执行。</span></p>
<span style="font-size: 10.5pt; font-family: 宋体">在第一个例子中，一些样本数据绑定到一个</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">DataTable</span><span style="font-size: 10.5pt; font-family: 宋体">中存储在</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">Session</span><span style="font-size: 10.5pt; font-family: 宋体">里<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #008000">//</span><span style="color: #008000">&nbsp;遍历GridView的列索引查找处于编辑模式下的单元格</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;i&nbsp;</span><span style="color: #000000">=</span>&nbsp;<span style="color: #000000">1</span><span style="color: #000000">;&nbsp;i&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;_gridView.Columns.Count;&nbsp;i</span><span style="color: #000000">++</span><span style="color: #000000">)<br />
<img id="Codehighlighter1_81_260_Open_Image" onclick="this.style.display='none'; Codehighlighter1_81_260_Open_Text.style.display='none'; Codehighlighter1_81_260_Closed_Image.style.display='inline'; Codehighlighter1_81_260_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_81_260_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_81_260_Closed_Text.style.display='none'; Codehighlighter1_81_260_Open_Image.style.display='inline'; Codehighlighter1_81_260_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_81_260_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;Get&nbsp;the&nbsp;editing&nbsp;control&nbsp;for&nbsp;the&nbsp;cell</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;Control&nbsp;_editControl&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;_gridView.Rows[e.RowIndex].Cells[i].Controls[</span><span style="color: #000000">3</span><span style="color: #000000">];<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(_editControl.Visible)<br />
<img id="Codehighlighter1_237_258_Open_Image" onclick="this.style.display='none'; Codehighlighter1_237_258_Open_Text.style.display='none'; Codehighlighter1_237_258_Closed_Image.style.display='inline'; Codehighlighter1_237_258_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_237_258_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_237_258_Closed_Text.style.display='none'; Codehighlighter1_237_258_Open_Image.style.display='inline'; Codehighlighter1_237_258_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_237_258_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;更新数据</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<br />
<span style="font-size: 10.5pt; font-family: 宋体">为了确保</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">RowUpdating</span><span style="font-size: 10.5pt; font-family: 宋体">在</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">GridView</span><span style="font-size: 10.5pt; font-family: 宋体">在未选中行状态下也能够被调用，例如我在编辑模式下编辑文本框点击了&#8220;</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">Enter</span><span style="font-size: 10.5pt; font-family: 宋体">&#8221;键，页面整页回发，这样确保任何数据的改变被保存。<br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">this</span><span style="color: #000000">.GridView1.SelectedIndex&nbsp;</span><span style="color: #000000">&gt;</span>&nbsp;<span style="color: #000000">-</span><span style="color: #000000">1</span><span style="color: #000000">)<br />
<img id="Codehighlighter1_39_108_Open_Image" onclick="this.style.display='none'; Codehighlighter1_39_108_Open_Text.style.display='none'; Codehighlighter1_39_108_Closed_Image.style.display='inline'; Codehighlighter1_39_108_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_39_108_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_39_108_Closed_Text.style.display='none'; Codehighlighter1_39_108_Open_Image.style.display='inline'; Codehighlighter1_39_108_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_39_108_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">this</span><span style="color: #000000">.GridView1.UpdateRow(</span><span style="color: #0000ff">this</span><span style="color: #000000">.GridView1.SelectedIndex,&nbsp;</span><span style="color: #0000ff">false</span><span style="color: #000000">);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<br />
<p><span style="font-family: 宋体">注册回发或回调数据以进行验证</span></p>
<p><span style="font-family: 宋体">创建在</span>RowDataBound<span style="font-family: 宋体">的自定义事件必须在页面中被注册。</span></p>
<span style="font-size: 10.5pt; font-family: 'Times New Roman'">ClientScriptManager.RegisterForEventValuedation</span><span style="font-size: 10.5pt; font-family: 宋体">通过重载</span><span style="font-size: 10.5pt; font-family: 'Times New Roman'">Render</span><span style="font-size: 10.5pt; font-family: 宋体">方法来调用。</span></span></span><br />
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">protected</span>&nbsp;<span style="color: #0000ff">override</span>&nbsp;<span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Render(HtmlTextWriter&nbsp;writer)<br />
<img id="Codehighlighter1_54_491_Open_Image" onclick="this.style.display='none'; Codehighlighter1_54_491_Open_Text.style.display='none'; Codehighlighter1_54_491_Closed_Image.style.display='inline'; Codehighlighter1_54_491_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="Codehighlighter1_54_491_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_54_491_Closed_Text.style.display='none'; Codehighlighter1_54_491_Open_Image.style.display='inline'; Codehighlighter1_54_491_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="Codehighlighter1_54_491_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">foreach</span><span style="color: #000000">&nbsp;(GridViewRow&nbsp;r&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;GridView1.Rows)<br />
<img id="Codehighlighter1_106_460_Open_Image" onclick="this.style.display='none'; Codehighlighter1_106_460_Open_Text.style.display='none'; Codehighlighter1_106_460_Closed_Image.style.display='inline'; Codehighlighter1_106_460_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_106_460_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_106_460_Closed_Text.style.display='none'; Codehighlighter1_106_460_Open_Image.style.display='inline'; Codehighlighter1_106_460_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_106_460_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(r.RowType&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;DataControlRowType.DataRow)<br />
<img id="Codehighlighter1_169_454_Open_Image" onclick="this.style.display='none'; Codehighlighter1_169_454_Open_Text.style.display='none'; Codehighlighter1_169_454_Closed_Image.style.display='inline'; Codehighlighter1_169_454_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_169_454_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_169_454_Closed_Text.style.display='none'; Codehighlighter1_169_454_Open_Image.style.display='inline'; Codehighlighter1_169_454_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_169_454_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">for</span><span style="color: #000000">&nbsp;(</span><span style="color: #0000ff">int</span><span style="color: #000000">&nbsp;columnIndex&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;_firstEditCellIndex;&nbsp;columnIndex&nbsp;</span><span style="color: #000000">&lt;</span><span style="color: #000000">&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r.Cells.Count;&nbsp;columnIndex</span><span style="color: #000000">++</span><span style="color: #000000">)<br />
<img id="Codehighlighter1_300_444_Open_Image" onclick="this.style.display='none'; Codehighlighter1_300_444_Open_Text.style.display='none'; Codehighlighter1_300_444_Closed_Image.style.display='inline'; Codehighlighter1_300_444_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="Codehighlighter1_300_444_Closed_Image" style="display: none" onclick="this.style.display='none'; Codehighlighter1_300_444_Closed_Text.style.display='none'; Codehighlighter1_300_444_Open_Image.style.display='inline'; Codehighlighter1_300_444_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_300_444_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Page.ClientScript.RegisterForEventValidation(<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r.UniqueID&nbsp;</span><span style="color: #000000">+</span>&nbsp;<span style="color: #000000">"</span><span style="color: #000000">$ctl00</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;columnIndex.ToString());<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">base</span><span style="color: #000000">.Render(writer);<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<img src ="http://www.blogjava.net/jvict/aggbug/255894.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2009-02-20 22:13 <a href="http://www.blogjava.net/jvict/articles/255894.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>引用 asp.net session的应用</title><link>http://www.blogjava.net/jvict/articles/251985.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 19 Jan 2009 15:55:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/251985.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/251985.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/251985.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/251985.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/251985.html</trackback:ping><description><![CDATA[<p><em><a href="http://blog.163.com/hanjz/blog/static/41028272200861051732741/">原文: http://blog.163.com/hanjz/blog/static/41028272200861051732741/</a><br />
<br />
引用</em></p>
<blockquote><a href="http://blog.163.com/lingfang_yan/" target="_blank">lingfang_yan</a> 的 <a href="http://blog.163.com/lingfang_yan/blog/static/374706862007926113498" target="_blank">asp.net session的应用</a><br />
<br />
<br />
<p style="text-indent: 21.25pt; line-height: 15.7pt">Session又称为会话状态，是Web系统中最常用的状态，用于维护和当前浏览器实例相关的一些信息。举个例子来说，我们可以把已登录用户的用户名放在Session中，这样就能通过判断Session中的某个Key来判断用户是否登录，如果登录的话用户名又是多少。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">我们知 道，Session对于每一个客户端（或者说浏览器实例）是&#8220;人手一份&#8221;，用户首次与Web服务器建立连接的时候，服务器会给用户分发一个 SessionID作为标识。SessionID是一个由24个字符组成的随机字符串。用户每次提交页面，浏览器都会把这个SessionID包含在 HTTP头中提交给Web服务器，这样Web服务器就能区分当前请求页面的是哪一个客户端。那么，ASP.NET 2.0提供了哪些存储SessionID的模式呢：</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cookie（默认）。如果客户端禁止了Cookie的使用，Session也将失效。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL。Cookie是否开启不影响Session使用，缺点是不能再使用绝对链接了。</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">前面说了SessionID可以存储在客户端的Cookie或者URL中，那么Session真正的内容存储在哪里呢？ASP.NET 2.0对于Session内容的存储也提供了多种模式。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InProc（默认）。Session存储在IIS进程中（Web服务器内存）。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StateServer。Session存储在独立的Windows服务进程中（可以不是Web服务器）。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlServer。Session存储在SqlServer数据库的表中（SqlServer服务器）。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">虽然 InProc模式的Session直接存储在Web服务器IIS进程中，速度比较快，但是每次重新启动IIS都会导致Session丢失。利用后两种模式，我们就完全可以把Session从Web服务器中独立出来，从而减轻Web服务器的压力，同时减少Session丢失的概率。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">因此，SessionID存储在客户端（可以是Cookie或者URL），其他都存储在服务端（可以是IIS进程、独立的Windows服务进程或者SQL Server数据库中）。</p>
<h3>12.3.2 &nbsp;Session的使用</h3>
<p style="text-indent: 21pt; line-height: 15.7pt">让我们先来实践一下如何使用Session，进而回答第二个问题：Session存储的类型限制。Session不需要进行任何配置就可以使用（默认是InProc模式并且依赖Cookie）。首先，在页面上建立两个按钮。</p>
<p>&lt;asp:Button ID="btn_WriteSession" runat="server"Text="写入Session" /&gt;</p>
<p>&lt;asp:Button ID="btn_ReadSession" runat="server" Text="读取Session" /&gt;</p>
<p style="text-indent: 21pt; line-height: 15.7pt">在btn_WriteSession按钮的Click事件处理方法中，写入两个Session，一个是简单的字符串，另外一个是自定义的类。</p>
<p style="line-height: 13pt">protected void btn_WriteSession_Click(object sender, EventArgs e)</p>
<p style="line-height: 13pt">{</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; Session["SimpleString"] = "编程快乐";</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; MyUser user = new MyUser();</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; user.sUserName = "小朱";</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; user.iAage = 24;</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; Session["CustomClass"] = user;</p>
<p style="line-height: 13pt">}</p>
<p style="text-indent: 21pt; line-height: 15.7pt">Session的使用非常简单，直接对某个Key的Session进行赋值即可。自定义类MyUser如下：</p>
<p>class MyUser</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp; public string sUserName;</p>
<p>&nbsp;&nbsp;&nbsp; public int iAage;</p>
<p>&nbsp;&nbsp;&nbsp; public override string ToString()</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Format("姓名：{0}，年龄：{1}", sUserName, iAage);</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p style="text-indent: 21pt; line-height: 15.7pt">在这里，我们覆写了ToString()方法直接返回实例的一些信息。然后，双击btn_ReadSession按钮来实现从Session中读取数据的代码：</p>
<p>protected void btn_ReadSession_Click(object sender, EventArgs e)</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp; if (Session["SimpleString"]==null)</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write("读取简单字符串失败&lt;br/&gt;");</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string s=Session["SimpleString"].ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write(s + "&lt;br/&gt;");</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; if (Session["CustomClass"]==null)</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write("读取简单自定义类失败&lt;br/&gt;");</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyUser user=Session["CustomClass"] as MyUser;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write(user.ToString()+"&lt;br/&gt;");</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p style="text-indent: 21pt; line-height: 15.7pt">在每次读取Session的值以前请务必先判断Session是否为空，否则很有可能出现&#8220;未将对象引用设置到对象的实例&#8221;的异常。我们看到，从Session 中读出的数据都是object类型的，我们需要进行类型转化后才能使用。打开页面，先单击写入Session按钮，再单击读取Session按钮，页面输出如&nbsp;&nbsp;&nbsp; 图12-1所示。</p>
<p align="center"><img height="118" alt="文本框:图12-1  从Session中读取字符串和自定义类" hspace="12" src="http://book.csdn.net/BookFiles/406/img/image002.gif" width="242" align="left" /></p>
<h3>12.3.3 &nbsp;把Session存储在独立的进程中</h3>
<p style="text-indent: 21.25pt; line-height: 15.7pt">由此看来，Session能存储任意对象，是这样吗？现在得出这个结论还太早了一点，因为我们并没有实践过StateServer和SqlServer模式的Session。要把Session存储在Windows服务进程中需要进行以下几个步骤。</p>
<p>n&nbsp; 第1步是打开状态服务。依次打开&#8220;控制面板&#8221;&#8594;&#8220;管理工具&#8221;&#8594;&#8220;服务&#8221;命令，找到ASP.NET状态服务一项，右键单击服务选择启动，如图12-2所示。</p>
<p align="center"><img height="132" alt="" src="http://book.csdn.net/BookFiles/406/img/image003.jpg" width="416" /></p>
<p align="center">图12-2 &nbsp;启动ASP.NET状态服务</p>
<p>n&nbsp; 如果你正式决定使用状态服务存储Session前，别忘记修改服务为自启动（在操作系统重启后服务能自己启动）以免忘记启动服务而造成网站Session不能使用，如图12-3所示，双击服务把服务的启动类型设置为自动。</p>
<p style="margin-top: 12.55pt" align="center"><img height="327" alt="" src="http://book.csdn.net/BookFiles/406/img/image004.jpg" width="303" /></p>
<p style="line-height: 220%" align="center">图12-3 &nbsp;修改服务启动类型为自动</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">服务正常启动后可以观察任务管理器的进程页，其中的aspnet_state.exe进程就是状态服务进程，如图12-4所示。</p>
<p style="margin-top: 12.55pt" align="center"><img height="47" alt="" src="http://book.csdn.net/BookFiles/406/img/image005.jpg" width="302" /></p>
<p style="line-height: 220%" align="center">图12-4 &nbsp;观察任务管理器的进程页</p>
<p>n&nbsp; 第2步，在system.web节点中加入：</p>
<p>&lt;sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" </p>
<p>stateNetworkTimeout="20"&gt;&lt;/sessionState&gt;</p>
<p>n&nbsp; stateConnectionString表示状态服务器的通信地址（IP：服务端口号）。由于我们现在在本机进行测试，这里设置成本机地址127.0.0.1。状态服务默认的监听端口为42422。当然，您也可以通过修改注册表来修改状态服务的端口号。</p>
<p>n&nbsp; 1．在运行中输入regedit启动注册表编辑器。</p>
<p>n&nbsp; 2．依次打开HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters节点，双击Port选项，如图12-5所示。</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">选择基数为十进制，然后输入一个端口号即可。stateNetworkTimeout属性表示从状态服务器请求Session数据最长的时间，默认为10秒，如果网络连接不是很好，请把这个数字适当设置得大一点。</p>
<p>n&nbsp; 第3步打开页面，单击&#8220;写入Session&#8221;按钮，系统会报错，如图12-6所示。</p>
<p align="center"><img height="120" alt="" src="http://book.csdn.net/BookFiles/406/img/image006.jpg" width="215" />&nbsp;&nbsp;&nbsp; <img height="122" alt="" src="http://book.csdn.net/BookFiles/406/img/image007.jpg" width="351" /></p>
<p style="text-align: justify" align="center">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图12-5 &nbsp;修改状态服务端口号&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图12-6 &nbsp;向StateServer默认的Session中写入自定义类出错</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">提示已经说得很清楚了，只有把对象标注为可序列化后才能在服务中进行存储。什么是序列化呢？序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中，先将对象的公共字段和私有字段以及类的名称转换为字节流，然后再把字节流写入数据流。在随后对对象进行反序列化时，将创建出与原对象完全相同的副本。要使一个类可序列化，最简单的方法是使用 Serializable 属性对它进行标记。</p>
<p style="line-height: 13pt">[Serializable]</p>
<p style="line-height: 13pt">class MyUser</p>
<p style="line-height: 13pt">{</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; public string sUserName;</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; public int iAage;</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; public override string ToString()</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; {</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Format("姓名：{0}，年龄：{1}", sUserName, iAage);</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; }</p>
<p style="line-height: 13pt">}</p>
<p>n&nbsp; 第4步现在重新打开页面进行测试，得到的结果和使用InProc模式是一样的。</p>
<h3>12.3.4 &nbsp;把Session存储在数据库中</h3>
<p style="text-indent: 21.25pt; line-height: 15.7pt">要把Session存储在SqlServer中，基本上也是这么几个步骤。</p>
<p>n&nbsp; 1．在命令行窗口输入cmd并在命令行中运行如下命令。</p>
<p>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe -S .\SqlExpress -E &#8211;ssadd</p>
<p style="text-indent: 21pt; line-height: 15.7pt">其中 C:\Windows用你自己Windows的目录代替，v2.0.50727用你安装的2.0框架的版本号代替。-S指定SqlServer服务器地址，-E表示采用信任连接，-ssadd表示为SqlServer服务器添加状态服务的支持。操作结束后，你可以使用IDE的服务器资源管理器连接 SqlExpress数据库，可以看到多了一个ASPState数据库，但是奇怪的是数据库中没有任何表却有很多存储过程，如图12-7所示。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">其实，所有Session的数据都存放在了tempdb数据库内，如图12-8所示。</p>
<p align="center"><img height="240" alt="" src="http://book.csdn.net/BookFiles/406/img/image008.jpg" width="209" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img height="127" alt="" src="http://book.csdn.net/BookFiles/406/img/image009.jpg" width="190" /></p>
<p style="text-align: justify" align="center">&nbsp;&nbsp;&nbsp; 图12-7 &nbsp;使用服务器资源管理器浏览ASPState数据库&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图12-8 &nbsp;存放Session数据的tempdb数据库</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">其实，aspnet_regsql.exe有一个-sstype参数可以用来指定Session的内容和操作的存储过程存放的表。由于篇幅关系，在这里就不详细介绍了，读者可以使用aspnet_regsql.exe/?来浏览程序详细的使用方式。</p>
<p>n&nbsp; 2．打开Web.config文件，修改前面建立的sessionState节点。</p>
<p>&lt;sessionState mode="SQLServer" sqlConnectionString="server=(local)\SQLEXPRESS; </p>
<p>Trusted_Connection=True" sqlCommandTimeout="60"&gt;&lt;/sessionState&gt;</p>
<p style="text-indent: 21pt; line-height: 15.7pt">为sqlConnectionString 属性指定以前一直用的连接字符串，唯一不同的是不需要再指定数据表的名字了。sqlCommandTimeout属性表示允许执行Sql命令最长的时间，默认为30秒，可以根据自己的需要适当调整这个数字。最后，重新打开页面进行测试，得到的结果和使用InProc模式是一样的（同样你需要确保在自定义类前标注了[Serializable]），不过我们能感到速度有些慢了，毕竟数据是从数据库中进行读取或保存的，而且在使用前还需要经过序列化和反序列化操作。</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">因此Session能存储的类型为： 对于InProc模式是一切类型，而对于StateServer和SqlServer模式是一切可以序列化的类型。</p>
<h3>12.3.5 &nbsp;Session的使用范围与大小限制</h3>
<p style="text-indent: 21pt; line-height: 15.7pt">那么， 会话状态使用的范围和大小限制又是怎么样的呢？我们可以分析一下图12-8，系统使用两个表来存储Session的状态。其中有一个 ASPStateTempApplication表，用来存储Session所在的应用程序，一定程度上反映了Session是不能跨应用程序的。举例来说，我们在计算机上建立了两个网站，同时都使用Session[&#8220;UserName&#8221;]来保存登录的用户名，一个网站的用户登录后，另一个网站直接访问 Session[&#8220;UserName&#8221;]是取不到任何值的。那么，Session是否可以跨用户呢？通过前面的分析我们知道，肯定是不行的， Session通过SessionID来区分用户，一般来说SessionID是不可能出现重复的现象，也就是说Session一般是不会&#8220;串号&#8221;的。既然页面每次提交的时候都会附加上当前用户的SessionID，那么Session应该是可以跨页面的，也就是说一个网站中所有的页面都使用同一份 Session。你可以自己来做个试验，请读者打开刚才那个页面，然后按Ctrl+N组合键再打开第二个同样的页面，单击第一个页面中的&#8220;写入 Session&#8221;按钮，单击第二个页面中的&#8220;读取Session&#8221;按钮，可以发现Session的值被正确读出了。第三个问题的答案有了。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Session状态使用的范围：使用同一个客户端（浏览器实例）访问同一个应用程序的所有页面。</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">我们再来做一个试验，看看Session的容量有多大，在测试以前请修改Web.config，把Session设置为StateServer模式。然后，把写入Session的代码修改成如下（别忘记using System.Data.SqlCient）：</p>
<p>DataSet ds = new DataSet();</p>
<p>using (SqlConnection conn = new SqlConnection(@"server=(local)\SQLEXPRESS;database=Forum; </p>
<p>Trusted_Connection=True"))</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp; SqlDataAdapter da = new SqlDataAdapter("select <sub>*</sub> from tbUser;select <sub>*</sub> from tbBoard;</p>
<p>&nbsp;&nbsp;&nbsp; select <sub>*</sub> from tbTopic;", conn);</p>
<p>&nbsp;&nbsp;&nbsp; da.Fill(ds);</p>
<p>}</p>
<p>ArrayList al = new ArrayList();</p>
<p>for(int i = 0;i&lt;10000000;i++)</p>
<p>&nbsp;&nbsp;&nbsp; al.Add(ds);</p>
<p>Session["LargeData"] = al;</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">我们把包含三个表的DataSet重复加入ArrayList中1000万次。由于这些表几乎每个表只有几条记录，这样可以模拟大数据量的情况。启动页面，单击&#8220;写入Session&#8221;按钮后可以发现，Windows服务进程一下子占用了多达70MB的内存，如图12-9所示。</p>
<p align="center"><img height="78" alt="" src="http://book.csdn.net/BookFiles/406/img/image010.jpg" width="301" /></p>
<p align="center">图12-9 &nbsp;把大量数据存放到Session中</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">Session 对于网站和用户是独立的，试想一下，如果服务器上有两个网站，每个网站的在线人数是100人，那么占用内存就要14G。是不是很恐怖的数字？因此，虽然 Session的大小没有限制，但是我们千万不能滥用Session。笔者推荐你在Session中存储少于100K的数据。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你使用InProc模式的Session，存储过多的数据会导致IIS进程被回收，引发Session不断丢失。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你使用StateServer存储Session，那么数据在存入Session以前需要进行序列化，序列化会消耗大量的CPU资源。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你使用SqlServer模式的Session，数据不但要序列化而且还是存储在磁盘上，更不适合存储大量数据。</p>
<h3>12.3.6 &nbsp;Session的生命周期</h3>
<p style="text-indent: 21.25pt; line-height: 15.7pt">在了解了Session中存储的数据无大小限制后，我们可能要更多地关心Session的生命周期了。我们已经知道，Session是在用户第一次访问网站的时候创建的，那么Session是什么时候销毁的呢？Session使用一种平滑超时的技术来控制何时销毁Session。默认情况下，Session 的超时时间（Timeout）是20分钟，用户保持连续20分钟不访问网站，则Session被收回，如果在这20分钟内用户又访问了一次页面，那么20 分钟就重新计时了，也就是说，这个超时是连续不访问的超时时间，而不是第一次访问后20分钟必过时。这个超时时间同样也可以通过调整Web.config 文件进行修改：</p>
<p>&lt;sessionState timeout="30"&gt;&lt;/sessionState&gt;</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">当然你也可以在程序中进行设置：</p>
<p>Session.Timeout = "30";</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">一旦Session超时，Session中的数据将被回收，如果再使用Session系统，将给你分配一个新的SessionID。本节一开始我们就介绍了可以在URL中存储SessionID，现在请你配置Web.config文件，设置Session超时时间为1分钟，SessionID在URl中存放。打开页面后单击&#8220;写入Session&#8221;按钮，过1分钟再次单击按钮并观察SessionID是否变化。</p>
<p>&lt;sessionState timeout="1" cookieless="true"&gt;&lt;/sessionState&gt;</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">如图12-10所示，SessionID的确发生了变化。</p>
<p align="center"><img height="29" alt="" src="http://book.csdn.net/BookFiles/406/img/image011.jpg" width="416" /></p>
<p align="center"><img height="26" alt="" src="http://book.csdn.net/BookFiles/406/img/image012.jpg" width="416" /></p>
<p align="center">图12-10 &nbsp;超时后SessionID发生变化</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">不过，你可别太相信Session的Timeout属性，如果你把它设置为24小时，则很难相信24小时之后用户的Session还在。Session是否存在，不仅仅依赖于Timeout属性，以下的情况都可能引起Session丢失（所谓丢失就是在超时以前原来的Session无效）。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bin目录中的文件被改写。asp.net有一种机制，为了保证dll重新编译之后，系统正常运行，它会重新启动一次网站进程，这时就会导致 Session丢失，所以如果有access数据库位于bin目录，或者有其他文件被系统改写，就会导致Session丢失。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SessionID丢失或者无效。如果你在URL中存储SessionID，但是使用了绝对地址重定向网站导致URL中的SessionID丢失，那么原来的Session将失效。如果你在Cookie中存储SessionID，那么客户端禁用Cookie或者Cookie达到了IE中Cookie数量的限制（每个域20个），那么Session将无效。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果使用InProc的Session，那么IIS重启将会丢失Session。同理，如果使用StateServer的Session，服务器重新启动Session也会丢失。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">一般来说，如果在IIS中存储Session而且Session的Timeout设置得比较长，再加上Session中存储大量的数据，非常容易发生Session丢失的问题。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">最后， Session的安全性怎么样呢？我们知道，Session中只有SessionID是存储在客户端的，并且在页面每次提交的过程中加入HTTP头发送给服务器。SessionID只是一个识别符，没有任何内容，真正的内容是存储在服务器上的。总的来说安全性还是可以的，不过笔者建议你不要使用 cookieless和SqlServer模式的Session。把SessionID暴露在URL中，把内容存储在数据库中可能会发生攻击隐患。</p>
<h3>12.3.7 &nbsp;遍历与销毁Session</h3>
<p style="text-indent: 21pt; line-height: 15.7pt">Session虽然很方便，但是要用好Session还需要自己不断实践，根据自己网站的特点灵活使用各种模式的Session。关于使用程序访问Session，笔者还想补充两点。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何遍历当前的Session集合。</p>
<p style="line-height: 15.3pt">System.Collections.IEnumerator SessionEnum = Session.Keys.GetEnumerator();</p>
<p style="line-height: 15.3pt">while (SessionEnum.MoveNext())</p>
<p style="line-height: 15.3pt">{</p>
<p style="line-height: 15.3pt">&nbsp;&nbsp;&nbsp; Response.Write(Session[SessionEnum.Current.ToString()].ToString() + "&lt;br/&gt;");</p>
<p style="line-height: 15.3pt">}</p>
<p style="text-indent: 21pt; line-height: 15.7pt">对于我们这个例子，输出和图12-1一样。如果你仅仅为了监视Session，也可以通过trace来获得详细信息。在Web.config的system.Web节点中添加：</p>
<p style="line-height: 14.3pt">&lt;trace enabled="true"&nbsp; pageOutput="true"/&gt;</p>
<p style="text-indent: 21pt; line-height: 15.7pt">打开页面后单击&#8220;写入Session&#8221;按钮，页面显示如图12-11所示。</p>
<p style="margin-top: 15.7pt" align="center"><img height="57" alt="" src="http://book.csdn.net/BookFiles/406/img/image013.jpg" width="553" /></p>
<p align="center">图12-11 &nbsp;使用trace观察会话状态</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何立刻让Session失效。比如用户退出系统后，Session中保存的所有数据全部失效，可以使用以下代码来让Session失效。</p>
<p>Session.Abandon();</p>
<h3 style="line-height: 320%">12.3.8&nbsp; Session的常见问题与总结</h3>
<p style="text-indent: 21pt; line-height: 16.3pt">Session的基本知识就介绍到这里，现在再回头看第一节中的几个问题，你是否都能回答了呢？为了强化大家的概念，笔者就三种模式的Session进行了一个比较（假设都使用Cookie来存储SessionID）。</p>
<p>表12.1&nbsp; 三种模式的Session比较</p>
<div align="center">
<table style="border-right: medium none; border-top: medium none; margin-left: -37.4pt; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="107"><br />
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">InProc</p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 130.15pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="174">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">StateServer</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 135.95pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="181">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">SQLServer</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">存储物理位置</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">IIS进程（内存）</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 130.15pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="174">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">Windows服务进程（内存）</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 135.95pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="181">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">SQLServer数据库（磁盘）</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">存储类型限制</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">无限制</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 130.15pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="174">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">可以序列化的类型</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 135.95pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="181">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">可以序列化的类型</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">存储大小限制</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 383pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="511" colspan="3">
            <p style="border-right: medium none; border-top: medium none; margin-bottom: 1pt; border-left: medium none; line-height: 12.5pt; border-bottom: medium none">无限制</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">使用范围</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 383pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="511" colspan="3">
            <p style="border-right: medium none; border-top: medium none; margin-bottom: 1pt; border-left: medium none; line-height: 12.5pt; border-bottom: medium none">当前请求上下文，对于每个用户独立</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">生命周期</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 383pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="511" colspan="3">
            <p style="margin-bottom: 1pt; line-height: 12.5pt; text-align: center" align="center">第一次访问网站的时候创建Session超时后销毁</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">优点</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">性能比较高</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 266.1pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="355" colspan="2">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">Session不依赖Web服务器，不容易丢失</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">缺点</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: 1pt solid" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">容易丢失</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 130.15pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="174">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">序列化与反序列化消耗CPU资源</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 135.95pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="181">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">序列化与反序列化消耗CPU资源，从磁盘读取Session比较慢</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">使用原则</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 383pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="511" colspan="3">
            <p style="margin-bottom: 1pt; line-height: 12.5pt; text-align: center" align="center">不要存放大量数据</p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="text-indent: 21pt; line-height: 15.9pt">在使用Session的过程中你可能还会遇到很多奇怪的问题，结束本节之前笔者列出了几条常见的FAQ，供大家参考：</p>
<p style="line-height: 15.9pt">&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为什么每次请求的SessionID都不相同？</p>
<p style="line-height: 15.9pt">n&nbsp; 可能是没有在Session里面保存任何信息引起的，即程序中任何地方都没有使用Session。只有在Session中保存了内容后，Session才会和浏览器进行关联，此时的SessionID将不会再变化。</p>
<p style="line-height: 15.9pt">&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为什么当我设置cookieless为true后，在重定向的时候会丢失Session？</p>
<p style="line-height: 15.9pt">n&nbsp; 当使用cookieless时，你必须使用相对路径替换程序中的绝对路径，如果使用绝对路径，ASP.NET将无法在URL中保存SessionID。</p>
<p style="line-height: 15.9pt">&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有办法知道应用程序的Session在运行时占用了多少内存吗？</p>
<p style="line-height: 15.9pt">n&nbsp; 没有办法，你可以通过观察IIS进程（InProc模式）或者aspnet_state进程（StateServer模式）大致估计。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有没有可能知道整个网站使用Session的用户列表？</p>
<p>n&nbsp; 对于InProc模式和StateServer模式很难，对于SqlServer模式你可以查询存储Session的表进行尝试。</p>
<p style="line-height: 15.9pt">&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当页面中设了frameset，发现在每个frame中显示页面的SessionID在第一次请求时都不相同，为什么？</p>
<p style="line-height: 15.9pt">n&nbsp; 原因是你的frameset是放在一个HTML页面上而不是ASPX页面。在一般情况下，如果frameset是aspx页面，当你请求页面时，它首先将请求发送到Web服务器，此时已经获得了SessionID，接着浏览器会分别请求Frame中的其他页面，这样所有页面的SessionID就是一样的，就是FrameSet页面的SessionID。然而如果你使用HTML页面做FrameSet页面，第一个请求将是HTML页面，当该页面从服务器上返回时并没有任何Session产生，接着浏览器会请求Frame里面的页面，这样，这些页面都会产生自己的SessionID，所以在这种情况下就可能出现这种问题。当你重新刷新页面时，SessionID就会一样，并且是最后一个请求页面的SessionID。</p>
</blockquote>
<img src ="http://www.blogjava.net/jvict/aggbug/251985.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2009-01-19 23:55 <a href="http://www.blogjava.net/jvict/articles/251985.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET会话（Session）保存模式</title><link>http://www.blogjava.net/jvict/articles/250421.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Wed, 07 Jan 2009 14:42:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/250421.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/250421.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/250421.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/250421.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/250421.html</trackback:ping><description><![CDATA[<p>引发 Session 丢失的几种原因<br />
动过手写代码的人都知道，Session 丢失是比较常见的事。以下是本人这几年所遇到的，能够引发 Session 丢失的原因，不敢说是百分百，丢失概率还是特别高的。错&#8230;，简直可以说是&#8220;相&#8230;当&#8230;&#8221;高哇 ^_^"</p>
<p>1、&nbsp;&nbsp;&nbsp; 存放 Session 的电脑重启（废话，若这样都不丢，你神仙啊）</p>
<p>2、&nbsp;&nbsp;&nbsp; InProc 模式：aspnet_wp.exe 或 w3wp.exe 在&#8220;任务管理器&#8221;中或其它情况下导致其进程被终止运行。</p>
<p>3、&nbsp;&nbsp;&nbsp; InProc 模式：修改 .cs 文件后，编译了两次（只编译一次，有时不会丢失）</p>
<p>4、&nbsp;&nbsp;&nbsp; InProc 模式：修改了 Web.config</p>
<p>5、&nbsp;&nbsp;&nbsp; InProc 模式，Windows 2003 环境：应用程序池回收、停止后重启</p>
<p>6、&nbsp;&nbsp;&nbsp; InProc 模式：服务器上 bin 目录里的 .dll 文件被更新</p>
<p>以上列举的都是 InProc 模式下，容易引发解析 ASP.NET 应用程序重置的原因。是不是觉得很窝火？之前我也有这种感觉，慢慢就习惯啦，再后来就干脆不用这种模式了。于是乎，就有了使用下列两种模式的尝试，现写出来与大家一起分享。</p>
<p>二、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使用 StateServer 保存 Session</p>
<p>StateServer 模式的实质是，把Session 存放在一个单独的进程里，此进程独立于 aspnet_wp.exe 或 w3wp.exe 。启用此服务后，在&#8220;任务管理器&#8221;中可以看到一个名为 aspnet_state.exe 的进程，下面开始说明一下设置的具体步骤：</p>
<p>&nbsp;</p>
<p>1、&nbsp;&nbsp;&nbsp; 修改注册表（关键步骤，如下图）</p>
<p>运行 regedit &#8594; 打开注册表 &#8594; 找到HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters 节点 &#8594; 将 AllowRemoteConnection 的键值设置成&#8220;1&#8221;（1 为允许，0 代表禁止）&#8594; 设置 Port (端口号)</p>
<p>注意事项：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a)、若ASP.NET State Service 正在运行，修改注册表内容后，则需要重新启动该服务</p>
<p>b)、注意端口号的键值是以十六进制储存的，可以使用十进制进行修改，42424 是默认的端口</p>
<p>c)、AllowRemoteConnection 的键值设置成&#8220;1&#8221;后，意味着允许远程电脑的连接，也就是说只要知道你的服务端口，就可享用你的ASP.NET State Service，即把 Session 存放在你的电脑进程内，因此请大家慎用；键值为&#8220;0&#8221;时，仅有stateConnectionString 为&#8220;tcpip=localhost: 42424&#8221;与&#8220;tcpip=127.0.0.1:42424&#8221;的情况，方可使用ASP.NET State Service<br />
2、&nbsp;&nbsp;&nbsp; 开启 ASP.NET State Service（如下图）</p>
<p>右键点击&#8220;我的电脑&#8221;&#8594; 管理 &#8594; 服务与应用程序 &#8594; 服务 &#8594; 双击&#8220;ASP.NET State Service&#8221; &#8594; 启动（可设为&#8220;自动&#8221;）</p>
<p>说明：只要安装了 .Net Framework v1.0/v1.1 ，都拥有此服务<br />
、&nbsp;&nbsp;&nbsp; 更改 Web.config</p>
<p>打开 Web.config &#8594; 找到 &lt;sessionState&gt; 节点内容</p>
<p>&lt;sessionState </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mode="InProc"</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stateConnectionString="tcpip=127.0.0.1:42424"</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sqlConnectionString="data source=127.0.0.1;Trusted_Connection=yes"</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cookieless="false" </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; timeout="20" /&gt;</p>
<p>&nbsp;</p>
<p>&#8594; 将其改为以下内容</p>
<p>&lt;sessionState mode="StateServer"&nbsp; stateConnectionString="tcpip=192.168.0.2:42424" timeout="20" /&gt;</p>
<p>注意事项：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a)、设成StateServer 后，必须要有对应的stateConnectionString </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b)、注意 IP 地址（可以是远程计算机 IP、计算机名称、域名）与端口号，端口号需与ASP.NET State Service 的服务端口一致</p>
<p>&nbsp;</p>
<p>三、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 将 Session 放入 SQLServer 保存</p>
<p>SQLServer 模式就是，把Session 存放在 SQL Server 数据库里（注意不是 Oracle ，动动脚趾都能猜到原因啦），下面开始说明一下设置的具体步骤：</p>
<p>&nbsp;</p>
<p>1、&nbsp;&nbsp;&nbsp; 启动相关的数据库服务（如图）</p>
<p>运行SQL Server 服务管理器 &#8594; 启动 SQL Server （最好设为开机自动运行） &#8594; 启动 SQL Server Agent 服务（最好设为开机自动运行）</p>
<p>注意事项：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a)、注意启动顺序，也可通过下列方式设置： 右键点击&#8220;我的电脑&#8221;&#8594; 管理 &#8594; 服务与应用程序 &#8594; 服务 &#8594; 找到&#8220;MSSQLSERVER&#8221;与&#8220;SQLSERVERAGENT&#8221; &#8594; 启动并设置启动类型为&#8220;自动&#8221;</p>
<p>b)、SQL Server Agent在此处的作用是清除数据库中已过期的 Session</p>
<p>2、&nbsp;&nbsp;&nbsp; 建立存放 Session 的 DataBase</p>
<p>运行&#8220;SQL 查询分析器&#8221;&#8594; 使用&#8220;sa&#8221;或是拥有&#8220;master&#8221;的 db_owner 权限的用户登录数据库 &#8594; 打开查询文件 C:\WINNT\Microsoft.NET\Framework\v1.1.4322\InstallSqlState.sql （存放在 Windows 系统目录的 .Net 安装目录下可找到） &#8594; 直接运行该 sql 脚本 &#8594; 刷新数据库即可看到名为 ASPState 的 DataBase</p>
<p>3、&nbsp;&nbsp;&nbsp; 建立连接数据库 ASPState 的用户，并为此用户授权（此步骤可跳过）</p>
<p>进行此步的原因是：一是不想在 Web.config 中出现 sa 的密码；二是 tempdb 在数据库启动后仅保留 sa 一个帐号的使用权限，其余帐号的权限统统被清除，但保存 Session又需要用到此 DataBase；</p>
<p>&nbsp;</p>
<p>A)、运行 SQL Server 的企业管理器 &#8594; 展开数据库的安全性 &#8594; 右击&#8220;登录&#8221; &#8594; 新建&#8220;登录&#8221; &#8594; 输入&#8220;名称&#8221; &#8594; 选择 &#8220;SQL Server 身份验证&#8221; &#8594; 输入&#8220;密码&#8221; &#8594; 指定&#8220;数据库&#8221; &#8594; 点击&#8220;数据库访问&#8221; &#8594; 勾选 &#8220;ASPState&#8221; &#8594; 选中&#8220;db_owner&#8221;角色 &#8594; 点击&#8220;确定&#8221; &#8594; 再一次输入&#8220;密码&#8221; &#8594; 点击&#8220;确定&#8221; 后即可建立 ASPState 的用户（此处建立名为&#8220;SessionStateUser&#8221;，密码为&#8220;123456&#8221;的测试用户）</p>
<p>B)、运行 SQL Server 的企业管理器 &#8594; 展开&#8220;管理&#8221; &#8594; 展开&#8220;SQL Server 代理&#8221; &#8594; 右击&#8220;作业&#8221; &#8594; 点击&#8220;新建作业&#8221; &#8594; 输入 &#8220;名称&#8221;（此例为 GrantSessionUser ） &#8594; 点击标签 &#8220;步骤&#8221; &#8594; 新建 &#8594; 输入 &#8220;步骤名&#8221;（此例为 Grant01） &#8594; 选择数据库&#8220;tempdb&#8221; &#8594; 编写 SQL 脚本&#8220;exec sp_adduser 'SessionStateUser', 'SessionUser' ,'db_owner' &#8221;&#8594; 确定 &#8594; 点击标签 &#8220;调度&#8221; &#8594; 新建 &#8594; 输入 &#8220;名称&#8221;（此例为 Start01 ）&#8594; 选择类型&#8220;SQL Server 代理启动时自动启动&#8221; &#8594; 确定 &#8594; 最后点击&#8220;确定&#8221;新增完毕</p>
<p>C）、也可运行以下脚本一次性搞定以上 A、B 两个步骤</p>
<p>/******脚本开始******/</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --新建数据库帐号 SessionStateUser ，默认登录 ASPState</p>
<p>EXEC sp_addlogin 'SessionStateUser', '123456', 'ASPState'</p>
<p>&nbsp;</p>
<p>use ASPState&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --切换 DataBase</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --将 SessionStateUser 授予 db_owner 的权限</p>
<p>exec sp_adduser 'SessionStateUser', 'SessionUser' ,'db_owner'</p>
<p>&nbsp;</p>
<p>use master&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --切换 DataBase</p>
<p>&nbsp;</p>
<p>BEGIN TRANSACTION&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /******声明变量******/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; DECLARE @JobID BINARY(16)&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; DECLARE @ReturnCode INT&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; SELECT @ReturnCode = 0&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; -- 若没有，则添加作业的分类</p>
<p>&nbsp;&nbsp;&nbsp; IF (SELECT COUNT(*) FROM msdb.dbo.syscategories WHERE name = N'[Uncategorized (Local)]') &lt; 1 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; EXECUTE msdb.dbo.sp_add_category @name = N'[Uncategorized (Local)]'</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; -- 新建作业</p>
<p>&nbsp;&nbsp;&nbsp; EXECUTE @ReturnCode = msdb.dbo.sp_add_job&nbsp;&nbsp; --调用存储过程 sp_add_job</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @job_id = @JobID OUTPUT,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --将返回的 JobID，赋值给变量</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @job_name = N'GrantSessionUser',&nbsp;&nbsp; --作业名称</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @owner_login_name = NULL,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --默认为当前用户所有</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @description = null, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @category_name = N'[Uncategorized (Local)]',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --作业分类归属</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @enabled = 1,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --是否启用</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @notify_level_email = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @notify_level_page = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @notify_level_netsend = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @notify_level_eventlog = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @delete_level= 0</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; IF (@@ERROR &lt;&gt; 0 OR @ReturnCode &lt;&gt; 0) GOTO QuitWithRollback --出错则回滚</p>
<p>&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; -- 新建步骤</p>
<p>&nbsp;&nbsp;&nbsp; EXECUTE @ReturnCode = msdb.dbo.sp_add_jobstep --调用存储过程 sp_add_jobstep</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @job_id = @JobID,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --传入刚刚新建的 JobID</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @step_id = 1, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @step_name = N'Grant01',&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --步骤名称</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @command = N'exec sp_adduser ''SessionStateUser'', ''SessionUser'' ,''db_owner''', </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --需要执行的 SQL 脚本（注意用两个连续的单引号表示 SQL 中的单引号）</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @database_name = N'tempdb', --执行上述 SQL 所用的 DataBase</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @server = N'', </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @database_user_name = N'', </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @subsystem = N'TSQL',&nbsp;&nbsp;&nbsp; --执行类型为&#8220;Transact-SQL 脚本&#8221;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @cmdexec_success_code = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @flags = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @retry_attempts = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @retry_interval = 1, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @output_file_name = N'', </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @on_success_step_id = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @on_success_action = 1, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @on_fail_step_id = 0, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @on_fail_action = 2</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; IF (@@ERROR &lt;&gt; 0 OR @ReturnCode &lt;&gt; 0) GOTO QuitWithRollback </p>
<p>&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; -- 新建调度</p>
<p>&nbsp;&nbsp;&nbsp; EXECUTE @ReturnCode = msdb.dbo.sp_add_jobschedule </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @job_id = @JobID, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @name = N'Start01',&nbsp;&nbsp; --调度名称</p>
<p><br />
该文章转载自德仔工作室：http://www.dezai.cn/article_show.asp?ArticleID=20551</p>
<p>@enabled = 1, </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; @freq_type = 64&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&#8220;64&#8221;表示 当 SQLServerAgent 服务启动时运行</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; IF (@@ERROR &lt;&gt; 0 OR @ReturnCode &lt;&gt; 0) GOTO QuitWithRollback </p>
<p>&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; -- 将新建的作业添加到本地数据库</p>
<p>&nbsp;&nbsp;&nbsp; EXECUTE @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @JobID, @server_name = N'(local)' </p>
<p>&nbsp;&nbsp;&nbsp; IF (@@ERROR &lt;&gt; 0 OR @ReturnCode &lt;&gt; 0) GOTO QuitWithRollback </p>
<p>&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; COMMIT TRANSACTION&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp; GOTO&nbsp;&nbsp; EndSave&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>QuitWithRollback:</p>
<p>&nbsp;&nbsp;&nbsp; IF (@@TRANCOUNT &gt; 0) ROLLBACK TRANSACTION </p>
<p>EndSave:</p>
<p>/******脚本结束******/</p>
<p>&nbsp;</p>
<p>4、&nbsp;&nbsp;&nbsp; 设置 Web.config 内容</p>
<p>打开 Web.config &#8594; 找到 &lt;sessionState&gt; 节点内容 &#8594; 修改为以下内容即可：</p>
<p>&lt;sessionState mode="SQLServer"&nbsp; sqlConnectionString ="data source=192.168.0.2; user id= SessionStateUser; password=123456" timeout="20" /&gt;</p>
<p>注意事项：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a)、sqlConnectionString 中不能出现 initial catalog 选项</p>
<p>b)、SQL Server Agent在此处的作用是清除数据库中已过期的 Session</p>
<p>c）、你若跳过了第三步，则 user id 需要用 sa 进行登录</p>
<p>d）、若sqlConnectionString 为 &#8220;data source=127.0.0.1;Trusted_Connection=yes&#8221;，则使用本地计算机ASPNET（Windows 2000 系统帐户）或 Network Service（Windows 2003 系统帐户）的身份登录数据库。要是数据库不允许上述用户登录，则报错；同样，即使上述帐户能成功登录，也要分配其 tempdb 的权限，理由是 Session 是保存在 tempdb 中的，若没有该 DataBase 的存取权限是行不滴</p>
<p><br />
该文章转载自德仔工作室：http://www.dezai.cn/Article_Show.asp?ArticleID=20551&amp;ArticlePage=2</p>
<img src ="http://www.blogjava.net/jvict/aggbug/250421.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2009-01-07 22:42 <a href="http://www.blogjava.net/jvict/articles/250421.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ASP.NET SESSION丢失问题解决方案</title><link>http://www.blogjava.net/jvict/articles/250417.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Wed, 07 Jan 2009 14:09:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/250417.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/250417.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/250417.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/250417.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/250417.html</trackback:ping><description><![CDATA[<p><span style="font-weight: bold; font-size: 20px; color: black; background-color: transparent">Session丢失的解决办法小结</span> <br />
<br />
<span style="font-weight: bold; font-size: 20px; color: black; background-color: transparent">SessionState 的Timeout)，其主要原因有三种</span> <br />
<br />
一：有些杀病毒软件会去扫描您的Web.Config文件，那时<a class="SearchKeyword">Session</a>肯定掉，这是微软的说法。 <br />
二:程序内部里有让<a class="SearchKeyword">Session</a>掉失的代码，及服务器内存不足产生的。 <br />
三：程序有框架页面和跨域情况。 <br />
<br />
第一种解决办法是:使杀病毒软件屏蔽扫描Web.Config文件(程序运行时自己也不要去编辑它) <br />
第二种是检查代码有无<a class="SearchKeyword">Session</a>.Abandon()之类的。 <br />
第三种是在Window服务中将ASP.NET State Service 启动。 <br />
<br />
<br />
一：在第一个页面置了<a class="SearchKeyword">SESSION</a>，然后REDIRECT去第二个页面。解决方法是在REDIRECT中设置endResponse为FALSE。 <br />
<br />
二： ASP.NET中使用了ACCESS数据库，而且数据库是放在bin目录中的。解决方法是不要放会更新的文件在BIN目录中。 <br />
<br />
参考：<a class="Url" href="http://www.dotnet247.com/247reference/msgs/58/290316.aspx">http://www.dotnet247.com/247reference/msgs/58/290316.aspx</a> <br />
<br />
<br />
<span style="font-weight: bold; font-size: 20px; color: black; background-color: transparent">Asp.net 默认配置下，Session莫名丢失的原因及解决办法</span> <br />
&nbsp;&nbsp; <br />
<br />
正常操作情况下<a class="SearchKeyword">Session</a>会无故丢失。因为程序是在不停的被操作，排除<a class="SearchKeyword">Session</a>超时的可能。另外，<a class="SearchKeyword">Session</a>超时时间被设定成60分钟，不会这么快就超时的。 <br />
<br />
这次到CSDN上搜了一下帖子，发现好多人在讨论这个问题，然后我又google了一下，发现微软网站上也有类似的内容。 <br />
<br />
现在我就把原因和解决办法写出来。 <br />
<br />
<br />
<span style="font-weight: bold; font-size: 20px; color: black; background-color: transparent">原因：</span> <br />
<br />
由于Asp.net程序是默认配置，所以Web.Config文件中关于<a class="SearchKeyword">Session</a>的设定如下： <br />
&lt;<a class="SearchKeyword">session</a>State mode='InProc' stateConnectionString='tcpip=127.0.0.1:42424' sqlConnectionString='data source=127.0.0.1;Trusted_Connection=yes' cookieless='true' timeout='60'/&gt; <br />
<br />
我们会发现<a class="SearchKeyword">session</a>State标签中有个属性mode，它可以有3种取值：InProc、StateServer?SQLServer（大小写敏感） 。默认情况下是InProc，也就是将<a class="SearchKeyword">Session</a>保存在进程内（IIS5是aspnet_wp.exe，而IIS6是W3wp.exe），这个进程不稳定，在某些事件发生时，进程会重起，所以造成了存储在该进程内的<a class="SearchKeyword">Session丢失</a>。 <br />
<br />
<span style="font-weight: bold; font-size: 20px; color: black; background-color: transparent">解决办法：</span> <br />
<br />
前面说到的<a class="SearchKeyword">session</a>State标签中mode属性可以有三个取值，除了InProc之外，还可以为StateServer、SQLServer。这两种存<a class="SearchKeyword">Session</a>的方法都是进程外的，所以当aspnet_wp.exe重起的时候，不会影响到<a class="SearchKeyword">Session</a>。 <br />
<br />
现在请将mode设定为StateServer。StateServer是本机的一个服务，可以在系统服务里看到服务名为ASP.NET State Service的服务，默认情况是不启动的。当我们设定mode为StateServer之后，请手工将该服务启动。 <br />
<br />
这样，我们就能利用本机的StateService来存储<a class="SearchKeyword">Session</a>了，除非电脑重启或者StateService崩掉，否则<a class="SearchKeyword">Session</a>是不会丢的（因<a class="SearchKeyword">Session</a>超时被丢弃是正常的）。 <br />
<br />
除此之外，我们还可以将<a class="SearchKeyword">Session</a>通过其他电脑的StateService来保存。具体的修改是这样的。同样还在<a class="SearchKeyword">session</a>State标签中，有个stateConnectionString='tcpip=127.0.0.1:42424'属性，其中有个ip地址，默认为本机（127.0.0.1），你可以将其改成你所知的运行了StateService服务的电脑IP，这样就可以实现位于不同电脑上的Asp.net程序互通<a class="SearchKeyword">Session</a>了。 <br />
<br />
如果你有更高的要求，需要在服务期重启时<a class="SearchKeyword">Session</a>也不丢失，可以考虑将mode设定成SQLServer，同样需要修改sqlConnectionString属性。关于使用SQLServer保存<a class="SearchKeyword">Session</a>的操作，请访问这里。 <br />
<br />
在使用StateServer或者SQLServer存储<a class="SearchKeyword">Session</a>时，所有需要保存到<a class="SearchKeyword">Session</a>的对象除了基本数据类型（默认的数据类型，如int、string等）外，都必须序列化。只需将[Serializable]标签放到要序列化的类前就可以了。</p>
<p><strong>理解Session State模式<br />
<br />
<span style="text-decoration: underline">存储位置</span></strong></p>
<p>InProc：session在服务器中以活动对象方式存储（aspnet_wp.exe）<br />
<br />
StateServer: session被序列化并保存在单独的aspnet_state.exe的内存中。StateServer能够运行在另一台服务器上<br />
<br />
SQLServer: session被序列化并保存在SQL Server中<br />
<br />
性能：<br />
<font color="#ff0000">InProc：最快</font>，但是session数据越多，web服务器上消耗的内存也越多，它可能影响性能。<br />
<br />
StateServer：当存储基本类型（如string,integer等）数据时，在同一个测试环境中它比<font color="#ff0000">InProc慢15%</font>。如果你存储大量对象，序列化和反序列化可能影响到性能</p>
<p>SQLServer：当存储基本类型（如string,integer等）数据时，在同一个测试环境中它比<font color="#ff0000">InProc慢25%</font>。它也有与StateServer一样的序列化性能问题。</p>
<img src ="http://www.blogjava.net/jvict/aggbug/250417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2009-01-07 22:09 <a href="http://www.blogjava.net/jvict/articles/250417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2008切换设计视图假死的解决办法</title><link>http://www.blogjava.net/jvict/articles/249714.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sun, 04 Jan 2009 04:13:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249714.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249714.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249714.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249714.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249714.html</trackback:ping><description><![CDATA[<p>原文: http://blog.csdn.net/cngkqy/archive/2008/12/24/3597082.aspx<br />
<br />
原来有一段时间经常碰到这个问题，搞的我疯狂的重做系统，被折腾的不清，最后也没有搞清楚到底是什么因为造成的，只是重做了好几次系统之后，自己莫名其妙的又不出了。今天在网上搜资料无意中又搜到了这个问题的贴子，发现这里边提到的腾讯通、Office2008插件原因我都弄过，可能就是这两个当中当中的一个原因，或是混合原因。赶紧先把帖子转进来，防止以后再走弯路。。。</p>
<p>&nbsp;</p>
<p>VS2008刚刚出来的时候，安装过一次，一段时间没用，后来打开WebApplication的时候，一点设计，VS2008IDE就死掉。后来就删除了。最近打算用VS2008，就又开始安装了。<br />
第一次安装：用的是电脑公司克隆版9，克隆好系统就安装VS2008，启动空WebApplication点设计就死。<br />
到网上查找，有不少提出这个问题的，但是没有解决方案。<br />
又下载了一个YLMF克隆版，克隆好就安装VS2008，测试没有问题。可把需要的软件安装好之后，点设计又死。<br />
下面是痛苦的历程，多次的克隆，安装，不过功夫不负有心人，确定了问题的原因，安装了RTX2006（腾讯通）之后，导致了VS2008 WEB设计假死。<br />
<br />
罪魁祸首确定之后，就是查找RTX2006安装程序做了什么。又经过了几个小时的折腾，最后确定原因出在注册表中的一个键值上面。<br />
<br />
<strong>原键值</strong>：<br />
<font face="Verdana">[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{F5078F18-C551-11D3-89B9-0000F81FE221}\5.0\0\win32]<br />
@="C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE11\\msxml5.dll"<br />
<br />
<strong>安装RTX2006后</strong>：<br />
<font face="Verdana">[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\{F5078F18-C551-11D3-89B9-0000F81FE221}\5.0\0\win32]<br />
@="C:\\Program Files\\Common Files\\Tencent\\MSXML5.dll"</font><br />
<br />
如果这个键值不为C:\\Program Files\\Common Files\\Microsoft Shared\\OFFICE11\\msxml5.dll，启动VS2008 的WEB设计界面就假死。<br />
不知道没有安装OFFICE2003的机器上安装VS2008这个键值是什么？</font></p>
<p><font face="Verdana"></font>&nbsp;</p>
<p><font face="Verdana"></font>&nbsp;</p>
<p><font face="Verdana">原贴地址：<a href="http://www.cnblogs.com/onecool/archive/2008/09/11/1242950.html">http://www.cnblogs.com/onecool/archive/2008/09/11/1242950.html</a></font></p>
<p>--------------------------------------------------------------------------------------------------------</p>
<p><font style="background-color: #c7edcc">家里电脑上安装了vs2008,之前没装其他版本的vs,最近在使用webform窗体的时候发现不能切换到设计视图了,一点切换vs就卡死,网上搜索了一下 除了重装vs2008 没有发现其他解决办法,发现vs2005也有这个问题,vs2005的解决办法是<a href="http://www.cnblogs.com/abeen/archive/2007/02/04/639871.html"><u><font color="#0000ff">http://www.cnblogs.com/abeen/archive/2007/02/04/639871.html</font></u></a><br />
对vs2008不起作用,说下vs2008解决办法:<br />
把C:\Program Files\Common Files\Microsoft Shared\OFFICE12\Office Setup Controller\setup.exe删除或改名<br />
<br />
重启vs,问题解决<br />
<br />
不知道为什么vs切换到设计视图的时候就运行到这个setup.exe,很诡异,看来是跟office 2007 有冲突 本来电脑上没有安装office 2007,一次需要打开.docx,安装了一个相关插件,结果引来这个麻烦事,写下来希望对遇到同样问题的人有点帮助</font></p>
<p><font style="background-color: #c7edcc"></font>&nbsp;</p>
<img src ="http://www.blogjava.net/jvict/aggbug/249714.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2009-01-04 12:13 <a href="http://www.blogjava.net/jvict/articles/249714.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linq to sql取出随机记录/多表查询/将查询出的结果生成xml</title><link>http://www.blogjava.net/jvict/articles/249027.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 15:46:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249027.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249027.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249027.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249027.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249027.html</trackback:ping><description><![CDATA[<p>原文:http://blog.csdn.net/yjmyzz/archive/2008/03/28/2226173.aspx<br />
在手写sql的年代，如果想从sqlserver数据库随机取几条数据，可以利用order by NewId()轻松实现，要实现多表查询也可以用select * from A,B Where A.ID=B.ID做到，但这些功能到了linq to sql中如何实现呢？</p>
<p>关键点:<br />
1.随机排序问题:可以用 Select(d=&gt; new {NewId=new Guid()}).OrderBy(d=&gt;d.NewId)达到order by NewId()的效果<br />
2.多表查询 <br />
from a in TableA <br />
from b in TableB<br />
where a.ID == b.ID</p>
<p>另外利用linq to xml还可以轻易将查询出来的结果保存成xml(这一点比传统xml的方法确实要新颖很多)</p>
<p>详细代码可参考我在一个项目中的示例(功能为随机取机10条产品视频的记录，并生成xml供播放器调用)</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;(DBDataContext&nbsp;db&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;DBDataContext(Database.ConnectionString))<br />
<img id="_80_2347_Open_Image" onclick="this.style.display='none'; document.getElementById('_80_2347_Open_Text').style.display='none'; document.getElementById('_80_2347_Closed_Image').style.display='inline'; document.getElementById('_80_2347_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_80_2347_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_80_2347_Closed_Text').style.display='none'; document.getElementById('_80_2347_Open_Image').style.display='inline'; document.getElementById('_80_2347_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="_80_2347_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_80_2347_Open_Text"><span style="color: #000000">{<br />
<img id="_200_213_Open_Image" onclick="this.style.display='none'; document.getElementById('_200_213_Open_Text').style.display='none'; document.getElementById('_200_213_Closed_Image').style.display='inline'; document.getElementById('_200_213_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_200_213_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_200_213_Closed_Text').style.display='none'; document.getElementById('_200_213_Open_Image').style.display='inline'; document.getElementById('_200_213_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;q&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;db.T_Shops.Where(s&nbsp;</span><span style="color: #000000">=&gt;</span><span style="color: #000000">&nbsp;s.F_ID&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Guid(</span><span style="color: #000000">"</span><span style="color: #000000">00000000-0000-0000-0000-000000000001</span><span style="color: #000000">"</span><span style="color: #000000">)).Select(s&nbsp;</span><span style="color: #000000">=&gt;</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;</span><span id="_200_213_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_200_213_Open_Text"><span style="color: #000000">{&nbsp;s.F_AutoID&nbsp;}</span></span><span style="color: #000000">).First();<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;_ShopAutoId&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;q.F_AutoID.ToString();<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;query&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;(from&nbsp;v&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;db.V_ProductVideos<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;pv&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;db.V_ProductTV<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">where</span><span style="color: #000000">&nbsp;v.F_ShopID&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;Guid(</span><span style="color: #000000">"</span><span style="color: #000000">00000000-0000-0000-0000-000000000001</span><span style="color: #000000">"</span><span style="color: #000000">)&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_ProductID&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;pv.F_ID&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pv.F_Status&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pv.F_isShow&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_Status&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_isShow&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_ProductStatus&nbsp;</span><span style="color: #000000">==</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">1</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000"><br />
<img id="_860_1242_Open_Image" onclick="this.style.display='none'; document.getElementById('_860_1242_Open_Text').style.display='none'; document.getElementById('_860_1242_Closed_Image').style.display='inline'; document.getElementById('_860_1242_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_860_1242_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_860_1242_Closed_Text').style.display='none'; document.getElementById('_860_1242_Open_Image').style.display='inline'; document.getElementById('_860_1242_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="_860_1242_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_860_1242_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_VideoS,<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_VideoP,<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_VideoW,<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_VideoL,<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_ClsAutoID,<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_ProductName,<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;v.F_ProductAutoID,<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NewId&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;Utils.NewComb()<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;).OrderBy(p&nbsp;</span><span style="color: #000000">=&gt;</span><span style="color: #000000">&nbsp;p.NewId).Take(</span><span style="color: #000000">10</span><span style="color: #000000">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">利用linq&nbsp;to&nbsp;xml生成xml</span><span style="color: #008000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;XDocument&nbsp;doc&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;XDocument(<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;XElement(</span><span style="color: #000000">"</span><span style="color: #000000">flvLists</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;from&nbsp;d&nbsp;</span><span style="color: #0000ff">in</span><span style="color: #000000">&nbsp;query<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;select&nbsp;(<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;XElement(<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">item</span><span style="color: #000000">"</span><span style="color: #000000">,<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;XAttribute(</span><span style="color: #000000">"</span><span style="color: #000000">title_p</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;d.F_VideoP),<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;XAttribute(</span><span style="color: #000000">"</span><span style="color: #000000">title_s</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;d.F_VideoS),<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;XAttribute(</span><span style="color: #000000">"</span><span style="color: #000000">name</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;Utils.NoHtml(d.F_ProductName,&nbsp;</span><span style="color: #000000">500</span><span style="color: #000000">)),<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">new</span><span style="color: #000000">&nbsp;XAttribute(</span><span style="color: #000000">"</span><span style="color: #000000">link</span><span style="color: #000000">"</span><span style="color: #000000">,&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">http://www.cntvs.com/product/</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;d.F_ClsAutoID.ToString()&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">/</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;_ShopAutoId&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">/</span><span style="color: #000000">"</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">+</span><span style="color: #000000">&nbsp;d.F_ProductAutoID)<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;))));<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;doc.Save(Server.MapPath(</span><span style="color: #000000">"</span><span style="color: #000000">~/upload/xml/tvvideo.xml</span><span style="color: #000000">"</span><span style="color: #000000">));<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;db.Connection.Close();<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></div>
</div>
<img src ="http://www.blogjava.net/jvict/aggbug/249027.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 23:46 <a href="http://www.blogjava.net/jvict/articles/249027.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>再谈web.config/app.config敏感数据加/解密的二种方法 </title><link>http://www.blogjava.net/jvict/articles/249026.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 15:38:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249026.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249026.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249026.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249026.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249026.html</trackback:ping><description><![CDATA[<p><span style="color: red"><span style="color: #000000"><span style="color: #000000"><a href="http://blog.csdn.net/yjmyzz/archive/2008/08/22/2816477.aspx">原文: http://blog.csdn.net/yjmyzz/archive/2008/08/22/2816477.aspx</a><br />
转载请注明来自"菩提树下的杨过"-</span></span><a id="Editor_Edit_hlEntryLink" title="view: 再谈web.config/app.config敏感数据加/解密的二种方法" href="http://www.cnblogs.com/yjmyzz/archive/2008/08/22/1274395.html" target="_blank"><span style="color: #000000"><span style="color: #000000"><u>http://www.cnblogs.com/yjmyzz/archive/2008/08/22/1274395.html</u></span></span></a></span></p>
<p><span style="color: red"><strong><span style="color: #000000"><u></u></span></strong></span>&nbsp;</p>
<p><span style="color: red"><strong>1.利用代码加解密</strong></span></p>
<p><span style="color: red">&nbsp;</p>
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000ff">using</span><span style="color: #000000">&nbsp;System.Web.Configuration;<br />
<img alt="" src="http://www.cnblogs.com/Images/dot.gif" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
</span><span style="color: #008000">//</span><span style="color: #008000">加密web.Config中的指定节</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;ProtectSection(</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;sectionName)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Configuration&nbsp;config&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ConfigurationSection&nbsp;section&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;config.GetSection(sectionName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(section&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">!</span><span style="color: #000000">section.SectionInformation.IsProtected)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;section.SectionInformation.ProtectSection(</span><span style="color: #800000">"</span><span style="color: #800000">DataProtectionConfigurationProvider</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config.Save();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000">//</span><span style="color: #008000">解密web.Config中的指定节</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">private</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;UnProtectSection(</span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;sectionName)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Configuration&nbsp;config&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ConfigurationSection&nbsp;section&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">&nbsp;config.GetSection(sectionName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">if</span><span style="color: #000000">&nbsp;(section&nbsp;</span><span style="color: #000000">!=</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">null</span><span style="color: #000000">&nbsp;</span><span style="color: #000000">&amp;&amp;</span><span style="color: #000000">&nbsp;section.SectionInformation.IsProtected)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;section.SectionInformation.UnprotectSection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;config.Save();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
</span></div>
<br />
示例:<br />
<div class="cnblogs_code"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000">//</span><span style="color: #008000">加密连接字符串</span><span style="color: #008000"><br />
</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">protected</span><span style="color: #000000">&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;btnEncrypt_Click(</span><span style="color: #0000ff">object</span><span style="color: #000000">&nbsp;sender,&nbsp;EventArgs&nbsp;e)<br />
&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ProtectSection(</span><span style="color: #800000">"</span><span style="color: #800000">connectionStrings</span><span style="color: #800000">"</span><span style="color: #000000">);<br />
&nbsp;}<br />
</span></div>
<p><br />
</span><span style="color: #ff0000">变化:<br />
<br />
</span><font color="#000000">加密前:<br />
&lt;connectionStrings&gt;<br />
&nbsp; &lt;add name="connStr" connectionString="Data Source=server;Initial Catalog=Lib;User ID=sa;password=***"<br />
&nbsp;&nbsp; providerName="System.Data.SqlClient" /&gt;<br />
&nbsp;&lt;/connectionStrings&gt;<br />
</font></p>
<p>加密后:<br />
&lt;connectionStrings configProtectionProvider="DataProtectionConfigurationProvider"&gt;<br />
&nbsp; &lt;EncryptedData&gt;<br />
&nbsp;&nbsp; &lt;CipherData&gt;<br />
&nbsp;&nbsp;&nbsp; </p>
<p>&lt;CipherValue&gt;AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAYzAtjjJo0km/XdUrGFh3YAQAAAACAAAAAAADZgAAqAAAABAAAAD5H0RB6uSYHCk33lo9x5VHAAAAAASAAACgAAAAEAAAALS6KNeUNySZfZ/0tpmh7YWAAQAA85NFHJH</p>
<p>oVx1aW5pTaFfLtTo5J9lWoBR76IYIinLiIjcTeJ4tuAstgCspZlK9NMgzyWmWbbNbb8Z8canVCUpdKF0xmTBTpVih08TtODLszcUpCsJGvEgxuDPi6JtKjG/nT+UvpRp154TNnm04LP/iq1InDxePW2tEViHIiooEXARX8FLY00R</p>
<p>FBaUgarrfi5Fppu4usqavdnj7oqwFEbp3MXOaWY6m9qyVzNsf2G1UwBrivsrM4hZUcr1hy/S87co63ioWie8QDVgGuaTEaSyklC9STyvRsLU6A/QxalCHY4VoRjzNS/27vGoin+c3AJ587wMKJyJBiV08DyzoGM7elAlg8yTAeHv</p>
<p>VMLOEFcTUwsCG0f2rwhi3fZYUyykczYsfHXLEXdbJ+YRiBxYWP6xzffIdyWzrawxaIfnPq/pw6e2Vrwt6tJthDImu0tzXdwupbJVdy4T5vQvy4Fw3SB9lmbSZQacekaXcViBdX7Tejx7TTpDs36RdAOf8WcVMJH4FFAAAACjQFCa</p>
<p>OcSfbD2LXX4YP506vHDXw&lt;/CipherValue&gt;<br />
&nbsp;&nbsp; &lt;/CipherData&gt;<br />
&nbsp; &lt;/EncryptedData&gt;<br />
&nbsp;&lt;/connectionStrings&gt;<br />
<br />
</p>
<p>注意:<br />
加密后，仍然可以按以前的操作来读取，不需要额外的解决操作,因为<br />
&lt;connectionStrings configProtectionProvider="DataProtectionConfigurationProvider"&gt;<br />
这里已经指定了用何种方式解密，asp.net会自动处理</p>
<p>&nbsp;</p>
<p><span style="color: #ff0000"><strong>2.利用aspnet_regiis.exe工具加解密</strong></span><br />
<br />
</p>
<span style="color: #ff0000"><span style="color: red"><span style="color: #000000"><span style="color: #000000"><span style="color: #000000"><span style="color: #000000">
<p><span style="color: #000000"><span style="color: #000000">步骤:<br />
<span style="color: #ff0000">1.</span>先在本地生成RSA容器(<span style="color: #ff0000"><strong><span style="color: #000000"><span style="color: #000000"><span style="color: #000000">有关RSA的详细操作，可参见<a href="http://msdn.microsoft.com/zh-cn/library/yxw286t2(VS.80).aspx"><u>http://msdn.microsoft.com/zh-cn/library/yxw286t2(VS.80).aspx</u></a></span></span></span></strong></span>&nbsp;)<br />
aspnet_regiis.exe -pc "JimmyKeys" -exp<br />
注:JimmyKeys为容器名字，可随便改<br />
<br />
</span></span></p>
<p><span style="color: #000000"><span style="color: #000000"><span style="color: #ff0000">2.</span>再将RSA导出到xml文件<br />
aspnet_regiis.exe -px "JimmyKeys" "c:\JimmyKeys.xml"<br />
<br />
</span></span></p>
<p><span style="color: #000000"><span style="color: #000000"><span style="color: #ff0000">3.</span>在web.config中增加一节,一般放在&lt;appSettings&gt;之前就可以了，如下</span></span></p>
<p><span style="color: #000000"><span style="color: #000000">&lt;configProtectedData&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;providers&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;add name="JimmyRSAProvider"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; type="System.Configuration.RsaProtectedConfigurationProvider,System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; keyContainerName="JimmyKeys"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; useMachineContainer="true" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/providers&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/configProtectedData&gt;</span></span></p>
<p><span style="color: #000000"><span style="color: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;appSettings&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ...<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<span style="color: #ff0000">4.</span>将web.config加密<br />
aspnet_regiis.exe -pef "appSettings" "c:\website" -prov "JimmyRSAProvider" </span></span></p>
<p><span style="color: #000000"><span style="color: #000000">解密:<br />
aspnet_regiis.exe -pdf "appSettings" "c:\website"<br />
<br />
</span></span></p>
<p><span style="color: #000000"><span style="color: #000000"><span style="color: #ff0000">5.</span>部署到远程服务器(1台或多台)<br />
a.将网站文件与JimmyKeys.xml(也就是导出的RSA容器文件)先上传到服务器,同时导入RSA<br />
aspnet_regiis.exe -pi "JimmyKeys" "c:\JimmyKeys.xml"<br />
<br />
</span></span></p>
<p><span style="color: #000000"><span style="color: #000000">b.确认服务器上aspx登录所用的默认帐号<br />
Response.Write(System.Security.Principal.WindowsIdentity.GetCurrent().Name);<br />
随便建一个aspx，把上一行代码贴到里面就可以了，IIS5环境下输出的是ASPNET，IIS6环境下输出的是NETWORK SERVICE，IIS7下没试过也不知道输出的是啥玩意儿<br />
<br />
</span></span></p>
<p><span style="color: #000000"><span style="color: #000000">c.授于RSA窗口的读取权限给b中的默认帐号<br />
aspnet_regiis.exe -pa "JimmyKeys" "NETWORK SERVICE"</span></span></p>
<p><br />
<span style="color: #000000"><span style="color: #000000">顺便把刚才这些个操作的命令整理成几个批处理</span></span></p>
<p><span style="color: #000000"><span style="color: #000000">1.本机bat(新建RSA容器，导出容器，加密web.config)<br />
%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pz "JimmyKeys" <br />
%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pc "JimmyKeys" -exp<br />
%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -px "JimmyKeys" "c:\JimmyKeys.xml"<br />
%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pef "appSettings" "c:\website" -prov "JimmyRSAProvider"</span></span></p>
<p><br />
<span style="color: #000000"><span style="color: #000000">2.远程服务器bat(导入RSA容器，授权)<br />
%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pi "JimmyKeys" "c:\JimmyKeys.xml"<br />
%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis.exe -pa "JimmyKeys" "NETWORK SERVICE"</span></span>&nbsp;</p>
<p></span></span></span></span></span></span><span style="color: #0000ff"><br />
&nbsp;</p>
</span>
<p>加密前:<br />
&nbsp;&lt;connectionStrings&gt;<br />
&nbsp; &lt;add name="connStr" connectionString="Data Source=server;Initial Catalog=Lib;User ID=sa;password=***"<br />
&nbsp;&nbsp; providerName="System.Data.SqlClient" /&gt;<br />
&nbsp;&lt;/connectionStrings&gt;</p>
<p>加密后:<br />
&lt;connectionStrings configProtectionProvider="RsaProtectedConfigurationProvider"&gt;<br />
&nbsp; &lt;EncryptedData Type="<a href="http://www.w3.org/2001/04/xmlenc#Element"><u><font color="#0000ff">http://www.w3.org/2001/04/xmlenc#Element</font></u></a>"<br />
&nbsp;&nbsp; xmlns="<a href="http://www.w3.org/2001/04/xmlenc"><u><font color="#0000ff">http://www.w3.org/2001/04/xmlenc</font></u></a>#"&gt;<br />
&nbsp;&nbsp; &lt;EncryptionMethod Algorithm="<a href="http://www.w3.org/2001/04/xmlenc#tripledes-cbc"><u><font color="#0000ff">http://www.w3.org/2001/04/xmlenc#tripledes-cbc</font></u></a>" /&gt;<br />
&nbsp;&nbsp; &lt;KeyInfo xmlns="<a href="http://www.w3.org/2000/09/xmldsig"><u><font color="#0000ff">http://www.w3.org/2000/09/xmldsig</font></u></a>#"&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;EncryptedKey xmlns="<a href="http://www.w3.org/2001/04/xmlenc"><u><font color="#0000ff">http://www.w3.org/2001/04/xmlenc</font></u></a>#"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;EncryptionMethod Algorithm="<a href="http://www.w3.org/2001/04/xmlenc#rsa-1_5"><u><font color="#0000ff">http://www.w3.org/2001/04/xmlenc#rsa-1_5</font></u></a>" /&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;KeyInfo xmlns="<a href="http://www.w3.org/2000/09/xmldsig"><u><font color="#0000ff">http://www.w3.org/2000/09/xmldsig</font></u></a>#"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;KeyName&gt;Rsa Key&lt;/KeyName&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/KeyInfo&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;CipherData&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&lt;CipherValue&gt;breSi2wD4X4CAKh0puzhYtyltmR3cp9JfEE8Yw03NeWGZCOoEvDuxAceKLEsmYx8r/tI5NsZxOmY20pQzD1KvGELzz4rhkEPE9LKTAwyKNhqzMPFoRnjsdGTvs6JhrvVat9rdvgKbfTvVLXuvpXgSeNB0T6XJWq</p>
<p>/vOIU7KTyFjk=&lt;/CipherValue&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/CipherData&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/EncryptedKey&gt;<br />
&nbsp;&nbsp; &lt;/KeyInfo&gt;<br />
&nbsp;&nbsp; &lt;CipherData&gt;<br />
&nbsp;&nbsp;&nbsp; </p>
<p>&lt;CipherValue&gt;c4HD+EfJl//pv4eEzT938aWYhLyPBUt8lbNWf4Y4c6tewWLNBTwgYXtxPh6TnF8ne6s9H5C/AwXy/3JECuNEd8YGOO+RDhxw8NySd8vUc53+iUiHW5TLs/aoIvy8k1yOfLWGKFFWPtoX4F4gMTS+MAmhkiHQ46p</p>
<p>H2VyjyprNsl8LE2pGNjDOJnDeGYq+wkn2iw968+qjuTCibGJn6h6iGYGHYmkYUrgRzfo3iIZu+eCWE2IqCP+s58eQRjU3MxJ2BqeUU9HaKy4=&lt;/CipherValue&gt;<br />
&nbsp;&nbsp; &lt;/CipherData&gt;<br />
&nbsp; &lt;/EncryptedData&gt;<br />
&nbsp;&lt;/connectionStrings&gt;</p>
<p>同样，这种方式加密后，aspx读取节点时也无需任何解密处理，代码不用做任何修改</p>
<p><br />
<span style="color: #ff0000">注意:</span>并不是所有的节点都能加密，ASP.NET 2.0仅支持对Web.config的部分配置节进行加密，以下配置节中的数据是不能进行加密的：<br />
&#8226;&nbsp;&lt;processModel&gt;<br />
&#8226;&nbsp;&lt;runtime&gt;<br />
&#8226;&nbsp;&lt;mscorlib&gt;<br />
&#8226;&nbsp;&lt;startup&gt;<br />
&#8226;&nbsp;&lt;system.runtime.remoting&gt;<br />
&#8226;&nbsp;&lt;configProtectedData&gt;<br />
&#8226;&nbsp;&lt;satelliteassemblies&gt;<br />
&#8226;&nbsp;&lt;cryptographySettings&gt;<br />
&#8226;&nbsp;&lt;cryptoNameMapping&gt;<br />
&#8226;&nbsp;&lt;cryptoClasses&gt;</p>
<p><br />
另外，除了AppSettings和ConnectionStrings以外的其它节点，可以这样写:<br />
aspnet_regiis.exe -pef "<span style="color: #ff0000">system.serviceModel/behaviors</span>" "d:\website\cntvs\" <br />
<br />
即对&lt;system.serviceModel&gt;下的&lt;behaviors&gt;节点加密,这一节点同样适用于代码方式加密，经过多次尝试，似乎除了AppSettings和ConnectionStrings以外的其它节点，只能支持二级节点。<br />
</p>
<p>象以下写法:<br />
aspnet_regiis.exe -pef "<span style="color: #ff0000">system.serviceModel/behaviors/endpointBehaviors</span>" "d:\website\cntvs"　<br />
运行时会报错:</p>
<p><span style="color: #ff0000">未找到配置节&#8220;system.serviceModel/behaviors/endpointBehaviors&#8221;。</span></p>
<p>&nbsp;</p>
<img src ="http://www.blogjava.net/jvict/aggbug/249026.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 23:38 <a href="http://www.blogjava.net/jvict/articles/249026.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转自雨痕]LINQ to SQL - Delay Loaded </title><link>http://www.blogjava.net/jvict/articles/249022.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 15:35:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249022.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249022.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249022.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249022.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249022.html</trackback:ping><description><![CDATA[<div class="postBody">
<p>原文: <a href="http://www.rainsts.net/article.asp?id=550"><font color="#a91718">http://www.rainsts.net/article.asp?id=550</font></a></p>
<p><font color="#a91718"></font>&nbsp;</p>
<p>对 ORM 而言，延迟加载(也叫 Lazy Loading)是必须的，毕竟当我们只是获取用户基本信息时，总不能动不动就返回大段的用户个人简介不是。<br />
<br />
在 VS 2008 O/R Designer 中，很容易找到 Delay Loaded 的设置。<br />
<br />
</p>
<div style="overflow-x: auto; width: 100%"><a href="http://www.rainsts.net/uploads/200708/27_133811_snap1.gif" target="_blank"><img alt="uploads/200708/27_133811_snap1.gif" src="http://www.rainsts.net/uploads/200708/27_133811_snap1.gif" /></a></div>
<p><br />
<br />
只是当我在自动生成的代码中找寻这个设置时，着实迷糊了半天。基于惯性思维，我查看了几乎所有的特性(Attribute)声明，却一无所获，最后才发觉这个家伙竟然是这个样子。<br />
<br />
<strong>Delay Loaded = False</strong> </p>
<div class="code">[Table(Name="dbo.[User]")]<br />
public partial class User : INotifyPropertyChanging, INotifyPropertyChanged<br />
{<br />
&nbsp;&nbsp;private string _Job;<br />
}</div>
<p><br />
<strong>Delay Loaded = True</strong> </p>
<div class="code">[Table(Name="dbo.[User]")]<br />
public partial class User : INotifyPropertyChanging, INotifyPropertyChanged<br />
{<br />
&nbsp;&nbsp;private System.Data.Linq.Link&lt;string&gt; _Job;<br />
}</div>
<p><br />
习惯害人~~~~ 接下来我们测试一下延迟加载的作用。<br />
</p>
<div class="code">using (DataClasses1DataContext context = new DataClasses1DataContext())<br />
{<br />
&nbsp;&nbsp;context.Log = Console.Out;<br />
<br />
&nbsp;&nbsp;var user = (from u in context.Users where u.Name == "user1" select u).FirstOrDefault();<br />
&nbsp;&nbsp;Console.WriteLine(user.Name);<br />
&nbsp;&nbsp;Console.WriteLine(user.Job);<br />
}</div>
<p><br />
Delay Loaded = False 输出<br />
</p>
<div class="code">SELECT TOP 1 [t0].[Id], [t0].[Name], [t0].[Age], [t0].[Job]<br />
FROM [dbo].[User] AS [t0]<br />
WHERE [t0].[Name] = @p0<br />
-- @p0: Input String (Size = 5; Prec = 0; Scale = 0) [user1]<br />
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20706.1<br />
<br />
user1<br />
job</div>
<p><br />
Delay Loaded = True 输出<br />
</p>
<div class="code">SELECT TOP 1 [t0].[Id], [t0].[Name], [t0].[Age]<br />
FROM [dbo].[User] AS [t0]<br />
WHERE [t0].[Name] = @p0<br />
-- @p0: Input String (Size = 5; Prec = 0; Scale = 0) [user1]<br />
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20706.1<br />
<br />
user1<br />
SELECT [t0].[Job]<br />
FROM [dbo].[User] AS [t0]<br />
WHERE [t0].[Name] = @p0<br />
-- @p0: Input String (Size = 5; Prec = 0; Scale = 0) [user1]<br />
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.20706.1<br />
<br />
job</div>
<p><br />
当设置延迟加载后，查询 User 时并没有返回 Job 字段值，只有当访问该属性时才进行了第二次 SQL 操作，很显然这就是我们所需要的。延迟加载虽然很有用，但并不表示我们应该将 n 多的 Column 设置成 Delay Loaded = true，或许你要做的是创建另外一个 One-to-One / Base-to-Detail。<br />
<br />
<strong>注意！</strong>当 "context.DeferredLoadingEnabled = false" 或 "context.ObjectTrackingEnabled = false" 时，都会导致 Delay Loaded 失效，不再进行延迟字段载入操作。 </p>
</div>
<img src ="http://www.blogjava.net/jvict/aggbug/249022.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 23:35 <a href="http://www.blogjava.net/jvict/articles/249022.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> linq to sql中慎用Where(Func predicate)，小心被Linq给"骗"了! </title><link>http://www.blogjava.net/jvict/articles/249019.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 15:29:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249019.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249019.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249019.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249019.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249019.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文:http://blog.csdn.net/yjmyzz/archive/2008/09/06/2890842.aspx近日在一个大型Web项目中，采用Linq to Sql替换原来的sqlcommand/sqldatareader方式来获取数据，上线后刚开始一切正常，但是随着访问量的增加，网站明显慢了很多，监测服务器CPU占用率/内存使用情况等性能指标却发现均在正常范围内，无意中在S...&nbsp;&nbsp;<a href='http://www.blogjava.net/jvict/articles/249019.html'>阅读全文</a><img src ="http://www.blogjava.net/jvict/aggbug/249019.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 23:29 <a href="http://www.blogjava.net/jvict/articles/249019.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>LINQ体验(6)——LINQ to SQL语句之Join和Order By </title><link>http://www.blogjava.net/jvict/articles/249014.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 15:07:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249014.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249014.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249014.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249014.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249014.html</trackback:ping><description><![CDATA[<h1>原文:http://www.cnblogs.com/lyj/archive/2008/01/24/1051495.html</h1>
<h1>Join操作</h1>
<p><strong>适用场景</strong>：在我们表关系中有一对一关系，一对多关系，多对多关系等。对各个表之间的关系，就用这些实现对多个表的操作。</p>
<p><strong>说明</strong>：在Join操作中，分别为Join(Join查询), SelectMany(Select一对多选择)和GroupJoin(分组Join查询)。<br />
该扩展方法对两个序列中键匹配的元素进行inner join操作</p>
<h1>SelectMany</h1>
<p><strong>说明</strong>：我们在写查询语句时，如果被翻译成SelectMany需要满足2个条件。1：查询语句中没有join和into，2：必须出现EntitySet。在我们表关系中有一对一关系，一对多关系，多对多关系等，下面分别介绍一下。 </p>
<h2>1.一对多关系(1 to Many)：</h2>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>c <span style="color: blue">in </span>db.Customers
<span style="color: blue">from </span>o <span style="color: blue">in </span>c.Orders
<span style="color: blue">where </span>c.City == <span style="color: #a31515">"London"
</span><span style="color: blue">select </span>o;</pre>
<p>语句描述：Customers与Orders是一对多关系。即Orders在Customers类中以EntitySet形式出现。所以第二个from是从c.Orders而不是db.Orders里进行筛选。这个例子在From子句中使用外键导航选择伦敦客户的所有订单。</p>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>p <span style="color: blue">in </span>db.Products
<span style="color: blue">where </span>p.Supplier.Country == <span style="color: #a31515">"USA" </span>&amp;&amp; p.UnitsInStock == 0
<span style="color: blue">select </span>p;</pre>
<p>语句描述：这一句使用了p.Supplier.Country条件，间接关联了Supplier表。这个例子在Where子句中使用外键导航筛选其供应商在美国且缺货的产品。生成SQL语句为：</p>
<pre class="code"><span style="color: blue">SELECT </span>[t0].[ProductID], [t0].[ProductName], [t0].[SupplierID],
[t0].[CategoryID],[t0].[QuantityPerUnit],[t0].[UnitPrice],
[t0].[UnitsInStock], [t0].[UnitsOnOrder],[t0].[ReorderLevel],
[t0].[Discontinued] <span style="color: blue">FROM </span>[dbo].[Products] <span style="color: blue">AS </span>[t0]
<span style="color: blue">LEFT OUTER JOIN </span>[dbo].[Suppliers] <span style="color: blue">AS </span>[t1] <span style="color: blue">ON
</span>[t1].[SupplierID] = [t0].[SupplierID]
<span style="color: blue">WHERE </span>([t1].[Country] = @p0) <span style="color: blue">AND </span>([t0].[UnitsInStock] = @p1)
<span style="color: green">-- @p0: Input NVarChar (Size = 3; Prec = 0; Scale = 0) [USA]
-- @p1: Input Int (Size = 0; Prec = 0; Scale = 0) [0]</span></pre>
<h2>2.多对多关系(Many to Many)：</h2>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>e <span style="color: blue">in </span>db.Employees
<span style="color: blue">from </span>et <span style="color: blue">in </span>e.EmployeeTerritories
<span style="color: blue">where </span>e.City == <span style="color: #a31515">"Seattle"
</span><span style="color: blue">select new
</span>{
e.FirstName,
e.LastName,
et.Territory.TerritoryDescription
};</pre>
<p>说明：多对多关系一般会涉及三个表(如果有一个表是自关联的，那有可能只有2个表)。这一句语句涉及Employees, EmployeeTerritories, Territories三个表。它们的关系是1：M：1。Employees和Territories没有很明确的关系。</p>
<p>语句描述：这个例子在From子句中使用外键导航筛选在西雅图的雇员，同时列出其所在地区。这条生成SQL语句为：</p>
<pre class="code"><span style="color: blue">SELECT </span>[t0].[FirstName], [t0].[LastName], [t2].[TerritoryDescription]
<span style="color: blue">FROM </span>[dbo].[Employees] <span style="color: blue">AS </span>[t0] <span style="color: blue">CROSS JOIN </span>[dbo].[EmployeeTerritories]
<span style="color: blue">AS </span>[t1] <span style="color: blue">INNER JOIN </span>[dbo].[Territories] <span style="color: blue">AS </span>[t2] <span style="color: blue">ON
</span>[t2].[TerritoryID] = [t1].[TerritoryID]
<span style="color: blue">WHERE </span>([t0].[City] = @p0) <span style="color: blue">AND </span>([t1].[EmployeeID] = [t0].[EmployeeID])
<span style="color: green">-- @p0: Input NVarChar (Size = 7; Prec = 0; Scale = 0) [Seattle]</span></pre>
<h2>3.自联接关系：</h2>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>e1 <span style="color: blue">in </span>db.Employees
<span style="color: blue">from </span>e2 <span style="color: blue">in </span>e1.Employees
<span style="color: blue">where </span>e1.City == e2.City
<span style="color: blue">select new </span>{
FirstName1 = e1.FirstName, LastName1 = e1.LastName,
FirstName2 = e2.FirstName, LastName2 = e2.LastName,
e1.City
};</pre>
<p>语句描述：这个例子在select 子句中使用外键导航筛选成对的雇员，每对中一个雇员隶属于另一个雇员，且两个雇员都来自相同城市。生成SQL语句为：</p>
<pre class="code"><span style="color: blue">SELECT </span>[t0].[FirstName] <span style="color: blue">AS </span>[FirstName1], [t0].[LastName] <span style="color: blue">AS </span>
[LastName1],[t1].[FirstName] <span style="color: blue">AS </span>[FirstName2], [t1].[LastName] <span style="color: blue">AS </span>
[LastName2],[t0].[City] <span style="color: blue">FROM </span>[dbo].[Employees] <span style="color: blue">AS </span>[t0],
[dbo].[Employees] <span style="color: blue">AS </span>[t1] <span style="color: blue">WHERE </span>([t0].[City] = [t1].[City]) <span style="color: blue">AND </span>
([t1].[ReportsTo] = [t0].[EmployeeID])</pre>
<h1>GroupJoin</h1>
<p>像上面所说的，没有join和into，被翻译成SelectMany，同时有join和into时，那么就被翻译为GroupJoin。在这里into的概念是对其结果进行重新命名。</p>
<h2>1.双向联接(Two way join)：</h2>
<p>此示例显式联接两个表并从这两个表投影出结果：</p>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>c <span style="color: blue">in </span>db.Customers
<span style="color: blue">join </span>o <span style="color: blue">in </span>db.Orders <span style="color: blue">on </span>c.CustomerID
<span style="color: blue">equals </span>o.CustomerID <span style="color: blue">into </span>orders
<span style="color: blue">select new
</span>{
c.ContactName,
OrderCount = orders.Count()
};</pre>
<p>说明：在一对多关系中，左边是1，它每条记录为c（from c in db.Customers），右边是Many，其每条记录叫做o ( join o in db.Orders )，每对应左边的一个c，就会有一组o，那这一组o，就叫做orders，也就是说，我们把一组o命名为orders，这就是into用途。这也就是为什么在select语句中，orders可以调用聚合函数Count。在T-SQL中，使用其内嵌的T-SQL返回值作为字段值。如图所示：</p>
<p><a href="http://lyj.cnblogs.com/images/cnblogs_com/lyj/LINQ/LINQ16.gif" target="_blank"><img alt="GroupJoin示意图" src="http://lyj.cnblogs.com/images/cnblogs_com/lyj/LINQ/LINQ16.gif" /></a></p>
<p>生成SQL语句为：</p>
<pre class="code"><span style="color: blue">SELECT </span>[t0].[ContactName], (
<span style="color: blue">SELECT COUNT</span>(*)
<span style="color: blue">FROM </span>[dbo].[Orders] <span style="color: blue">AS </span>[t1]
<span style="color: blue">WHERE </span>[t0].[CustomerID] = [t1].[CustomerID]
) <span style="color: blue">AS </span>[OrderCount]
<span style="color: blue">FROM </span>[dbo].[Customers] <span style="color: blue">AS </span>[t0]</pre>
<h2>2.三向联接(There way join)：</h2>
<p>此示例显式联接三个表并分别从每个表投影出结果：</p>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>c <span style="color: blue">in </span>db.Customers
<span style="color: blue">join </span>o <span style="color: blue">in </span>db.Orders <span style="color: blue">on </span>c.CustomerID
<span style="color: blue">equals </span>o.CustomerID <span style="color: blue">into </span>ords
<span style="color: blue">join </span>e <span style="color: blue">in </span>db.Employees <span style="color: blue">on </span>c.City
<span style="color: blue">equals </span>e.City <span style="color: blue">into </span>emps
<span style="color: blue">select new
</span>{
c.ContactName,
ords = ords.Count(),
emps = emps.Count()
};</pre>
<p>生成SQL语句为：</p>
<pre class="code"><span style="color: blue">SELECT </span>[t0].[ContactName], (
<span style="color: blue">SELECT COUNT</span>(*)
<span style="color: blue">FROM </span>[dbo].[Orders] <span style="color: blue">AS </span>[t1]
<span style="color: blue">WHERE </span>[t0].[CustomerID] = [t1].[CustomerID]
) <span style="color: blue">AS </span>[ords], (
<span style="color: blue">SELECT COUNT</span>(*)
<span style="color: blue">FROM </span>[dbo].[Employees] <span style="color: blue">AS </span>[t2]
<span style="color: blue">WHERE </span>[t0].[City] = [t2].[City]
) <span style="color: blue">AS </span>[emps]
<span style="color: blue">FROM </span>[dbo].[Customers] <span style="color: blue">AS </span>[t0]</pre>
<h2>3.左外部联接(Left Outer Join)：</h2>
<p>此示例说明如何通过使用 此示例说明如何通过使用DefaultIfEmpty() 获取左外部联接。在雇员没有订单时，DefaultIfEmpty()方法返回null：</p>
<pre class="code"><span style="color: blue">var</span> q =
<span style="color: blue">from </span>e <span style="color: blue">in </span>db.Employees
<span style="color: blue">join </span>o <span style="color: blue">in </span>db.Orders <span style="color: blue">on </span>e <span style="color: blue">equals </span>o.Employee <span style="color: blue">into </span>ords
<span style="color: blue">from </span>o <span style="color: blue">in </span>ords.DefaultIfEmpty()
<span style="color: blue">select new
</span>{
e.FirstName,
e.LastName,
Order = o
};</pre>
<p>说明：以Employees左表，Orders右表，Orders 表中为空时，用null值填充。Join的结果重命名ords，使用DefaultIfEmpty()函数对其再次查询。其最后的结果中有个Order，因为from o in ords.DefaultIfEmpty() 是对ords组再一次遍历，所以，最后结果中的Order并不是一个集合。但是，如果没有from o in ords.DefaultIfEmpty() 这句，最后的select语句写成select new { e.FirstName, e.LastName, Order = ords }的话，那么Order就是一个集合。</p>
<h2>4.投影的Let赋值(Projected let assignment)：</h2>
<p>说明：let语句是重命名。let位于第一个from和select语句之间。</p>
<p>这个例子从联接投影出最终&#8220;Let&#8221;表达式：</p>
<pre class="code"><span style="color: blue">var</span> q =
<span style="color: blue">from </span>c <span style="color: blue">in </span>db.Customers
<span style="color: blue">join </span>o <span style="color: blue">in </span>db.Orders <span style="color: blue">on </span>c.CustomerID
<span style="color: blue">equals </span>o.CustomerID <span style="color: blue">into </span>ords
<span style="color: blue">let </span>z = c.City + c.Country
<span style="color: blue">from </span>o <span style="color: blue">in </span>ords
<span style="color: blue">select new
</span>{
c.ContactName,
o.OrderID,
z
};</pre>
<h2>5.组合键(Composite Key)：</h2>
<p>这个例子显示带有组合键的联接：</p>
<pre class="code"><span style="color: blue">var</span> q =
<span style="color: blue">from </span>o <span style="color: blue">in </span>db.Orders
<span style="color: blue">from </span>p <span style="color: blue">in </span>db.Products
<span style="color: blue">join </span>d <span style="color: blue">in </span>db.OrderDetails
<span style="color: blue">on new
</span>{
o.OrderID,
p.ProductID
} <span style="color: blue">equals
new
</span>{
d.OrderID,
d.ProductID
}
<span style="color: blue">into </span>details
<span style="color: blue">from </span>d <span style="color: blue">in </span>details
<span style="color: blue">select new
</span>{
o.OrderID,
p.ProductID,
d.UnitPrice
};</pre>
<p>说明：使用三个表，并且用匿名类来说明：使用三个表，并且用匿名类来表示它们之间的关系。它们之间的关系不能用一个键描述清楚，所以用匿名类，来表示组合键。还有一种是两个表之间是用组合键表示关系的，不需要使用匿名类。</p>
<h2>6.可为null/不可为null的键关系(Nullable/Nonnullable Key Relationship)：</h2>
<p>这个实例显示如何构造一侧可为 null 而另一侧不可为 null 的联接：</p>
<pre class="code"><span style="color: blue">var</span> q =
<span style="color: blue">from </span>o <span style="color: blue">in </span>db.Orders
<span style="color: blue">join </span>e <span style="color: blue">in </span>db.Employees
<span style="color: blue">on </span>o.EmployeeID <span style="color: blue">equals
</span>(<span style="color: blue">int</span>?)e.EmployeeID <span style="color: blue">into </span>emps
<span style="color: blue">from </span>e <span style="color: blue">in </span>emps
<span style="color: blue">select new
</span>{
o.OrderID,
e.FirstName
};</pre>
<h1>Order By操作</h1>
<p><strong>适用场景</strong>：对查询出的语句进行排序，比如按时间排序等等。</p>
<p><strong>说明</strong>：按指定表达式对集合排序；延迟，：按指定表达式对集合排序；延迟，默认是升序，加上descending表示降序，对应的扩展方法是OrderBy和OrderByDescending</p>
<h2>1.简单形式</h2>
<p>这个例子使用 orderby 按雇用日期对雇员进行排序：</p>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>e <span style="color: blue">in </span>db.Employees
<span style="color: blue">orderby </span>e.HireDate
<span style="color: blue">select </span>e;</pre>
<p>说明：默认为升序</p>
<h2>2.带条件形式</h2>
<p>注意：Where和Order By的顺序并不重要。而在T-SQL中，Where和Order By有严格的位置限制。</p>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>o <span style="color: blue">in </span>db.Orders
<span style="color: blue">where </span>o.ShipCity == <span style="color: #a31515">"London"
</span><span style="color: blue">orderby </span>o.Freight
<span style="color: blue">select </span>o;</pre>
<p>语句描述：使用where和orderby按运费进行排序。</p>
<h2>3.降序排序</h2>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>p <span style="color: blue">in </span>db.Products
<span style="color: blue">orderby </span>p.UnitPrice <span style="color: blue">descending
select </span>p;</pre>
<h2>4.ThenBy</h2>
<p>语句描述：使用复合的 orderby 对客户进行排序，进行排序：</p>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>c <span style="color: blue">in </span>db.Customers
<span style="color: blue">orderby </span>c.City, c.ContactName
<span style="color: blue">select </span>c;</pre>
<p>说明：按多个表达式进行排序，例如先按City排序，当City相同时，按ContactName排序。这一句用Lambda表达式像这样写：</p>
<pre class="code"><span style="color: blue">var</span> q =
db.Customers
.OrderBy(c =&gt; c.City)
.ThenBy(c =&gt; c.ContactName).ToList();</pre>
<p>在T-SQL中没有ThenBy语句，其依然翻译为OrderBy，所以也可以用下面语句来表达：</p>
<pre class="code"><span style="color: blue">var </span>q =
db.Customers
.OrderBy(c =&gt; c.ContactName)
.OrderBy(c =&gt; c.City).ToList();</pre>
<p>所要注意的是，多个OrderBy操作时，级连方式是按逆序。对于降序的，用相应的降序操作符替换即可。</p>
<pre class="code"><span style="color: blue">var </span>q =
db.Customers
.OrderByDescending(c =&gt; c.City)
.ThenByDescending(c =&gt; c.ContactName).ToList();</pre>
<p>需要说明的是，OrderBy操作，不支持按type排序，也不支持匿名类。比如 </p>
<pre class="code"><span style="color: blue">var </span>q =
db.Customers
.OrderBy(c =&gt; <span style="color: blue">new
</span>{
c.City,
c.ContactName
}).ToList();</pre>
<p>会被抛出异常。错误是前面的操作有匿名类，再跟OrderBy时，比较的是类别。比如</p>
<pre class="code"><span style="color: blue">var </span>q =
db.Customers
.Select(c =&gt; <span style="color: blue">new
</span>{
c.City,
c.Address
})
.OrderBy(c =&gt; c).ToList();</pre>
<p>如果你想使用OrderBy(c =&gt; c)，其前提条件是，前面步骤中，所产生的对象的类别必须为C#语言的基本类型。比如下句，这里City为string类型。</p>
<pre class="code"><span style="color: blue">var </span>q =
db.Customers
.Select(c =&gt; c.City)
.OrderBy(c =&gt; c).ToList();</pre>
<h2>5.ThenByDescending</h2>
<p>这两个扩展方式都是用在OrderBy/OrderByDescending之后的，第一个ThenBy/ThenByDescending扩展方法作为第二位排序依据，第二个ThenBy/ThenByDescending则作为第三位排序依据，以此类推</p>
<pre class="code"><span style="color: blue">var </span>q =
<span style="color: blue">from </span>o <span style="color: blue">in </span>db.Orders
<span style="color: blue">where </span>o.EmployeeID == 1
<span style="color: blue">orderby </span>o.ShipCountry, o.Freight <span style="color: blue">descending
select </span>o;</pre>
<p>语句描述：使用orderby先按发往国家再按运费从高到低的顺序对 EmployeeID 1 的订单进行排序。</p>
<h2>6.带GroupBy形式</h2>
<pre class="code"><span style="color: blue">var</span> q =
<span style="color: blue">from </span>p <span style="color: blue">in </span>db.Products
<span style="color: blue">group </span>p <span style="color: blue">by </span>p.CategoryID<span style="color: blue"> into </span>g
<span style="color: blue">orderby </span>g.Key
<span style="color: blue">select new </span>{
g.Key,
MostExpensiveProducts =
<span style="color: blue">from </span>p2 <span style="color: blue">in </span>g
<span style="color: blue">where </span>p2.UnitPrice == g.Max(p3 =&gt; p3.UnitPrice)
<span style="color: blue">select </span>p2
};</pre>
<p>语句描述：使用orderby、Max 和 Group By 得出每种类别中单价最高的产品，并按 CategoryID 对这组产品进行排序。</p>
<p>本系列链接：<a href="http://www.cnblogs.com/lyj/archive/2008/03/24/1119671.html" target="_blank">LINQ体验系列文章导航</a></p>
<h2>LINQ推荐资源</h2>
<p>LINQ专题：<a href="http://kb.cnblogs.com/zt/linq/" target="_blank">http://kb.cnblogs.com/zt/linq/</a> 关于LINQ方方面面的入门、进阶、深入的文章。<br />
LINQ小组：<a href="http://space.cnblogs.com/group/linq/" target="_blank">http://space.cnblogs.com/group/linq/</a> 学习中遇到什么问题或者疑问提问的好地方。</p>
<p id="LyjSignature"><br />
作者：<a href="http://lyj.cnblogs.com/" target="_blank">李永京</a>（<a href="http://lyj.cnblogs.com/" target="_blank">YJingLee's Blog</a>）<br />
出处：<a href="http://lyj.cnblogs.com/" target="_blank">http://lyj.cnblogs.com</a><br />
本文版权归作者和博客园共有，欢迎转载，但未经作者同意必须保留此段声明，且在文章页面明显位置给出原文连接，否则保留追究法律责任的权利。</p>
<img src ="http://www.blogjava.net/jvict/aggbug/249014.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 23:07 <a href="http://www.blogjava.net/jvict/articles/249014.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转自Scott]ASP.NET MVC框架(第四部分): 处理表单编辑和提交场景</title><link>http://www.blogjava.net/jvict/articles/249011.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 14:52:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249011.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249011.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249011.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249011.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249011.html</trackback:ping><description><![CDATA[<p>过去的几个星期内，我一直在写着讨论我们正在开发的新ASP.NET MVC框架的系列贴子。ASP.NET MVC框架是个你可以用来结构化你的ASP.NET web应用，使之拥有清晰的关注分离，方便你单元测试代码和支持TDD流程的可选方法。 </p>
<p>这个系列的<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一篇</font></a>建造了一个简单的电子商务产品列表/浏览网站。它讨论了MVC后面的高层次的概念，示范了如何从头创建一个新的ASP.NET MVC项目，实现和测试这个电子商务产品列表功能。系列的<a href="http://blog.joycode.com/scottgu/archive/2007/12/04/112249.aspx" target="_blank"><font color="#087da8">第二篇</font></a>对ASP.NET MVC框架的URL路径选择（routing）架构做了深入探讨，讨论了它的工作原理以及你如何使用它来处理更高级的URL路径选择场景。 <a href="http://blog.joycode.com/scottgu/archive/2007/12/07/112355.aspx" target="_blank"><font color="#087da8">第三篇</font></a>讨论了控制器是如何与视图做交互的，特别地讨论了你可以把视图数据从控制器传给视图以显示返回到客户端的回复的各种方法。 </p>
<p>在今天的帖子里，我将讨论你可以用MVC框架来处理表单输入和提交场景的各种方法，以及讨论一些你可以用来简化数据编辑场景的HTML辅助方法。<a href="http://www.scottgu.com/blogposts/mvc4/mvcapplication5.zip" target="_blank"><font color="#087da8">点击这里</font></a>下载我们将在下面为解释这些概念而建造的完整的应用的源代码。 </p>
<h3><u>表单输入和提交场景</u></h3>
<p>为示范如何在ASP.NET MVC框架中处理表单输入和提交场景的一些基本原则，我们将建造一个简单的产品列表，产品生成，和产品编辑场景。它将拥有三个核心的用户体验：</p>
<p><u>按类列出的产品列表</u></p>
<p>通过导航到<em>/Products/Category/[CategoryID]</em> 这样的URL，用户将能看到在某个特定产品分类内的所有产品的列表： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step1.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step1.png" width="500" /></a> </p>
<p><u>添加新产品</u></p>
<p>用户将能通过点击上面的&#8220;添加新产品&#8221;的链接往商店里添加一个新产品。点击之后，会转到<em>/Products/New</em> URL，在这里，系统将提示用户输入要添加的新产品的细节： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step2.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step2.png" width="500" /></a> </p>
<p>在点击Save（保存）之后，产品就会添加到数据库中，然后就会转向返回到产品列表网页。 </p>
<p><u>编辑产品</u></p>
<p>在产品列表网页上，用户可以点击每个产品旁边的&#8220;Edit&#8221;（编辑）链接。这会转到<em>/Products/Edit/[ProductID]</em> URL，在这里，用户可以改动产品的细节，然后点击Save按钮，往数据库里更新： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step3.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step3.png" width="500" /></a> </p>
<h3><u>我们的数据模型</u></h3>
<p>我们将使用SQL Server Northwind样品数据库来存储我们的数据。然后我们将使用.NET 3.5内置的LINQ to SQL对象关系映射器（ORM）来对Product, Category, 和 Supplier对象进行建模，这些对象代表了我们的数据库数据表中的记录行。 </p>
<p>一开始，在ASP.NET MVC项目中，右击/Models子目录，选择&#8220;添加新项&#8221; -&gt; &#8220;LINQ to SQL 类&#8221;，调出 <a href="http://weblogs.asp.net/scottgu/archive/2007/05/29/linq-to-sql-part-2-defining-our-data-model-classes.aspx" target="_blank"><font color="#087da8">LINQ to SQL orM 设计器</font></a>来对我们的数据对象建模： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step4.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step4.png" width="500" /></a> </p>
<p>然后我们将在项目中创建一个NorthwindDataContext部分类（partial class），向里面添加一些辅助方法。我们定义这些辅助方法有2个原因： 1)避免在我们的Controller类中直接嵌入我们的LINQ查询，2) 将允许我们在将来更容易地改变我们的控制器以使用dependency injection（依赖注入）。 </p>
<p>我们将添加的NorthwindDataContext辅助方法是象下面这样的： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step5.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step5.png" width="500" /></a> </p>
<p>想进一步了解LINQ和LINQ to SQL的话，请参阅我<a href="http://weblogs.asp.net/scottgu/archive/2007/09/07/linq-to-sql-part-9-using-a-custom-linq-expression-with-the-lt-asp-linqdatasource-gt-control.aspx" target="_blank"><font color="#087da8">这里</font></a>的LINQ to SQL系列。</p>
<h3><u>建造我们ProductsController控制器</u></h3>
<p>我们将使用单一控制器类来实现这三个核心用户浏览体验，我们将称这个控制器类为&#8220;ProductsController&#8221;（在Controllers子目录上右击，选择&#8220;添加新项&#8221; -&gt; &#8220;MVC 控制器&#8221;来创建这个类： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step6.png" /> </p>
<p>我们的 ProductsController 类将通过实现"Category", "New", 和"Edit" 等action方法来处理象<em>/Products/Category/3</em>, <em>/Products/New</em>, 和<em>/Products/Edit/5</em>这样的URL： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step7.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step7.png" width="500" /></a> </p>
<p>想了解这些URL是如何导向到 ProductsController 类的action方法上的话，请阅读我的ASP.NET MVC系列的<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一部分</font></a>和<a href="http://blog.joycode.com/scottgu/archive/2007/12/04/112249.aspx" target="_blank"><font color="#087da8">第二部分</font></a>。在本文的例子里，我们将使用默认的<em>/[Controller]/[Action]/[Id]</em>路径映射规则，这意味着我们<u>不必</u>配置什么东西，路径导向就会自动发生。 </p>
<p>我们控制器的Action方法将使用三个视图网页，用以显示输出。"List.aspx", "New.aspx", 和 "Edit.aspx" 网页将居于 \Views\Products 子目录下，这些网页将基于\Views\Shared目录中的Site.Master母版页上。 </p>
<h3><u>实现按类列出的产品列表</u></h3>
<p>我们要实现的网站的第一部分将是产品列表URL (/Products/Category/[CategoryId]) ： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step1.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step1.png" width="500" /></a> </p>
<p>我们将使用我们的ProductsController类上的"Category" action方法来实现这个功能。我们将使用LINQ to SQL DataContext类，和我们往其中添加的GetCategoryById辅助方法，来获取一个Category对象，该对象代表了由URL （譬如， /Products/Category/3） 指定的某个特定分类。然后我们将该Category对象传给"List"视图来从中生成回复： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step8.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step8.png" width="500" /></a> </p>
<p>在实现我们的List视图时，我们首先将更新我们网页的后台代码，从ViewPage&lt;Category&gt;继承而来，这样页面的ViewData属性将是从我们的控制器传过来的Category对象的类型（<a href="http://blog.joycode.com/scottgu/archive/2007/12/07/112355.aspx" target="_blank"><font color="#087da8">第三部分</font></a>对此有详细讨论）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step9.png" /> </p>
<p>然后我们将象下面这样实现List.aspx： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step10.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step10.png" width="500" /></a> </p>
<p>上面的视图在页面上方显示了分类名称，然后显示了分类内的所有产品的项目列表。 </p>
<p>在项目列表的每个产品旁边，有个 "Edit" 链接。我们是用在<a href="http://blog.joycode.com/scottgu/archive/2007/12/04/112249.aspx" target="_blank"><font color="#087da8">第二部分</font></a>中讨论过的Html.ActionLink辅助方法来显示这些HTML超链接（譬如，&lt;a href="/Products/Edit/4"&gt;Edit&lt;/a&gt;）的，在"Edit"链接被点击后，用户将被导向到"Edit"action方法。然后我们还将使用Html.ActionLink辅助方法在页面底部生成一个&lt;a href="/Products/New"&gt;Add New Product&lt;/a&gt;链接，在该链接被点击后，用户将被导向到"New" action方法。 </p>
<p>当我们访问 /Products/Category/1 URL时，在浏览器中查看源码的话，你会注意到我们的ASP.NET MVC应用输出了非常干净的HTML和URL标识： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step11.png" /> </p>
<h3><u>实现添加新产品（第一部分-背景知识）</u></h3>
<p>现在让我们来实现网站的&#8220;添加新产品&#8221;表单提交功能，最终我们想要用户在访问<em>/Products/New</em> URL时看到象下面这样的显示： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step2.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step2.png" width="500" /></a> </p>
<p>在ASP.NET MVC框架中，表单输入和编辑场景一般是通过在Controller类上呈示2个Action方法来处理的。第一个Controller Action方法负责发送含有要显示的初始表单的HTML。第二个Controller Action方法则负责处理从浏览器发回的任何表单提交。 </p>
<p>例如，对上面的&#8220;添加产品&#8221;屏幕，我们会选择在ProductsController上的2个不同action中来实现：一个叫"New"，另一个叫"Create"。<em>/Products/New</em> URL负责显示一个带有HTML文本框和下拉框控件的空白表单，让用户输入新产品的细节。然后，这个网页上的HTML &lt;form&gt;元素将其action属性设置为 <em>/Products/Create</em> URL。这意味着当用户点击表单提交按钮时，表单的输入将被发送到"Create" action方法上来处理和更新数据库。 </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step12.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step12.png" width="500" /></a> </p>
<h3><u>实现添加新产品（第二部分 - 第一种方法）</u></h3>
<p>下面是我们可以用来实现ProductsController的一个初始实现。</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step13.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step13.png" width="500" /></a> </p>
<p>注意上面，在涉及产品生成过程中，我们有2个action方法， - "New" 和 "Create"。 "New" action方法只是简单地向用户显示一个空白表单。"Create" action方法则处理从表单提交过来的值，根据这些值在数据库中生成一个新产品，然后将客户转向到产品的分类列表网页。 </p>
<p>发送到客户端的HTML表单，是在由"New" action方法调用的"New.aspx"视图里实现的。这个视图的一个初始实现（每个输入都用了文本框）看上去象下面这样： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step14.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step14.png" width="500" /></a> </p>
<p>注意上面，我们在网页上使用了标准的 HTML &lt;form&gt; 元素，而不是form runat=server。表单的"action"属性被设置为ProductsController上的"Create" action方法。在页面底部的&lt;input type="submit"&gt;元素被点击时，提交就会发生，之后，ASP.NET MVC框架就会自动将ProductName, CategoryID, SupplierID 和 UnitPrice值映射为方法参数，传给ProductsController上的 "Create" action方法： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step15.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step15.png" width="500" /></a> </p>
<p>至此，我们运行网站时，就有了最基本的产品输入功能： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step16.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step16.png" width="500" /></a> </p>
<h3><u>实现添加新产品 （第三部分 - 使用HTML辅助方法实现下拉框）</u></h3>
<p>我们在前面一节里创建的产品输入屏幕是可行的，但不是很友好。具体来说，它要求用户知道正输入的产品的原始CategoryID和SupplierID成员。我们需要通过显示内含可读名称的HTML下拉框来修正这个问题。 </p>
<p>第一步，将修改ProductsController来向视图里传人2个集合，一个内含现有的分类列表，另一个内含产品供应商列表。我们将通过生成一个封装这些列表的强类型的ProductsNewViewData类，然后将它传给视图来达成这个目的（你可以在<a href="http://blog.joycode.com/scottgu/archive/2007/12/07/112355.aspx" target="_blank"><font color="#087da8">第三部分</font></a>中了解有关详情）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step17.png" /> </p>
<p>然后我们将更新 "New" action 方法来填充这些集合，然后将它们作为ViewData传给 "New" 视图： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step18.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step18.png" width="500" /></a> </p>
<p>然后在我们的视图里，我们可以使用这些集合来生成 HTML &lt;select&gt; 下拉框。</p>
<p><u>ASP.NET MVC HTML 辅助方法</u></p>
<p>我们可以用来生成下拉框的一个方法是在HTML里手工生成内含 if/else 语句的 &lt;% %&gt; for-循环。这会给与我们对HTML的完全控制，但HTML会很乱。 </p>
<p>一个你可以使用的干净得多的方法是利用ViewPage基类上的"Html"辅助属性。这是个方便对象，呈示了一套HTML辅助界面方法，用于自动化HTML界面的生成。例如，在本帖子的前面，我们使用了 Html.ActionLink辅助方法来生成 &lt;a href=""&gt; 元素： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step19.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step19.png" width="500" /></a> </p>
<p>HtmlHelper对象（以及我们将在以后的教程里讨论的AjaxHelper对象）是特地设计可以通过使用"<a href="http://blog.joycode.com/scottgu/archive/2007/04/07/100611.aspx" target="_blank"><font color="#087da8">扩展方法</font></a>"（VS 2008中VB和C#的一个新语言特性）来轻松地扩展的。这意味着，任何人都可以为这些对象生成他们自己的自定义辅助方法，共享这些方法，为你所用。 </p>
<p>在ASP.NET MVC框架将来的预览版中，我们将提供几十个内置的HTML和AJAX辅助方法。在第一个预览版中，只有"ActionLink"方法是内置于System.Web.Extensions（目前实现核心ASP.NET MVC框架的程序集）中的。但我们还将有一个单独的 "MVCToolkit" 下载，你可以加到你的项目中，来得到你可以在第一个预览版中使用的的几十个辅助方法。 </p>
<p>要安装MVCToolkit HTML辅助方法的话，只要将MVCToolkit.dll程序集添加为你的项目的引用即可： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step21.png" /> </p>
<p>重新编译你的项目，然后下一次你键入 &lt;%= Html. %&gt; 的话，你将看到许许多多你可以使用的额外界面辅助方法： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step20.png" /> </p>
<p>为生成HTML &lt;select&gt;下拉框，我们可以使用Html.Select()方法。每个方法都有重载的版本，在视图里有完整的intellisense： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step22.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step22.png" width="500" /></a> </p>
<p>我们可以更新我们的"New"视图，用下面的代码，使用Html.Select选项来显示使用CategoryID/SupplierID属性作为值，CategoryName/SupplierName作为显示文字的下拉框： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step24.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step24.png" width="500" /></a> </p>
<p>这会在运行时为我们生成适当的&lt;select&gt; HTML标识： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step25.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step25.png" width="500" /></a> </p>
<p>在/Products/New屏幕上给用户一个方便的方式来选择产品分类和供应商： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step23.png" /> </p>
<p>注： 因为我们还是在向服务器提交CategoryID和SupplierID值，所以我们根本不用更新ProductsController的Create Action方法来支持这个新的下拉框界面，这个方法还是工作的。 </p>
<h3><u>实现添加新产品（第四部分 - 使用UpdateFrom方法清理Create代码）</u></h3>
<p>我们的ProductsController的"Create" Action方法负责处理我们的&#8220;添加产品&#8221;场景的表单提交。目前它是以action方法参数的方式来处理进来的表单参数的： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step26.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step26.png" width="500" /></a> </p>
<p>这个方法是可行的，但对于涉及大量值的表单，Action方法的签名就会开始变得有点难读。而且，上面将所有进来的参数值设置到新的Product对象上的代码有点长，而且单调。 </p>
<p>如果你引用了MVCToolkit程序集，你可以利用在System.Web.Mvc.BindingHelpers命名空间下实现的一个有用的扩展方法，来对此代码作些清理。这个扩展方法叫做&#8220;UpdateFrom&#8221;，可以用在任何 .NET 对象上。它接受一个字典作为参数，然后，它会对任何匹配该对象的公开属性的键，自动对本身进行属性赋值。 </p>
<p>例如，我们可以重写我们上面的Create action方法，来使用UpdateFrom方法，象这样：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step27.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step27.png" width="500" /></a>&nbsp;</p>
<p>注： 如果你因为安全的原因，想要更明确些，只允许某些属性可以更新的话，你还可以向UpdateFrom方法传入一个可以更新的属性名称的字符串数组： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step28.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step28.png" width="500" /></a> </p>
<h3><u>实现编辑产品功能（第一部分 - 背景知识）</u></h3>
<p>现在让我们来实现网站&#8220;编辑产品&#8221;的功能。我们最终想要用户在访问<em>/Products/Edit/[ProductID]</em> URL时看到象下面这样的屏幕： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step3.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step3.png" width="500" /></a> </p>
<p>跟上面的&#8220;添加新产品&#8221;表单提交例子一样，我们将使用2个ProductsController Action方法来实现这个表单编辑交互，我们将称这2个方法为"Edit"和"Update"： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step29.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step29.png" width="500" /></a> </p>
<p>"Edit" 会显示产品表单，"Update"会被用来处理表单的提交行动。</p>
<h3><u>实现编辑产品功能（第二部分 - Edit Action）</u></h3>
<p>我们将通过实现ProductController的Edit action方法来开始启用我们应用的编辑功能。当我们在本贴子的开头创建产品列表网页的时候，我们是这么建造的，Edit action将接受一个作为URL一部分的id参数（譬如，/Products/Edit/5）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step31.png" /> </p>
<p>我们想要Edit Action方法从数据库中获取适当的产品对象，以及现有的产品供应商和分类集合（这样，我们可以在我们的编辑视图里实现这些东西对应的下拉框）。我们将使用下面的ProductsEditViewData对象来定义一个强类型的视图对象来代表所有这些数据： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step30.png" /> </p>
<p>然后，我们可以实现我们的Edit action方法来填充这个viewdata对象，在"Edit" 视图中显示： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step32.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step32.png" width="500" /></a> </p>
<h3><u>实现编辑产品功能（第三部分 - Edit 视图）</u></h3>
<p>我们可以使用下述方法来实现Edit.aspx视图网页： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step33.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step33.png" width="500" /></a> </p>
<p>注意我们是如何同时使用上面例子中的Html.TextBox和Html.Select辅助方法来的。这2个方法都是来自MVCToolkit.dll程序集中的扩展方法。 </p>
<p>注意Html.Select辅助方法有个重载版本，允许你指定下拉框中的选定值是什么。在下面的代码片断中，我表示我要Category下拉框根据编辑产品目前的CategoryID值自动选择某一项： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step34.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step34.png" width="500" /></a> </p>
<p>最后，注意我们是如何使用Url.Action()辅助方法来设置&lt;form&gt;元素的action属性的：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step35.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step35.png" width="500" /></a> </p>
<p>Url.Action和Html.ActionLink这2个辅助方法都使用了ASP.NET MVC框架的<a href="http://blog.joycode.com/scottgu/archive/2007/12/04/112249.aspx" target="_blank"><font color="#087da8">路径选择引擎</font></a>来生成URL（参阅<a href="http://blog.joycode.com/scottgu/archive/2007/12/04/112249.aspx" target="_blank"><font color="#087da8">第二部分</font></a>以了解URL生成原理的细节）。这意味着，如果我们改变我们网站的编辑功能的路径选择规则的话，我们<u>不</u>需要改动控制器或视图中的任何代码。例如，我们可以将我们的URL做重新映射，换掉/Products/Edit/1，而是使用象/Products/1/Edit这样更具RESTful的URL的话，上面的控制器和视图代码不用做改动，而依旧会工作。 </p>
<h3><u>实现编辑产品功能（第四部分 - Update Action）</u></h3>
<p>最后一步是实现ProductController类上的"Update" action方法: </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc4/step36.png" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc4/step36.png" width="500" /></a> </p>
<p>跟前面的"Create" action方法一样，我们将利用"UpdateFrom"扩展方法来从请求中自动填充我们的产品对象。但注意，填充的不是一个空对象，我们使用了一个模式，先从数据库中获取老的值，然后对它应用用户做的改动，然后更新到数据库中。 </p>
<p>编译完毕之后，我们重新定向到产品列表网页，自动设置 /Products/Category/[CategoryID]，以匹配我们正在操作的产品的保存的状态。 </p>
<h3><u>结语</u></h3>
<p>希望本帖子提供了在ASP.NET MVC框架中如何处理表单输入和提交场景的一些细节，还提供了你可以如何处理和结构化常见数据输入和编辑场景的一些背景。 </p>
<p><a href="http://www.scottgu.com/blogposts/mvc4/mvcapplication5.zip" target="_blank"><font color="#087da8">点击这里</font></a>下载一个内含我们在上面建造的完整应用源代码的.ZIP 文件。 </p>
<p>在将来的帖子里，我将讨论如何处理表单输入和编辑场景中数据验证和错误复原的情形。我将讨论一些促进快速应用开发的内置的数据和安全支架（scaffolding）。我将讨论你如何在MVC框架中使用ASP.NET AJAX进行启用AJAX的编辑。我还将对如何单元测试控制器和向控制器添加依赖注入做深入的探讨。 </p>
<p>希望本文对你有所帮助，</p>
<p>Scott</p>
<img src ="http://www.blogjava.net/jvict/aggbug/249011.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 22:52 <a href="http://www.blogjava.net/jvict/articles/249011.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转自Scott]ASP.NET MVC框架(第三部分): 把ViewData从控制器传到视图</title><link>http://www.blogjava.net/jvict/articles/249009.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 14:45:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249009.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249009.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249009.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249009.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249009.html</trackback:ping><description><![CDATA[<p>英文原文地址:<font face="Verdana">http://weblogs.asp.net/scottgu/archive/2007/12/06/asp-net-mvc-framework-part-3-passing-viewdata-from-controllers-to-views.aspx</font><br />
翻译原文地址:<font face="Verdana">http://blog.joycode.com/scottgu/archive/2007/12/07/112355.aspx</font><br />
<br />
</p>
<p>过去的几个星期内，我一直在写着讨论我们正在开发的新ASP.NET MVC框架的系列贴子。ASP.NET MVC框架是个你可以用来结构化你的ASP.NET web应用，使之拥有清晰的关注分离，方便你单元测试代码和支持TDD流程的可选方法。 </p>
<p>这个系列的<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一篇</font></a>建造了一个简单的电子商务产品列表/浏览网站。它讨论了MVC后面的高层次的概念，示范了如何从头创建一个新的ASP.NET MVC项目，实现和测试这个电子商务产品列表功能。系列的<a href="http://blog.joycode.com/scottgu/archive/2007/12/04/112249.aspx" target="_blank"><font color="#087da8">第二篇</font></a>对ASP.NET MVC框架的URL路径选择（routing）架构做了深入探讨，讨论了它的工作原理以及你如何使用它来处理更高级的URL路径选择场景。 </p>
<p>在今天的帖子里，我将讨论控制器是如何与视图做交互的，具体来说，我将讨论你可以把数据从控制器传到视图以显示返回到客户端的回复的各种方式。 </p>
<h3><u>第一部分的扼要简述</u></h3>
<p>在这个系列的<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一部分</font></a>，我们创建了一个电子商务网站，实现了基本的产品列表/浏览支持。我们是用ASP.NET MVC框架实现这个网站的，这个方法会很自然地将代码结构化为独特的控制器，模型和视图组件。 </p>
<p>当浏览器向我们的网站发送一个HTTP请求时，ASP.NET MVC框架将使用它的<a href="http://blog.joycode.com/scottgu/archive/2007/12/04/112249.aspx" target="_blank"><font color="#087da8">URL路径选择引擎</font></a>，把进来的请求映射到一个控制器上的action方法来处理它。在基于MVC的应用中的控制器负责处理进来的请求，处理用户输入和交互，执行基于这些输入和交互的应用逻辑（获取或更新存储在数据库中的模型数据等等）。 </p>
<p>到生成返回到客户端的HTML回复的时候，控制器一般是与&#8220;视图&#8221;组件合作，这些视图组件是以独立于控制器的单独的类或模板的形式实现的，其目的是完全注重于封装显示逻辑。 </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step0.jpg" /> </p>
<p>视图<u>不应该</u>含有任何应用逻辑或数据库访问代码，所有的应用/数据逻辑应该由控制器类来处理。这么划分的动机是帮助强制你的应用/数据逻辑与界面生成代码间的清晰分离。同时这也方便你独立于你的界面显示逻辑来单元测试你的应用/数据逻辑。 </p>
<p>视图<u>应该只</u>使用从控制器传过来的特定于视图的数据来生成输出。在ASP.NET MVC框架中，我们称这个特定于视图的数据为&#8220;ViewData&#8221;。这个博客的其他部分将讨论你可以用来将ViewData从控制器传递给视图来生成显示的一些不同方法。 </p>
<h3><u>一个简单的产品列表场景</u></h3>
<p>为帮助说明我们可以用来把ViewData从控制器传递给视图的一些技术，让我们来建造一个简单的产品列表网页： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step1.png" /> </p>
<p>我们将用一个CategoryID整数来过滤我们想要显示在页面上的产品。注意上面我们是如何把CategoryID嵌在URL中的（例如，Products/Category/2 或 /Products/Category/4 ）。 </p>
<p>然后，我们的产品列表网页显示了2个不同的动态内容元素。第一个元素是我们要显示的分类的文本名称（例如，Condiments-调味品），第二个元素是一个HTML &lt;ul&gt;&lt;li/&gt;&lt;/ul&gt; 产品名字列表。我在上面的屏幕截图中对这2个元素用红笔画了圈。 </p>
<p>在下面，我们将看一下我们可以使用的2个不同的方法来实现ProductsController类，这个类处理进来的请求，获取处理请求所需的数据，然后将这个数据传给一个List视图来显示。我们要研究的第一个方法是用后期绑定的字典对象传递这个数据，第二个方法则使用强类型类的方式来传递这个数据。 </p>
<h3><u>方法 1：使用 Controller.ViewData 字典来传递ViewData </u></h3>
<p>Controller基类有个ViewData字典属性，可以用来填充你要传给视图的数据。你使用键/值模式将对象加入 ViewData 字典。 </p>
<p>下面是个ProductsController类，其中的Category action方法实现了我们上面的产品列表场景。注意，它是如何使用分类的ID参数来查询该分类的文本名称，以及获取该分类中的产品列表的。它使用&#8220;CategoryName&#8221;和&#8220;Products&#8221;两个键将这两个数据存储在Controller.ViewData 集合中： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step2.png" />&nbsp; </p>
<p>然后，我们上面的Category action方法调用 <em>RenderView("List")</em> 来表示它要用哪个模板来做显示。当你象这样调用RenderView时，它会将ViewData字典传给视图，以显示对应的回复。 </p>
<p><u>实现我们的视图</u></p>
<p>我们将使用居于我们项目的\Views\Products目录下的List.aspx文件来实现我们的List视图。这个 List.aspx 将继承 \Views\Shared 文件夹中的Site.Master母版页中的布局（在你创建一个新的视图网页时，你可以在 VS 2008 中，右击，选择添加新项-&gt;MVC视图内容网页来接连一个母版页）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step3.png" /> </p>
<p>当我们使用MVC视图内容网页模板来创建List.aspx网页时，它不是从通常的 System.Web.UI.Page 类继承而来，而是从System.Web.Mvc.ViewPage 基类继承而来（是现有的Page类的一个子类）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step4.png" /> </p>
<p>ViewPage基类提供一个ViewData字典属性，我们可以在视图网页里访问由控制器添加的数据对象。然后我们可以取出这些数据对象，使用它们来显示HTML输出，可以用服务器控件的方式，或者用 &lt;%= %&gt; 显示代码的方式。 </p>
<p><u>使用服务器控件来实现我们的视图</u></p>
<p>下面是一个如何使用现有的&lt;asp:literal&gt; 和 &lt;asp:repeater&gt;服务器控件来实现我们的HTML界面的例子： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step5.png" /> </p>
<p>我们可以用下面的后台代码类将 ViewData 绑定到这些控件之上（注意我们是如何使用ViewPage的ViewData字典来实现的 ）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step6.png" /> </p>
<p>注： 因为页面上没有 &lt;form runat="server"&gt;，是不会输出 view-state 的。上面的控件也不会自动生成任何ID值，这意味着你对输出的HTML有完全的控制。 </p>
<p><u>使用 &lt;%= %&gt; 代码来实现我们的视图</u></p>
<p>如果你更喜欢使用行内代码来生成输出的话，你可使用下面的 List.aspx 来实现跟上面完全一样的结果： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step8.png" /> </p>
<p>注： 因为ViewData的类型是含有&#8220;objects&#8221;的字典，为了对它使用foreach语句，我们需要将ViewData["Products"]的类型转换成 List&lt;Product&gt; 或者 IEnumerable&lt;Product&gt;。我在页面上引用了System.Collections.Generic 和 MyStore.Models 命名空间 以避免输入 List&lt;T&gt; 和 Product 类型的完整名称。 </p>
<p>注: 上面使用了&#8220;var&#8221;关键词，这是VS 2008中新的 C# 和 VB &#8220;类型推断&#8221;特性的一个例子（<a href="http://blog.joycode.com/scottgu/archive/2007/05/21/102887.aspx" target="_blank"><font color="#087da8">在这里阅读</font></a>我以前的相关贴子）。因为我们将ViewData["Products"] 转换成了 List&lt;Product&gt;，我们在 List.aspx 文件中的 prduct 变量上得到了完整的intellisense： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step9.png" /> </p>
<h3><u>方法 2：使用强类型类来传递ViewData</u></h3>
<p>除了支持后期绑定的字典方法外，ASP.NET MVC框架还允许你把强类型的ViewData对象从控制器传递给你的视图。使用这个强类型的方法有几个好处： </p>
<ol>
    <li>避免使用字符串来查询对象，得到对你的控制器和视图代码的编译时检查
    <li>避免需要在使用象C#这样的强类型语言中明确转换ViewData对象字典中的值
    <li>在你的视图网页的标识文件以及后台代码文件中得到你的ViewData对象的自动代码intellisense
    <li>可以使用代码重构工具来帮助自动化对整个应用和单元测试代码库的改动 </li>
</ol>
<p>下面是一个强类型的ProductsListViewData类，封装了 List.aspx 视图显示我们的产品列表所需的数据，它含有 CategoryName 和 Products 属性（是通过使用新的C#<a href="http://blog.joycode.com/scottgu/archive/2007/03/11/95954.aspx" target="_blank"><font color="#087da8">自动属性</font></a>支持来实现的）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step23.png" /> </p>
<p>然后我们可以更新我们的 ProductsController 实现来使用这个对象，把一个强类型的ViewData对象传给我们的视图： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step10.png" /> </p>
<p>注意上面，我们是如何通过 RenderView() 方法的一个额外的参数，把我们的强类型 ProductsListViewData 对象传给View的。 </p>
<p><u>把视图的ViewData字典与强类型的ViewData对象一起使用</u></p>
<p>前面我们编写的 List.aspx 视图实现会继续和我们更新过的 ProductsController 协作，不需改动代码。这是因为，当把一个强类型的 ViewData 对象传递给继承自 ViewPage 的视图类时，ViewData 字典会自动使用反射对强类型的对象的属性做查询取值。所以我们象下面这样的视图中的代码： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step11.png" /> </p>
<p>会自动使用反射来从强类型的 ProductsListViewData 对象中获取 CategoryName 属性，这个对象是我们在调用 RenderView 方法时传入的。 </p>
<p><u>使用ViewPage&lt;T&gt;基类来对ViewData强类型化</u></p>
<p>除了支持基于字典的ViewPage基类外，ASP.NET MVC框架中还发布有基于泛型的 ViewPage&lt;T&gt; 实现。如果你的视图是从 ViewPage&lt;T&gt; 继承而来，这里T表示是控制器传给视图的 ViewData 的类型，那么 ViewData 属性就将是使用了这个T类的强类型属性。 </p>
<p>例如，我们可以更新我们的 List.aspx.cs 后台代码类，不是从ViewPage继承来，而是继承自 ViewPage&lt;ProductsListViewData&gt; ： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step12.png" /> </p>
<p>这么做之后，页面上的 ViewData 属性将会从一个字典变成属于 ProductsListViewData 类型。这意味着，我们现在可以不再使用基于字符串的字典来查阅获取数据，而是可以使用强类型的属性了： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step13.png" /> </p>
<p>然后，我们可以使用服务器控件的方法，或者 &lt;%= %&gt; 显示的方法来生成基于这个ViewData的HTML。 </p>
<p><u>使用服务器控件来实现 ViewPage&lt;T&gt;视图<t></t></u></p>
<p>下面是一个例子，我们可以使用&lt;asp:literal&gt; 和 &lt;asp:repeater&gt;服务器控件来实现我们的HTML界面。这是我们使用继承自 ViewPage 的 List.aspx 网页时所使用的完全一样的标识： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step5.png" /> </p>
<p>下面是相应的后台代码。注意，因为我们是从 ViewPage&lt;ProductsListViewData&gt; 继承而来的，我们可以直接访问它的属性，而不要对任何东西做类型转换（什么时候我们决定对其中一个属性改名的话，我们还将得到重构工具的支持）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step14.png" /> </p>
<p><u>使用 &lt;%= %&gt; 代码实现我们的 ViewPage&lt;T&gt; 视图</u></p>
<p>如果你更喜欢使用行内代码来生成输出的话，你可以象下面这样在 List.aspx 中达成跟上面一样的结果：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step15.png" /> </p>
<p>使用 ViewPage&lt;T&gt; 方法，我们现在不再需要对 ViewData 使用字符串查阅了。更重要的是，注意上面，我们不再需要对任何属性做类型转换了，因为它们已经是强类型的。这意味着，我们可以编写 foreach (var product in ViewData.Products) ，而不用对 Products 做类型转换。我们还在循环中的 product 变量上得到了完整的intellisense： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/viewdata/step16.png" /> </p>
<h3><u>结语</u></h3>
<p>希望本贴子提供了关于控制器如何把数据传递给视图以显示返回到客户端的回复的一些细节。你可以使用后期绑定的字典，或者使用强类型的方式来达成这个目的。 </p>
<p>第一次试着建造MVC应用时，你很可能发现把应用控制器的逻辑和生成界面的代码分离开来的概念有点怪。你大概要花上一段专门的时间来多建造些应用，你才会感到习惯，把自己的思路转向到处理一个请求，执行所有的应用逻辑，把建造界面回复所需的 viewdata 包装起来，然后交给单独的一个视图页面去显示的观念上去。 <em>重要事项：如果这个模型对你来说并不感觉舒服，那么别用它，MVC的方法纯粹是可选的，我们并不认为这是每个人都想要用的东西。</em> </p>
<p>但这个划分应用的好处以及其后的目标在于，它允许你独立于你的界面显示代码，来运行和测试你的应用和数据逻辑。这极大地方便你为你的应用开发全面的单元测试，以及在建造应用时使用TDD（测试驱动开发）的流程。在以后的贴子里，我会对此做更深入的讨论，以及讨论你可以用来轻松测试代码的最佳实践。 </p>
<p>希望本文对你有所帮助，</p>
<p>Scott</p>
<img src ="http://www.blogjava.net/jvict/aggbug/249009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 22:45 <a href="http://www.blogjava.net/jvict/articles/249009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> [转自scott]ASP.NET MVC框架 (第二部分): URL路径选择</title><link>http://www.blogjava.net/jvict/articles/249008.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 14:44:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249008.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249008.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249008.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249008.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249008.html</trackback:ping><description><![CDATA[英文原文地址:<font face="Verdana">http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx</font><br />
翻译原文地址:<font face="Verdana">http://blog.joycode.com/scottgu/archive/2007/12/04/112249.aspx</font><br />
<br />
<p>上个月，我发表了我要撰写的系列贴子中的<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一篇</font></a>，这些帖子将讨论我们正在开发的新ASP.NET MVC框架。这个系列的<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一个贴子</font></a>建造了一个简单的电子商务产品列表/浏览场景,讨论了MVC后面的高层次的概念，示范了如何从头创建一个新ASP.NET MVC 项目，实现和测试电子商务产品列表的功能。 </p>
<p>在今天的贴子里，我将深入讨论ASP.NET MVC框架的路径选择（routing）架构，讨论一些很酷的定制方式，你可以将其用于你应用中的一些更高级的场景。</p>
<h3><u>第一部分的扼要简述</u></h3>
<p>在这个系列的<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一部分</font></a>里，我们创建了一个电子商务网站，呈示了三类URL: </p>
<table cellspacing="0" cellpadding="2" width="650" border="1">
    <tbody>
        <tr>
            <td valign="top" width="177"><strong>URL格式</strong></td>
            <td valign="top" width="245"><strong>行为</strong></td>
            <td valign="top" width="225"><strong>URL例子</strong></td>
        </tr>
        <tr>
            <td valign="top" width="179">/Products/Categories</td>
            <td valign="top" width="245">浏览所有的产品分类</td>
            <td valign="top" width="225">/Products/Categories</td>
        </tr>
        <tr>
            <td valign="top" width="182">/Products/List/<em>Category</em></td>
            <td valign="top" width="245">列出一个分类中的产品</td>
            <td valign="top" width="225">/Products/List/Beverages</td>
        </tr>
        <tr>
            <td valign="top" width="184">/Products/Detail/<em>ProductID</em></td>
            <td valign="top" width="245">显示一个特定产品的细节</td>
            <td valign="top" width="225">/Products/Detail/34</td>
        </tr>
    </tbody>
</table>
<p>我们通过创建象下面这样一个ProductsController类来处理这些URL：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step11.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step11.jpg" width="500" /></a> </p>
<p>在把上面这个类加到我们的应用中后，ASP.NET MVC框架就会把进来的URL自动导向到我们的控制器上的适当的action方法来处理请求。 </p>
<p>在今天的贴子里，我们将深入讨论这个URL映射是如何发生的，以及探讨我们可以在ASP.NET MVC框架中利用的更高级的路径选择（routing）场景。我还将示范你如何可以轻松地单元测试URL路径选择场景。 </p>
<h3><u>ASP.NET MVC URL路径选择系统都做些什么？</u></h3>
<p>ASP.NET MVC框架包括了一个很灵活的URL路径选择系统，它允许你在应用中定义URL映射规则。路径选择系统有2个主要目的：</p>
<ol>
    <li>把进来的URL映射到应用，并把它们做导向，这样，正确的Controller和Action方法执行来处理这些请求
    <li>构建可以用来回调Controllers/Actions的输出到客户端的URL（例如，表单提交， &lt;a href=""&gt; 链接, 和 AJAX 调用等等） </li>
</ol>
<p>能够使用URL映射规则来同时处理进来的和输出的URL场景给应用代码添加了许多灵活性。这意味着，如果我们以后想改变应用的URL结构的话（譬如，把 /Products 改名为 /Catalog），我们可以修改应用层次的一套映射规则即可，而不需要改动控制器或视图模板中的<em>任何</em>代码。 </p>
<h3><u>默认的ASP.NET MVC URL路径选择规则</u></h3>
<p>在默认情形下，当你使用Visual Studio用ASP.NET MVC Web Application模板来创建一个新项目时，它会往项目里添加一个ASP.NET Application类。这是在Global.asax后台代码中实现的： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step1.jpg" /> </p>
<p>ASP.NET Application类允许开发人员处理应用启动/中止以及全局性的错误处理的逻辑。 </p>
<p>默认的ASP.NET MVC项目模板自动向该类添加一个Application_Start方法，在其中注册2条URL路径选择规则： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step2.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step2.jpg" width="500" /></a> </p>
<p>上面的第一条路径选择规则表示，ASP.NET MVC框架在默认情形下，在决定用哪个Controller类来生成实例，调用哪个Action方法时（以及哪些需要传入的参数时），应该使用"[controller]/[action]/[id]"的格式把URL映射到控制器上。 </p>
<p>这个默认的路径选择规则就是为什么<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一部分</font></a>中我们的电子商务浏览例程中对URL /Products/Detail/3 的请求自动调用我们的ProductsController类的Detail方法，并且传入3作为id参数值的原因： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step10.jpg" /> </p>
<p>上面的第二条路径选择规则，是用来对我们应用的根URL"Default.aspx"做特例处理的（当处理一个应用的根URL的请求时，这个URL有时会被服务器代替"/"来传入）。这个规则确保对我们应用的根"/Default.aspx"或"/"的请求，都会由HomeController类（是在我们使用ASP.NET MVC Web Application项目模板生成一个新的应用时，由Visual Studio自动生成的控制器）里的Index() action方法处理。 </p>
<h3><u>理解Route实例</u></h3>
<p>路径选择规则是通过向System.Web.Mvc.RouteTable的Routes集合添加Route实例来注册的。</p>
<p>Route类定义了许多你可以用以配置映射规则的属性。你可以通过&#8220;传统的&#8221; .NET 2.0属性赋值的方式来设置这些属性： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step4.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step4.jpg" width="500" /></a> </p>
<p>或者利用VS 2008的C#和VB编译器中的新的<a href="http://blog.joycode.com/scottgu/archive/2007/03/11/95954.aspx" target="_blank"><font color="#087da8">对象初始化器</font></a>特性，更简洁地设置属性： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step3.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step3.jpg" width="500" /></a>&nbsp;</p>
<p>Route类的Url属性定义了应该用来评估一个路径选择规则是否适用于进来的特定请求的Url匹配规则。它还定义了URL应该如何分割成（tokenized）不同的参数。URL中可替换的参数，是通过 [参数名称] 的句法来定义的。就象在后文论及的那样，我们并不限制于一套固定的&#8220;熟知&#8221;参数名称，你可以在URL使用任何数目的任意参数。例如，我可以使用一个"/Blogs/[Username]/Archive/[Year]/[Month]/[Day]/[Title]"的URL规则把进来的一个博客贴子的URL进行分割，由MVC框架自动分析成UserName，Year，Month，Day 和 Title参数，并把它们传入我的控制器的action方法中。 </p>
<p>Route类上的Defaults属性定义了一个默认值的字典，可以在进来的URL并不包含某个指定的参数值的情形下使用。例如，在上面的URL映射例子中，我们定义了2个默认URL参数值，一个是"[action]" ，另一个是 "[id]"。这意味着，如果应用收到的是 /Products/ 这个URL，在默认情形下，路径选择系统会默认使用&#8220;Index&#8221;作为ProductsController的action的名称来执行。同样地，如果指定了/Products/List/ ，那么就会使用null字符串作为"ID"参数的值。 </p>
<p>Route类的RouteHandler属性定义了在URL被分割成参数，适当的路径选择规则被确定之后，应该用来处理请求的 IRouteHandler 实例。在上面的例子中，我们表示，我们想要使用System.Web.Mvc.MvcRounteHandler类来处理我们配置好的URL。这个额外的步骤存在的原因是，我们想确保URL路径选择系统可以同时用于MVC和非MVC请求的情形。有这个IRouteHandler接口，意味着，我们也能够干净地用于非MVC的请求（例如标准的WebForms，Astoria REST支持等等）。 </p>
<p>Route类还有一个Validation属性，在本文的稍后我们会做讨论。这个属性允许我们指定一个路径选择规则匹配需要满足的先决条件。例如，我们可以指定一个路径选择规则应该只适用于一个特定的HTTP动词（允许我们轻松地映射REST命令），或者我们可以对参数值使用正则表达式，来过滤一个路径选择规则是否匹配。 </p>
<p><em>注：在MVC框架的第一个公开预览版中，Route类是不可以扩展的（它只是个数据类），在下一个预览版中，我们正在研究把它做成可扩展的，允许开发人员添加特定场景的路径类（譬如，一个RestRoute子类）来干净利索地添加新的语义和功能。 </em></p>
<h3><u>路径规则的评估</u></h3>
<p>当一个进来的URL被ASP.NET MVC Web应用收到时， MVC框架会对RouteTable.Routes集合中的路径选择规则进行评估，以决定适当的Controller来处理该请求。 </p>
<p>MVC框架是按RouteTable规则注册的次序做评估来选择使用哪个Controller的。将进来的URL对每条Route规则做检测，看它是否匹配，如果一个Route规则匹配的话，那么该规则（以及相关联的RouteHandler）将被用来处理进来的请求（所有后面的规则都略过不计）。这意味着你一般要按&#8220;最特殊到最不特殊（most specific to least specific，从特殊到一般）&#8221;的次序来组织你的路径选择规则。 </p>
<h3><u>路径选择场景：自定义查询URL</u></h3>
<p>让我们使用一下现实场景中的自定义路径选择规则来对此做一流程示范，以实现我们的电子商务网站的查询功能为例。 </p>
<p>开始，我们往我们项目中添加一个新的SearchController类：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step5.jpg" /> </p>
<p>然后，我们在SearchController类中定义2个Action方法。Index()方法用来显示一个查询网页，上有一个文本框，让用户来输入和提交查询文字。Results() action方法则用来处理相应的表单提交，对数据库做查询，然后把结果显示给用户： </p>
<p>&nbsp;<img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step6.jpg" /> </p>
<p>使用默认的<em>/[controller]/[action]/[id]</em> URL路径映射规则，我们可以现成使用象下面这样的URL来调用我们的SearchController的行为： </p>
<table cellspacing="0" cellpadding="2" width="562" border="1">
    <tbody>
        <tr>
            <td valign="top" width="132"><strong>场景</strong></td>
            <td valign="top" width="236"><strong>URL</strong></td>
            <td valign="top" width="190"><strong>Action方法</strong></td>
        </tr>
        <tr>
            <td valign="top" width="134">查询表单： </td>
            <td valign="top" width="236">/Search/</td>
            <td valign="top" width="190">Index</td>
        </tr>
        <tr>
            <td valign="top" width="135">查询结果： </td>
            <td valign="top" width="236">/Search/Results?query=Beverages</td>
            <td valign="top" width="190">Results</td>
        </tr>
        <tr>
            <td valign="top" width="136">&nbsp;</td>
            <td valign="top" width="236">/Search/Results?query=ASP.NET</td>
            <td valign="top" width="190">Results</td>
        </tr>
    </tbody>
</table>
<p>注意，根URL /Search 默认映射到Index() action方法的原因是因为在Visual Studio创建一个新项目时，默认添加的 /[controller]/[action]/[id] 的路径定义将默认的action自动设置到&#8220;Index"上的（通过Defaults属性）： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step3.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step3.jpg" width="500" /></a> </p>
<p>虽然象 <em>/Search/Results?query=Beverages</em> 这样的URL是完全可行的，我们也许决定对查询结果我们想要稍微好看些的URL。具体来说，我们也许想去掉URL中的&#8220;Results&#8221;action名称，把要查询的文字作为URL的一部分传入，而不是作为URL的查询字符串的值。例如： </p>
<table cellspacing="0" cellpadding="2" width="560" border="1">
    <tbody>
        <tr>
            <td valign="top" width="132"><strong>场景</strong></td>
            <td valign="top" width="236"><strong>URL</strong></td>
            <td valign="top" width="190"><strong>Action方法</strong></td>
        </tr>
        <tr>
            <td valign="top" width="134">查询表单： </td>
            <td valign="top" width="236">/Search/</td>
            <td valign="top" width="190">Index</td>
        </tr>
        <tr>
            <td valign="top" width="135">查询结果： </td>
            <td valign="top" width="236">/Search/Beverages</td>
            <td valign="top" width="190">Results</td>
        </tr>
        <tr>
            <td valign="top" width="136">&nbsp;</td>
            <td valign="top" width="236">/Search/ASP.NET</td>
            <td valign="top" width="190">Results</td>
        </tr>
    </tbody>
</table>
<p>我们可以通过在默认的 /[controller]/[action]/[id] 规则<em><u>之前</u></em>添加2条自定义的URL路径映射规则来启用这些比较好看的查询结果URL，象下面这样： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step7.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step7.jpg" width="500" /></a> </p>
<p>在前2条规则中，我们现在明确地指定了对应 /Search/ URL的控制器和Action参数。我们表明，"/Search" 应该总是由SearchController上的&#8220;Index&#8221; action来处理。而任何拥有子URL层次结构的URL （/Search/Foo, /Search/Bar等等 ）则总是由SearchController上的 "Results" action 来处理。 </p>
<p>上面的第二条路径选择规则表明，在 /Search/ 前缀之后的任何字符应该当作名为"[query]"的参数来处理，这个参数将作为方法参数来传入SearchController上的Results action方法中： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step8.jpg" /> </p>
<p>最有可能的，我们还会对查询结果启用分页（我们每次只显示10个查询结果）显示。我们可以通过查询字符串值的方法来实现（譬如，/Search/Beverages?page=2），或者我们也可以把页号嵌在URL中（譬如/Search/Beverages/2）。要支持后面这个做法的话，我们需要做的是，给我们的第二条路径选择规则再加一个额外的可省参数： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step9.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step9.jpg" width="500" /></a> </p>
<p>注意，上面的新URL规则现在匹配的是&#8220;Search/[query]/[page]"。我们还将默认的页号配置为1，万一页号没有包含在URL之中的话（这是通过作为&#8220;Defaults&#8221;属性值的<a href="http://blog.joycode.com/scottgu/archive/2007/05/21/102887.aspx" target="_blank"><font color="#087da8">匿名类型</font></a>传入的）。 </p>
<p>然后我们可以把我们的SearchController.Results action方法更新为接受页号参数作为一个方法参数： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step10.jpg" />&nbsp;</p>
<p>这样，我们就有比较好看的查询URL了（剩下的就是实现这个查询算法，我将把它作为练习留给读者来完成 &lt;g&gt;）。 </p>
<h3><u>路径选择规则的验证先决条件</u></h3>
<p>就象我在这个贴子前面提到的，Route类有个Validation属性，允许你添加为使路径选择规则匹配，必须为真的验证先决条件规则（除了URL过滤外）。ASP.NET MVC框架允许你使用正则表达式来验证URL中的参数值，也允许你对HTTP Headers进行评估（根据HTTP动词的不同进行不同的URL路径选择）。 </p>
<p>下面是一个我们可以用到象 /Products/Detail/43 这样的URL身上的自定义的验证规则，它指定了其中的ID参数必须是数字（不允许字符串），而且它的长度必须在1到8之间： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step11.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step11.jpg" width="500" /></a> </p>
<p>如果我们往应用中传入象 /Products/Detail/12 这样的URL,上面的路径选择规则是合法的，但如果传入 /Products/Detail/abc 或 /Products/Detail/23232323232，它就不会匹配。 </p>
<h3><u>从路径选择系统构建输出的URL</u></h3>
<p>在本文的前面，我说过ASP.NET MVC框架中的URL路径选择系统负责两件事情：</p>
<ol>
    <li>把进来的URL映射到处理的Controllers/Actions上
    <li>帮着构建可以在以后用来回调Controllers/Actions的输出到客户端的URL（例如，表单提交， &lt;a href=""&gt;链接, 和 AJAX 调用等等） </li>
</ol>
<p>URL路径选择系统有不少辅助方法和类，方便你在运行时动态查看和构建URL（你也可以直接对RouteTable的Route集合进行操作来查看URL）。 </p>
<p><u>Html.ActionLink</u></p>
<p>在本博客系列的<a href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx" target="_blank"><font color="#087da8">第一部分</font></a>，我简单地讨论了Html.ActionLink()视图辅助方法。它可以在视图里使用，允许你动态地生成 &lt;a href=""&gt; 超链接。比较酷的是，它可以使用MVC路径选择系统里定义的URL映射规则来生成这些URL。例如，下面2个Html.ActionLink 调用： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step12.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step12.jpg" width="500" /></a> </p>
<p>automatically pick up the special Search results route rule we configured earlier in this post, and the "href" attribute they generate automatically reflect this: 会自动地使用我们在本贴子前面配置的的特殊查询结果路径规则，它们自动生成的href属性反映了这个情况： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step13.jpg" /> </p>
<p>特别地，注意上面，Html.ActionLink的第二个调用自动地把page参数映射成URL的一部分（也注意，第一个调用省略了page参数值，因为它知道服务器端会自动提供默认值）。 </p>
<p><u>Url.Action</u></p>
<p>除了使用Html.ActionLink外，ASP.NET MVC还有个Url.Action()视图辅助方法。该方法生成原生的字符串URL，然后你可以任何方式来使用它们。例如，下面的代码片段： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step14.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step14.jpg" width="500" /></a> </p>
<p>会使用URL路径选择系统返回下面这个原生的URL（而不是包装在 &lt;a href=""&gt; 元素里）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step15.jpg" /> </p>
<p><u>Controller.RedirectToAction</u></p>
<p>ASP.NET MVC还提供了Controller.RedirectToAction()辅助方法，你可以在控制器里使用来进行转向操作（URL是使用URL路径选择系统计算出来的）。 </p>
<p>例如，当在控制器里调用下面代码时： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step16.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step16.jpg" width="500" /></a>&nbsp;</p>
<p>在内部，它会生成一个对Response.Redirect("/Search/Beverages")的调用。</p>
<p><u>DRY （别重复自己）</u></p>
<p>上述所有的辅助方法的好处在于它们允许我们避免在我们的控制器和视图逻辑中硬写URL。如果在后来我们决定改变查询URL路径映射规则，从"/Search/[query]/[page]" 改回到 "/Search/Results/[query]/[page]" 或者 "/Search/Results?query=[query]&amp;page=[page]" ，我们只要在一个地方（我们的路径注册代码中）做编辑，就可以轻松搞定。我们不需要改动视图或控制器中的任何代码，就可以捡起新的URL（这就坚持了<a href="http://en.wikipedia.org/wiki/Don't_repeat_yourself" target="_blank"><font color="#087da8">&#8220;DRY原则&#8221;</font></a>）。 </p>
<h3><u>使用Lambda表达式从路径选择系统构建输出的URL</u></h3>
<p>前面的URL辅助方法例子使用了VS 2008中VB和C#现在支持的新的<a href="http://blog.joycode.com/scottgu/archive/2007/05/21/102887.aspx" target="_blank"><font color="#087da8">匿名类型</font></a>。在上面的例子中，我们使用了匿名类型来有效地传入一串名称/数值对，用以帮助映射URL（你可以把这想像为<a href="http://weblogs.asp.net/leftslipper/archive/2007/09/24/using-c-3-0-anonymous-types-as-dictionaries.aspx" target="_blank"><font color="#087da8">生成字典的一个比较干净的方式</font></a>）。 </p>
<p>除了使用匿名类型以动态方式传递参数外， ASP.NET MVC框架还支持使用强类型机制创建action路径的能力，这些强类型机制为URL辅助方法提供了编译时检查和intellisense。这是通过使用泛型和新的VB和C#对Lambda表达式的支持来实现的。 </p>
<p>例如，下面这个匿名类型 ActionLink 调用：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step17.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step17.jpg" width="500" /></a> </p>
<p>也可以写成：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step18.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step18.jpg" width="500" /></a> </p>
<p>除了写起来简短外，这第二个选项还有类型安全的好处，这意味着你得到对表达式的编译时检查以及Visual Studio的代码intellisense（你还可以使用重构工具对它进行重构）： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step19.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step19.jpg" width="500" /></a> </p>
<p>注意上面，我们是如何使用intellisense挑选出我们想用的SearchController的Action方法的，以及参数是强类型的。生成的URL都是由ASP.NET MVC URL路经选择系统驱动的。 </p>
<p>你也许在想，这到底是怎么回事呢？如果你还记得，8个月前，我在博客里讨论<a href="http://blog.joycode.com/scottgu/archive/2007/04/09/100744.aspx" target="_blank"><font color="#087da8">Lambda表达式</font></a>时，我谈到了Lambda表达式既可以编译出成代码代理（delegate），也可以编译成表达式树对象，然后在运行时可以用来分析Lambda表达式。对于Html.ActionLink&lt;T&gt; 辅助方法，我们使用这个表达式树选项，然后在运行时分析对应的lambda，查出它调用的action方法以及相关的参数类型，在表达式中指定的名称和值等。然后我们可以在MVC URL路径选择系统中使用这些信息， 返回合适的URL和相关联的HTML。 </p>
<p><u>重要注意事项</u>: 当使用这Lambda表达式方法时，我们实际上从不运行对应的Controller action方法。例如，下面的代码<em>并不</em>调用我们的SearchController中"Results" action方法： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step18.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step18.jpg" width="500" /></a></p>
<p>实际上，它只是返回这个HTML超链接：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step20.jpg" /> </p>
<p>如果这个超链接被用户点击的话，它会向服务器发回一个请求，该请求会调用SearchController的Results action方法。 </p>
<h3><u>单元测试路径</u></h3>
<p>ASP.NET MVC框架的一个核心设计原则是促进很好的测试支持。 跟MVC框架的其他部分一样，你可以轻松地单元测试路径和路径匹配规则。MVC路径选择系统可以独立于ASP.NET生成实例和运行，这意味着你可以在任何单元测试库里装载和单元测试路径模式（而不用启动web服务器），可以使用任何单元测试框架（NUnit, MBUnit, MSTest等等）。 </p>
<p>虽然你可以在你的单元测试中直接单元测试一个ASP.NET MVC应用的全局RouteTable映射集合，但一般来说，让单元测试改变或者依赖于一个全局的状态不是一个很好的主意。一个你可以使用的较好的模式是，把你的路径注册逻辑放在一个象下面这样的RegisterRoutes()辅助方法中，对作为参数传入的RouteCollection进行操作（注：我们也许会把这个模式在下个预览版更新中做成默认的VS模板模式）： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step21.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step21.jpg" width="500" /></a> </p>
<p>然后，你可以编写单元测试，创建自己的RouteCollection实例，调用Application的RegisterRoutes辅助方法，在其中注册应用的路径选择规则。然后，你可以向应用发出模拟请求，核实这些请求确有注册了的正确的控制器和action方法，而不用担心任何副作用： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvcrouting/step22.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvcrouting/step22.jpg" width="500" /></a> </p>
<h3><u>结语</u></h3>
<p>希望这个贴子提供了关于ASP.NET MVC路径选择架构工作原理的一些细节，以及你如何可以使用它来定制发布在你的ASP.NET MVC应用中的URL的结构和布局。 </p>
<p>在默认情形下，在你创建一个新的ASP.NET MVC Web应用时，它会预先定义一个你可以使用的默认的 /[controller]/[action]/[id] 路径选择规则，而不必手工配置或启用什么。这应该允许你不用注册你自己的自定义路径选择规则，就可以建造许多应用。但希望上面的内容示范了，如果你想对你自己的URL格式做自定义结构的话，做起来并不难， MVC框架对此提供了许多的功能和灵活性。</p>
<p>希望本文对你有所帮助，</p>
<p>Scott</p>
<img src ="http://www.blogjava.net/jvict/aggbug/249008.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 22:44 <a href="http://www.blogjava.net/jvict/articles/249008.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> [转自Scott]ASP.NET MVC框架（第一部分）</title><link>http://www.blogjava.net/jvict/articles/249007.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 29 Dec 2008 14:42:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/249007.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/249007.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/249007.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/249007.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/249007.html</trackback:ping><description><![CDATA[英文原文地址:<font face="Verdana">http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx</font><br />
翻译原文地址:<font face="Verdana">http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx</font><br />
<a id="ctl00_MainContent_ViewPost1_TitleUrl" title="Title of this entry." href="http://blog.joycode.com/scottgu/archive/2007/11/14/111385.aspx"><br />
</a>
<p>两个星期前， <a href="http://blog.joycode.com/scottgu/archive/2007/10/15/109399.aspx" target="_blank"><font color="#087da8">我在博客里讨论了ASP.NET的一个新MVC（模型、视图，控制器）框架</font></a>，我们将在不久的将来作为一个可选功能来支持。该框架提供了一个结构化的模型，来加强应用中的清晰关注分离，方便你单元测试代码和支持TDD流程。它还提供了对你在应用中发布的URL的更多的控制，也可以对从中输出的HTML提供更多的控制。 </p>
<p>之后，我回答了来自迫切想了解更多详情的很多人的很多问题。鉴于如此高的兴趣，我觉得，写几个贴子更详细地描述如何使用这个框架，也许更有意义些。这是我将在以后几个星期里要撰写的相关贴子的第一个。</p>
<h3><u>一个简单的电子商务店面应用</u></h3>
<p>我将使用一个简单的电子商务商店应用来示范ASP.NET MVC框架的工作原理。在今天的贴子里，我将实现一个产品列单，以及相关的浏览应用场景。</p>
<p>具体来说，我们将建造一个网上商店，允许用户在访问该网站上的<em>/Products/Categories</em>网址时 浏览产品分类列表： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step4.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step4.jpg" width="500" /></a> </p>
<p>当用户点击上面网页上的产品分类链接时，他们将转到一个产品分类列表URL <em>/Products/List/CategoryName</em>上，该页面列出了指定分类中的还在销售的产品： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step5.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step5.jpg" width="500" /></a> </p>
<p>当用户点击个别的产品时，他们将转到产品细节URL <em>/Products/Detail/ProductID</em>上，这个网页将显示用户选定的产品的更多细节： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step6.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step6.jpg" width="500" /></a> </p>
<p>我们将使用新的ASP.NET MVC框架来实现上述的所有功能。这将会允许我们在应用的不同组件间保持&#8220;清晰的关注分离&#8221;，允许我们更轻易地集成单元测试和测试驱动的开发。</p>
<h3><u>创建一个新的ASP.NET MVC应用</u></h3>
<p>ASP.NET MVC框架包含一个Visual Studio项目模板，方便你创建新的MVC web应用。选择文件-&gt;新项目菜单，选择&#8220;ASP.NET MVC Web 应用&#8221;模板，用它创建一个新web应用。</p>
<p>在默认情形下，当你使用该选项生成一个新应用时，Visual Studio 将为你创建一个新的解决方案，然后往里面加2个项目。第一个项目是web项目，在其中你实现你的web应用的功能。第二个项目是个测试项目，你可以在其中编写单元测试，来测试你的应用代码：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step1.jpg" /> </p>
<p>你可以在ASP.NET MVC 框架中使用任何单元测试框架，包括NUnit, MBUnit, MSTest, XUnit以及其他的框架。VS 2008专业版现在包含了对MSTest的内置测试项目的支持（VS 2005版本的MSTest要求你拥有Visual Studio Team System版本才能使用），当你使用VS 2008时，默认的ASP.NET MVC 项目模块自动生成这样的测试项目。</p>
<p>我们还将发布可用以NUnit, MBUnit 和其他单元测试框架的项目模板，所以，如果你更喜欢那些框架的话，你可以轻松地一次点击即生成你的应用和可以马上使用的相应的测试项目。</p>
<h3><u>理解项目的目录结构</u></h3>
<p>ASP.NET MVC 应用的默认目录结构有三个顶层目录：</p>
<ul>
    <li>/Controllers
    <li>/Models
    <li>/Views </li>
</ul>
<p>你大概可以猜出来，我们建议把控制器类置于 /Controllers 目录之中，你的数据模型类置于/Models目录之中，你的视图模板置于 /Views 目录之中。</p>
<p>虽然ASP.NET MVC框架并不强迫你总是使用这个结构，但默认的项目模板使用这个模式，我们也把它作为结构化应用的一种比较容易的方式向你推荐。除非你有好的理由使用另外的文件布局，我建议你使用这个默认模式。</p>
<h3><u>把URL映射到Controller类</u></h3>
<p>在大多数web框架（ASP, PHP, JSP, ASP.NET WebForms等等）里，到来的URL一般都映射到保存在硬盘上的模板文件。譬如，"/Products.aspx"或者"/Products.php" URL一般都在硬盘上有个对应的Products.aspx 或Products.php 模板文件来处理请求。当一个web应用的http请求进入web服务器时，web框架运行由硬盘上的模板文件指定的代码，然后这代码负责处理该请求。很多时候，这代码使用Products.aspx 或 Products.php文件中的HTML 标识来帮助生成返回客户端的响应。 </p>
<p>MVC框架一般以不同的方式把URL映射到服务器代码上。它不是将URL映射到硬盘上的模板文件，而是直接把URL映射到代码类上。这些类称为&#8220;Controllers（控制器）&#8221;，它们负责处理到来的请求，处理用户输入和交互，执行基于输入和交互的相应的应用和数据逻辑。然后，一个Controller类一般会调用单独的&#8220;视图&#8221;组件，该组件负责生成请求的实际的HTML输出。 </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step0.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step0.jpg" width="500" /></a> </p>
<p>ASP.NET MVC框架包括一个非常强大的URL映射引擎，在如何把URL映射到Controller类方面，该引擎提供了很多灵活性。你可以使用它来轻松地设置routing（路径选择，路由）规则，然后ASP.NET会根据这些规则，对进来的URL进行评估，选出一个Controller来运行。然后你也可以让routing引擎自动分析出你在URL里定义的变量，让ASP.NET自动把这些变量作为参数传给你的Controller。我将在这个系列将来的一个贴子里，讨论涉及URL routing引擎的比较高级的场景。 </p>
<h3><u>映射到控制器类的默认ASP.NET MVC URL Routing规则</u></h3>
<p>在默认情形下，ASP.NET MVC项目有一套预先配置好的URL routing规则，这些规则允许你不用配置什么，就可以轻松地上路。这样，使用一套默认的基于名称的URL映射约定，你就可以开始编写代码了，这些约定是在Global.asax文件（由Visual Studio中新的ASP.NET MVC项目模板生成的）中的ASP.NET Application类中声明的。 </p>
<p>默认的命名约定是这样的：把进来的HTTP请求的URL路径的开头部分，譬如 /Products/，映射到一个类，该类的名称遵循<em>UrlPath</em>Controller的模式，譬如在默认情形下，一个以/Products/开头的URL 会被映射到名为<em>Products</em>Controller的类上。 </p>
<p>为建造我们的电子商务产品浏览功能，我们将在我们的项目中加一个新的&#8220;ProductsController&#8221;类 （你可以使用Visual Studio中的&#8220;添加新项&#8221;菜单从模板中轻松地创建一个Controller类）： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step3.jpg" /> </p>
<p>我们的ProductsController是从System.Web.MVC.Controller 基类继承而来，从这个基类继承而来并不是必需的，但它含有一些我们以后可以使用的非常有用的辅助方法和功能： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step2.jpg" /> </p>
<p>在项目中定义这个ProductsController类之后，在默认情形下，ASP.NET MVC 框架就会使用它来处理所有到来的以"/Products/"开头的URL的应用请求。这意味着，它会自动被调用来处理我们将在我们的网上商店应用中开启的"/Products/Categories", "/Products/List/Beverages", 和 "/Products/Detail/3" 等URL。</p>
<p>在将来的贴子里，我们还将添加一个ShoppingCartController（以允许用户管理他们的购物车）以及 AccountController （允许用户在网站上创建新的成员帐号，实现登录和退出等功能）。在向我们的项目里添加这2个新的控制器类之后，以/ShoppingCart/ 和 /Account/开头的URL就会自动地导向到这些类做处理。 </p>
<p><em>注：ASP.NET MVC框架并不要求你总是使用这个命名约定模式。我们的应用默认使用这个模式的唯一原因是因为在我们使用Visual Studio创建新的ASP.NET MVC项目时，有一个配置了这个模式的映射规则被自动地添加到了我们的ASP.NET Application 类中。如果你不喜欢这个规则，或者想使用另外的URL映射模式来对它进行定制，那么就到Global.asax中的ASP.NET Application类中做改动。我会在以后的一个贴子讨论该怎么做，到时我也会展示一些URL routing引擎允许的一些非常酷的场景。</em></p>
<h3><u>理解控制器的Action方法</u></h3>
<p>既然我们已经在项目里创建了一个ProductsController类，我们可以开始添加逻辑来处理来到应用的"/Products/" URL了。 </p>
<p>在本贴子的前面定义我们的电子商务店面用例时，我说过我们将在网站上实现3个场景：1) 浏览所有的产品分类, 2) 列出特定分类里的产品, 和 3) 显示特定产品的细节。我们将使用下列这些SEO友好的URL来处理这三个场景： </p>
<table cellspacing="0" cellpadding="2" width="680" border="1" unselectable="on">
    <tbody>
        <tr>
            <td valign="top" width="211"><strong>URL格式</strong></td>
            <td valign="top" width="241"><strong>行为</strong></td>
            <td valign="top" width="224"><strong>URL例子</strong></td>
        </tr>
        <tr>
            <td valign="top" width="212">/Products/Categories</td>
            <td valign="top" width="241">浏览所有的产品分类</td>
            <td valign="top" width="224">/Products/Categories</td>
        </tr>
        <tr>
            <td valign="top" width="213">/Products/List/<em>Category</em></td>
            <td valign="top" width="241">列出特定分类里的产品</td>
            <td valign="top" width="224">/Products/List/Beverages</td>
        </tr>
        <tr>
            <td valign="top" width="214">/Products/Detail/<em>ProductID</em></td>
            <td valign="top" width="241">显示特定产品的细节</td>
            <td valign="top" width="224">/Products/Detail/34</td>
        </tr>
    </tbody>
</table>
<p>我们可以用几种方式在ProductsController类中编写代码来处理这三类到来的URL。一种方式是，覆盖Controller基类中的&#8220;Execute&#8221;方法，手工编写我们自己的 if/else/切换逻辑，对照用户请求的URL，然后执行适当的逻辑来处理这个请求。 </p>
<p>但一种容易得多的方式是，使用MVC框架中内置的功能，该功能允许我们在我们的控制器中定义&#8220;action方法&#8221;，然后由Controller基类根据我们应用使用的URL routing规则来自动调用适当的action方法来执行。</p>
<p>譬如，我们可以往我们的ProductsController类里添加如下所示的三个控制器action方法，来处理上述的三个电子商务URL场景：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step7.jpg" /> </p>
<p>在项目创建时默认配置的URL routing规则会把紧随控制器名称之后的子路径当作请求的action名称来对待。所以，如果我们收到一个/Products/Categories的URL请求，routing规则会把&#8220;Categories&#8221;作为一个action的名称来对待，Categories() 方法就会被调用来处理这个请求。如果我们收到的是 /Products/Detail/5 URL请求，routing规则就会把&#8220;Detail"&#8221;当中action的名称，Detail() 方法就会被调用来处理请求，等等。 </p>
<p><em>注：ASP.NET MVC框架并不要求你总是使用这个action命名约定模式。如果你想使用不同的URL映射模式，到 Global.asax文件中的ASP.NET Application类去做改动。</em></p>
<h3><u>把URL参数映射到Controller的Action方法上</u></h3>
<p>在Controller类中的action方法中可以用几个方法访问URL中的参数值。</p>
<p>Controller基类呈现了可以使用的Request 和Response对象。这些对象跟ASP.NET中你已经熟悉的HttpRequest/HttpResponse对象拥有完全一样的API结构。一个非常重要的区别是，这些对象现在是基于接口（interface）的，而不是封闭的类。具体来说，MVC 框架将发布System.Web.IHttpRequest和System.Web.IHttpResponse接口。这些对象是基于的接口的好处是，现在非常容易mock（模仿）它们，这样，就可以方便对控制器类的单元测试。在将来的博客贴子里，我将对此进行深入的讨论。 </p>
<p>下面是一个如何在ProductsController类的Detail action方法中使用Request API来手工获取ID查询字符串值的例子： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step8.jpg" /> </p>
<p>ASP.NET MVC 框架还支持自动将进来的URL的参数值映射成action方法的参数。在默认情形下，如果你的action方法有个参数的话，MVC框架会检查进来的请求的数据，看是否有个同样名称的对应的HTTP请求值。如果有的话，它会自动将其作为参数传入你的action方法。 </p>
<p>譬如，我们可以利用这个支持来重写我们的Detail action方法来，将其简化，象下面这样： </p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step9.jpg" /> </p>
<p>除了从请求的查询字符串/表单集合中映射参数值外，ASP.NET MVC框架还允许你使用MVC URL route映射基础设施在核心URL本身内嵌参数值（譬如，不是使用/Products/Detail?id=3，而是使用/Products/Detail/3 ）。</p>
<p>当你创建一个新的MVC项目时，声明的默认的路径映射规则拥有这样的格式，&#8220;/[controller]/[action]/[id]&#8221;。这意味着，如果URL中在控制器名称和action名称之后还有任何子路径的话，在默认情形下，它将作为一个名为&#8220;id&#8221;的参数处理，会自动地作为一个方法参数传给我们的控制器action方法。</p>
<p>这意味着我们现在可以使用我们的Detail 方法来处理从URL路径（譬如/Products/Detail/3）中获取ID参数：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step10.jpg" /> </p>
<p>我可以对List action使用类似的方法，这样我们可以将分类名称作为URL的一部分传进来（譬如:/Products/List/Beverages）。为了使得代码容易阅读，我对routing规则做了一个小变动，这样不是把参数名定为&#8220;id&#8221;，对这个action，它被称作&#8220;category&#8221;。</p>
<p>下面是实现了完整URL routing和参数映射支持的ProductsController类的一个版本： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step11.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step11.jpg" width="500" /></a> </p>
<p>注意上面List action方法接受一个作为URL一部分的category参数，然后一个作为URL查询字符串一部分的可缺省的网页索引参数（我们将实现服务器端分页，将使用该参数值来表示我们应该显示对应分类数据的哪一页）。</p>
<p>我们的MVC 框架中的可缺省的参数是通过Controller Action方法上nullable的类型参数来处理的。因为我们List action的分页参数是个nullable的int,从语法上来说，即是int? ，如果这个参数存在于URL中，MVC框架会将其值传给对应方法，如果不存在，会传入null。参阅我<a href="http://weblogs.asp.net/scottgu/archive/2007/09/20/the-new-c-null-coalescing-operator-and-using-it-with-linq.aspx" target="_blank"><font color="#087da8">以前的关于?? null coalescing operator帖子</font></a>以了解如何操作象这样传入的nullable类型参数的一个有用的技巧/诀窍。 </p>
<h3><u>建造数据模型对象</u></h3>
<p>至此，我们有了一个 ProductsController类，内含三个action方法，准备好处理进来的web请求了。下一步将是建造一些类，来帮我们操作数据库，从中获取处理这些请求所需的适当的数据。</p>
<p>在MVC世界里，&#8220;model（模型）&#8221;是负责保持状态的应用组件。在web应用中，这个状态一般都持久于数据库之中（譬如，我们也许有一个Product 对象，用来代表我们SQL数据库里Products表中的产品数据）。</p>
<p>ASP.NET MVC框架允许你为获取和管理你的模型，可以使用你想要的任何数据访问模式或框架。如果你要使用ADO.NET DataSets/DataReaders （或者建于它们之上的抽象），你可以那么做。如果你更喜欢使用象NHibernate, LLBLGen, WilsonORMapper, LINQ to SQL/LINQ to Entities这样的对象关系映射器（ORM），你也绝对可以那么做。</p>
<p>对我们的电子商务例程，我想用随 .NET 3.5 和 VS 2008发布的内置LINQ to SQL orM 。你可以从我的<a href="http://weblogs.asp.net/scottgu/archive/2007/09/07/linq-to-sql-part-9-using-a-custom-linq-expression-with-the-lt-asp-linqdatasource-gt-control.aspx" target="_blank"><font color="#087da8">还在撰写中的讨论LINQ to SQL 的博客系列</font></a>中了解其中详情，特别是一定要阅读一下其中的<a href="http://weblogs.asp.net/scottgu/archive/2007/05/19/using-linq-to-sql-part-1.aspx" target="_blank"><font color="#087da8">第一部分</font></a>，<a href="http://weblogs.asp.net/scottgu/archive/2007/05/29/linq-to-sql-part-2-defining-our-data-model-classes.aspx" target="_blank"><font color="#087da8">第二部分</font></a>，<a href="http://weblogs.asp.net/scottgu/archive/2007/06/29/linq-to-sql-part-3-querying-our-database.aspx" target="_blank"><font color="#087da8">第三部分</font></a>，和<a href="http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx" target="_blank"><font color="#087da8">第四部分</font></a>的帖子。 </p>
<p>从右击VS中的MVC web项目的&#8220;Models&#8221;子目录开始，选择&#8220;添加新项&#8221;，加一个 LINQ to SQL 模型。在LINQ to SQL orM 设计器中，我将定义三个数据模型类，分别映射到SQL Server Northwind数据库中的Categories, Products, 和Suppliers 表（阅读我的<a href="http://weblogs.asp.net/scottgu/archive/2007/05/29/linq-to-sql-part-2-defining-our-data-model-classes.aspx" target="_blank"><font color="#087da8">LINQ to SQL 系列的第二部分</font></a>学习该怎么做）：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step12.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step12.jpg" width="500" /></a> </p>
<p>定义完LINQ to SQL 数据模型类之后，然后我还将添加一个新NorthwindDataContext部分类到我们的Models目录中：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step14.jpg" /> </p>
<p>在这个类中，我将定义几个辅助方法封装一些LINQ表达式，这些表达式是用来从数据库中获取独特的Category对象，获取指定分类的所有Product 对象，以及基于指定的ProductID获取单独的 Product对象： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step13.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step13.jpg" width="500" /></a> </p>
<p>这些辅助方法将方便我们在ProductsController类中干净利索地获取所需的数据模型对象 （而不用在Controller类中编写LINQ表达式）：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step16.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step16.jpg" width="500" /></a> </p>
<p>至此，我们就有了为完成我们的ProductsController功能所需的所有的数据代码和对象。</p>
<h3><u>完成ProductsController类的实现</u></h3>
<p>基于MVC的应用中的控制器类负责处理到来的请求，处理用户输入和交互，并且基于这些输入和交互执行适当的应用逻辑（获取和更新储存在数据库中的模型数据等等）。</p>
<p>控制器一般<u>不</u>对请求生成特定的HTML响应。生成HTML响应的任务是为应用中的&#8220;视图&#8221;组件所拥有，这些视图是通过独立于控制器的单独的类或模板实现的。视图的目的是完全注重于封装表现层的逻辑，不应该包含任何应用逻辑或数据库数据获取的代码的（所有的应用逻辑应当为Controller来处理）。 </p>
<p>在一个典型的MVC web流程中，控制器action方法负责处理进来的web请求，使用传入的参数值执行适当的应用逻辑代码，从数据库中获取或更新数据模型对象，然后选择使用一个&#8220;视图&#8221;来显示返回给浏览器的界面响应。作为选择适当的视图来显示的一部分，控制器会明确地以参数的形式向&#8220;视图&#8221;传入视图所需的所有的数据和变量，以使后者显示适当的响应：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step0.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step0.jpg" width="500" /></a> </p>
<p>你也许在想，象这样分开Controller和View有什么好处呢？为什么不把它们放在同一个类里呢？象这样分割应用的主要动机在于帮助你加强应用/数据逻辑与你的界面生成代码间的分离。这可以在隔离你的界面显示逻辑的情形下，极大地方便你单元测试你的应用/数据逻辑。它还有助于使得你的应用更好维护，因为它妨碍了你无意中把应用/数据逻辑加到你的视图模板里的可能。</p>
<p>在实现我们ProductsController类的三个控制器action方法时，我们将根据进来的URL参数值从数据库中获取适当的模型对象，然后选择一个&#8220;视图&#8221;组件来显示适当的HTML响应。我们将使用Controller基类的一个RenderView() 方法来指定我们想要使用的视图，以及明确地把我们要视图在显示响应时使用的特定数据传入该方法。</p>
<p>下面是我们的ProductsController实现的最终结果：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step17.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step17.jpg" width="500" /></a> </p>
<p>注意，我们的action方法的代码行数目很小（每个方法只有2行），部分原因是因为URL参数分析逻辑完全是由MVC框架为我们做的（给我们省了很多行代码），还有部分原因是因为产品浏览场景从业务逻辑的角度来说相当简单（涉及的action方法都是只读的显示场景）。</p>
<p>但总的来说，你经常会发现你有的都是些有时被称为&#8220;瘦控制器&#8221;的东西，即控制器方法充满了相当简短的action方法（少于10行代码）。这经常是好的迹象，表明你非常干净地封装了你的数据逻辑，也非常好地分隔了你的控制器逻辑。</p>
<h3><u>单元测试ProductsController</u></h3>
<p>你也许会感到惊奇，我们要做的下一步居然是测试我们的应用逻辑和功能。你也许会问，这怎么可能呢？我们还没有实现我们的视图呢，我们的应用目前并不显示一个HTML tag。其实呢，使得MVC方法有魅力的部分原因就是我们可以完全独立于视图/Html生成逻辑来测试Controller和Model 逻辑。在下面你将看到，我们甚至可以在创建视图前单元测试这些对象。</p>
<p>为单元测试我们在编写的ProductsController类，我们将往测试项目里加一个ProductsControllerTest类，这个测试项目是在我们使用Visual Studio创建我们的ASP.NET MVC应用时，默认添加到我们的解决方案里的：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step18.jpg" /> </p>
<p>然后我们将定义一个简单的单元测试，测试我们的ProductsController的 Detail action方法：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step19.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step19.jpg" width="500" /></a> </p>
<p>ASP.NET MVC 框架是特地设计来促成轻松的单元测试的。框架中的所有的核心API和契约都是接口，提供了大量的扩展点以促成轻松的对象注入和定制（包括使用象Windsor, StructureMap, Spring.NET, 和ObjectBuilder这样的IOC容器的能力）。开发人员将能够使用内置的mock类，或者使用任何.NET 类型mock框架来模拟他们自己的MVC相关对象的测试版本。 </p>
<p>在上面的单元测试中，你可以看到一个例子，我们是如何在调用 Detail() action 方法之前，往我们的ProductsController里注入了一个伪（dummy）&#8220;ViewFactory&#8221;实现的。这么做的话，我们就覆盖了默认的ViewFactory，否则的话，默认的ViewFactory会创建和显示我们的视图。我们可以使用这个测试ViewFactory实现来做隔离，只对我们ProductController的Detail action的行为进行测试（而不必调用实际的视图来做测试）。注意我们是如何在Detail() action方法被调用之后，使用了三个 Assert 语句来核实该方法的正确的行为确实发生了（具体地说，该方法获取了正确的Product对象，然后将它传给了适当的视图）。</p>
<p>因为我们可以mock和模拟MVC框架中的任何对象（包括 IHttpRequest 和 IHttpResponse 对象），你不用再在web服务的环境里运行单元测试，我们可以在常规的类库里创建我们的ProductsController对象，然后对它直接测试。这可以极大地加快单元测试的运行速度，以及简化对它们的配置和运行。</p>
<p>如果我们使用 Visual Studio 2008 IDE，我们还可以轻易地跟踪我们运行测试的结果（这个功能现在已经成为VS 2008 专业版的一部分）：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step20.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step20.jpg" width="500" /></a> </p>
<p>我想你会发现ASP.NET MVC 框架极大地方便了测试的编写，而且促成了非常好的TDD流程。</p>
<h3><u>使用视图显示界面</u></h3>
<p>我们完成了我们电子商务应用的产品浏览部分的应用+数据逻辑的实现和测试，现在我们需要实现相关的HTML界面。</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step0.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step0.jpg" width="500" /></a> </p>
<p>我们将通过实现&#8220;视图&#8221;来实现，这些视图将使用我们ProductsController的action方法在调用RenderView() 方法时提供的跟视图有关的数据对象，来显示适当的界面：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step21.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step21.jpg" width="500" /></a> </p>
<p>在上面的代码例子里，RenderView方法的&#8220;Categories&#8221;参数表示我们要显示的视图名称，第二个参数是我们要传给视图对象并要视图对象据此显示适当HTML界面的分类对象的列表。</p>
<p>ASP.NET MVC框架支持使用任何模板引擎（包括象NVelocity, Brail，以及你自己想要编写的任何模板引擎）来帮助生成界面。在默认情形下， ASP.NET MVC 框架使用ASP.NET中现有的ASP.NET 页面 (.aspx), 母版页 (.master), 和用户控件 (.ascx) 。 </p>
<p>我们将使用内置的ASP.NET 视图引擎来实现我们的电子商务应用的界面。</p>
<h3><u>定义Site.Master文件</u></h3>
<p>因为我们将要在网站上建造很多页面，我们先来定义一个母版页，用以封装整个网站公用的HTML布局/样式。我们将在我们项目的\Views\Shared 目录里创建一个名为&#8220;Site.Master&#8221;的文件：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step22.jpg" /> </p>
<p>我们可以引用一个外部的CSS样式文件来封装整个网站的所有样式，然后使用母版页来定义网站总的布局，以及指定我们要具体页面填充相关内容的内容placeholder 区域。在做的时候，我们也可以使用VS 2008 中的新设计器的所有的酷功能，包括<a href="http://weblogs.asp.net/scottgu/archive/2007/07/30/enabling-vertical-split-view-in-vs-2008.aspx" target="_blank"><font color="#087da8">HTML分割视图设计器</font></a>，<a href="http://weblogs.asp.net/scottgu/archive/2007/07/25/vs-2008-web-designer-and-css-support.aspx" target="_blank"><font color="#087da8">编著CSS</font></a>和<a href="http://weblogs.asp.net/scottgu/archive/2007/07/09/vs-2008-nested-master-page-support.aspx" target="_blank"><font color="#087da8">嵌套母版页支持</font></a>等。 </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step23.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step23.jpg" width="500" /></a> </p>
<h3><u>理解/Views目录结构</u></h3>
<p>在默认情形下，当你使用Visual Studio创建新的ASP.NET MVC 项目时，它会在&#8220;Views&#8221;根目录下生成一个&#8220;Shared&#8221;子目录。这是存放应用中为多个控制器所共享的母版页，用户控件和视图的推荐使用的地点。 </p>
<p>在建造为特定个别控制器所用的视图时，默认的 ASP.NET MVC 约定是，把它们存放在\Views 根目录的子目录里。在默认情形下，子目录的名字应该对应于控制器的名字。譬如，因为我们正编写的Controller类叫&#8220;ProductsController&#8221;，在默认情形下，我们将在\Views\Products 子目录里存放跟它相关的特定视图：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step24.jpg" /> </p>
<p>当我们在一个特定的Controller中调用 RenderView(string viewName)方法时，MVC框架会自动地首先在\Views\<em>ControllerName</em> 目录里寻找对应的.aspx 或 .ascx视图模板，如果它找不到适当的视图模板，然后它会在 \Views\Shared目录寻找。 </p>
<h3><u>创建一个Categories视图</u></h3>
<p>我们可以在 Visual Studio 中 Products 目录上使用&#8220;添加新项&#8221;菜单选项，然后选择&#8220;MVC视图网页&#8221;项模板，为我们的ProductsController 创建一个&#8220;Categories&#8221;视图。这会生成一个新的.aspx 页面，我们可以将它跟我们的 Site.Master母版页相关联，来得到总的外观（就象母版页一样，你会得到即见即所得设计器的支持）：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step25.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step25.jpg" width="500" /></a> </p>
<p>在使用MVC模式建造应用时，你要把你的视图代码尽可能地保持简洁，确认视图代码纯粹是用来显示界面。应用和数据获取逻辑应该只在Controller类里编写。然后Controller类就可以在调用RenderView 方法时选择把所需的数据对象传递给视图。譬如，在下面，我们的ProductsController类的 Categories action方法中，我们把 一个Category对象的List集合传给了Categories视图： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step21.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step21.jpg" width="500" /></a> </p>
<p>MVC视图页默认是从System.Web.Mvc.ViewPage 基类继承而来的，该基类提供了可为我们构建界面时所用的许多特定于MVC的辅助方法和属性。ViewPage的其中一个属性名叫&#8220;ViewData&#8221;，通过它，你可以访问Controller作为参数传给 RenderView()方法的特定于视图的数据对象。</p>
<p>从你的视图里，你可以后期绑定或以强类型的方式访问&#8220;ViewData&#8221;。如果你的视图是从ViewPage继承而来，那么ViewData属性是个后期绑定的字典。如果你的视图是从基于泛型的ViewPage&lt;T&gt;继承而来，其中T表示Controller传给视图的ViewData的数据对象的类型，那么ViewData属性就是强类型的，匹配你的Controller传入的数据的类型。 </p>
<p>譬如，如下所示的我的Categories视图的后台类是从ViewPage&lt;T&gt;继承而来，我指明T为Category对象的一个List </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step26.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step26.jpg" width="500" /></a> </p>
<p>这意味着在我的视图代码里操作ProductsController.Categories() 提供的List&lt;Category&gt; ViewData时，我将得到完整的类型安全， intellisense和编译时检查：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step27.jpg" /> </p>
<h3><u>显示Categories视图：</u></h3>
<p>如果你还记得本帖子最前面的截图的话，我们要在我们的 Categories 视图里显示产品分类列表：</p>
<p><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step28.jpg" /> </p>
<p>我可以在我的Categories视图实现里用2种方式编写这个HTML界面生成代码：1) 在.aspx 文件里使用行内代码, 或者 2) 在.aspx 文件中使用服务器控件，然后在后台代码里使用数据绑定。</p>
<h3><u>显示方法1：使用行内代码</u></h3>
<p>目前的ASP.NET网页, 用户控件和母版页支持使用 &lt;% %&gt; 和 &lt;%= %&gt;的句法来在html 标识内嵌入显示代码。我们可以在Categories 视图里使用这个技巧，轻松地编写一个foreach循环，来生成HTML分类列表： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step29.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step29.jpg" width="500" /></a> </p>
<p>VS 2008在源码编辑器内为VB和C#提供完整的代码intellisense。这意味着，在对传入视图的Category模型对象操作时，我们将得到intellisense：</p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step30.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step30.jpg" width="500" /></a> </p>
<p>VS 2008还为行内代码提供了完整的调试器支持（允许我们在调试器对视图中的代码设置断点以及动态检查任何东西）： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step31.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step31.jpg" width="500" /></a> </p>
<h3><u>显示方法2：使用服务器端控件</u></h3>
<p>&nbsp;</p>
<p>ASP.NET网页，用户控件和母版页还提供对使用声明式服务器端控件封装HTML界面生成的支持。不是象上面那样使用行内代码，我们可以使用 <a href="http://weblogs.asp.net/scottgu/archive/2007/08/10/the-asp-listview-control-part-1-building-a-product-listing-page-with-clean-css-ui.aspx" target="_blank"><font color="#087da8">.NET 3.5中新的&lt;asp:listview&gt; 控件</font></a>来生成列表界面： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step32.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step32.jpg" width="500" /></a> </p>
<p>注意上面 ListView 控件封装了显示值列表的情形，还负责处理列表中没有任何东西的情形（&lt;EmptyDataTemplate&gt;省略了需要在标识中编写 if/else 语句的麻烦）。然后我们可以象下面这样，在后台代码里，将我们的分类对象绑定到listview控件上： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step33.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step33.jpg" width="500" /></a> </p>
<p><em>重要注意事项：在MVC世界里，我们只想要把显示代码放在我们视图的后台代码里,不包括任何应用或数据逻辑。注意上面我们只有把强类型的Category对象的ViewData集合赋值给ListView控件的逻辑。我们的ProductsController控制器类才是实际从数据库获取Category对象列表的责任者，不是视图。 </em></p>
<p>我们视图模板的ListView服务器端控件版本然后就会生成跟上面行内代码版本完全一样的HTML。因为我们在页面里没有 &lt;form runat="server"&gt;控件，ViewState，ID值以及其他的标识都不会生成，只有纯粹的CSS友好的HTML： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step34.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step34.jpg" width="500" /></a>&nbsp;</p>
<h3><u>Html.ActionLink方法</u></h3>
<p>你也许注意到的一件事情是，在上面视图代码片断中行内代码以及服务器端控件两个版本中对一个Html.ActionLink 方法的调用： </p>
<p><a title="在新窗口打开图片" href="http://www.scottgu.com/blogposts/mvc2/step35.jpg" target="_blank"><img alt="" src="http://www.scottgu.com/blogposts/mvc2/step35.jpg" width="500" /></a> </p>
<p>Html对象是 ViewPage 基类的一个辅助属性，ActionLink方法是它的一个辅助方法，它方便你动态地生成连回到控制器的action 方法的HTML超链接。如果你看一下上面生成的HTML输出图，你可以看到一些由该方法生成的一些HTML输出例子：</p>
<blockquote>
<p>&lt;a href="http://weblogs.asp.net/Products/List/Beverages"&gt;Beverages&lt;/a&gt;</p>
</blockquote>
<p>我使用的Html.ActionLink方法的签名是这样的：</p>
<blockquote>
<p>string ActionLink(string text, object values);</p>
</blockquote>
<p>第一个参数表示要显示的超链接的内容（譬如&lt;a&gt;这里是文字&lt;/a&gt;），第二个参数是个<a href="http://blog.joycode.com/scottgu/archive/2007/05/21/102887.aspx" target="_blank"><font color="#087da8">匿名对象 </font></a>，它代表用以生成实际URL的一串值，你可以认为它是<a href="http://weblogs.asp.net/leftslipper/archive/2007/09/24/using-c-3-0-anonymous-types-as-dictionaries.aspx" target="_blank"><font color="#087da8">生成字典的一个比较干净的方式</font></a>。我会在将来讨论URL routing引擎的博客帖子里仔细讨论这个参数的运用情形。但简而言之，你可以使用URL routing系统既处理进来的URL,也可以用它来生成你可以在返回的HTML输出的URL。如果我们的routing规则是象这样的： </p>
<blockquote>
<p>/&lt;controller&gt;/&lt;action&gt;/&lt;category&gt;</p>
</blockquote>
<p>那么在ProductController的Category视图里编写这样的代码时：</p>
<blockquote>
<p>&lt;%= Html.ActionLink("Click Me to See Beverages", new { action="List", category="Beverages" } %&gt;</p>
</blockquote>
<p>ActionLink方法就会使用你应用的URL映射规则，换进你的参数，生成这样的输出：</p>
<blockquote>
<p>&lt;a href="http://weblogs.asp.net/Products/List/Beverages"&gt;Click Me to See Beverages&lt;/a&gt;</p>
</blockquote>
<p>这方便了在你应用中生成URL和到你的控制器的AJAX回调。它也意味着你可以在一个地方更新你的URL routing规则，你整个应用中的代码会在对进来的URL的处理和外出的URL的生成过程中自动采用新的变化。 </p>
<p><em>重要注意事项</em>： 为加强可测试性，目前的MVC框架并不支持你视图中针对服务器端控件的postback事件，取而代之的是，ASP.NET MVC应用生成超链接和对控制器action的AJAX回调，然后只使用视图（以及其中的任何服务器端控件）显示输出。这有助于确保你的视图逻辑保持在最小限度，只注重于显示，以及你可以单元测试你的Controller类，独立于你的视图，核实所有的应用和数据逻辑行为。我在将来的帖子里会对此做更深入的讨论。 </p>
<h3><u>结语</u></h3>
<p>这第一个贴子非常长，但希望它对新的ASP.NET MVC框架中所有不同的组件是如何组合在一起的，如何使用它打造常见的现实世界场景的应用提供了一个相当广泛的综览。 ASP.NET MVC的第一个公开预览版将在几个星期内发布，你将能够使用它来做我上面描述的一切。 </p>
<p>虽然很多MVC固有的概念（特别是关注分离的观念）对该贴子的很多读者来说是比较新的，但希望本贴子展示了我们正在开发的ASP.NET MVC实现是如何很干净地嵌合到现有的ASP.NET, .NET, 和 Visual Studio框架中的。你可以使用.ASPX, .ASCX 和 .MASTER文件以及ASP.NET AJAX创建你的ASP.NET MVC 视图。今天ASP.NET中的非界面功能，譬如表单认证, Windows认证, 成员，角色, Url授权, 缓存, Session 状态, 用户信息,健康监测, 配置，编译，本地化以及 HttpModules/HttpHandlers 都是完全支持MVC模型的。 </p>
<p>如果你不喜欢MVC模型，或者发现它对你的开发风格来说并不自然的话，你完全不必强用它的。它完全只是提供选项，<u>并不</u>替代现有的 WebForms Page Controller 模型。WebForms和MVC这2个模型在以后都会得到完全支持和改进。如果你想的话，你甚至可以建造一个应用，部分使用WebForms编写，部分使用MVC编写。 </p>
<p>如果你喜欢上面贴子里的东西的话（或者感兴趣想进一步了解的话），留意一下我这段时间的博客。我将进一步讨论MVC概念，使用它们来进一步建造我们的电子商务应用，展示更多的MVC特性。 </p>
<p>希望本文对你有所帮助，</p>
<p>Scott</p>
<img src ="http://www.blogjava.net/jvict/aggbug/249007.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-29 22:42 <a href="http://www.blogjava.net/jvict/articles/249007.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>GridView导出Excel研究 </title><link>http://www.blogjava.net/jvict/articles/247617.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sun, 21 Dec 2008 05:57:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/247617.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/247617.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/247617.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/247617.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/247617.html</trackback:ping><description><![CDATA[<p style="text-align: left" align="left">原文：http://www.cnblogs.com/stswordman/articles/485641.html<span style="font-size: 10pt; font-family: 宋体"><br />
<br />
将</span><span style="font-size: 10pt; font-family: Verdana">GridView</span><span style="font-size: 10pt; font-family: 宋体">中的数据导出为</span><span style="font-size: 10pt; font-family: Verdana">Excel</span><span style="font-size: 10pt; font-family: 宋体">是</span><span style="font-size: 10pt; font-family: Verdana">web</span><span style="font-size: 10pt; font-family: 宋体">应用中的常见功能。在不同的应用场景下有不同的导出技术。在本文中我将介绍一些导出的技术，希望对您有所帮助</span></p>
<p style="text-align: left" align="left"><strong><u><span style="font-size: 10pt; font-family: Verdana">GridView Export the Excel (Basic Code):&nbsp; </span></u></strong></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: Verdana">. </span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">首先看一个基础的应用。创建一个表格，见截图</span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: Verdana">&lt;!--[if !vml]--&gt; &lt;!--[if !vml]--&gt;<img height="207" alt="" src="http://images.cnblogs.com/cnblogs_com/stswordman/GridViewExportToExcelAllYouNeed1.GIF" width="526" /></p>
<fieldset><legend><br />
</legend></fieldset>&lt;!--[endif]--&gt;&nbsp;</span>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">然后将数据库中的数据绑定到</span><span style="font-size: 10pt; font-family: Verdana">GridView</span><span style="font-size: 10pt; font-family: 宋体">中的数据，代码如下：</span></p>
<table style="background: silver 0% 50%; width: 100%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%">
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">private</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">void</span> BindData()</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">SqlConnection</span><span style="font-size: 10pt; font-family: 'Courier New'"> myConnection = <span style="color: blue">new</span> <span style="color: teal">SqlConnection</span>(<span style="color: maroon">"Server=localhost;Database=School;Trusted_Connection=true"</span>);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">SqlDataAdapter</span><span style="font-size: 10pt; font-family: 'Courier New'"> ad = <span style="color: blue">new</span> <span style="color: teal">SqlDataAdapter</span>(<span style="color: maroon">"SELECT * FROM Users"</span>, myConnection);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">DataSet</span><span style="font-size: 10pt; font-family: 'Courier New'"> ds = <span style="color: blue">new</span> <span style="color: teal">DataSet</span>();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">ad.Fill(ds);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gvUsers.DataSource = ds;</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gvUsers.DataBind(); </span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">&lt;!--[if !vml]--&gt;<img src="http://images.cnblogs.com/cnblogs_com/stswordman/GridViewExportToExcelAllYouNeed2.GIF" border="0"  alt="" /><br />
&lt;!--[endif]--&gt; &lt;!--[if !vml]--&gt;&lt;!--[endif]--&gt;</span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">现在，</span><span style="font-size: 10pt; font-family: Verdana">GridView</span><span style="font-size: 10pt; font-family: 宋体">中已经绑定了数据，接下来的任务就是导出到</span><span style="font-size: 10pt; font-family: Verdana">Excel</span><span style="font-size: 10pt; font-family: 宋体">。下面是</span><span style="font-size: 10pt; font-family: Verdana">button</span><span style="font-size: 10pt; font-family: 宋体">事件中的代码</span></p>
<table style="background: silver 0% 50%; width: 100%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%">
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.ClearContent();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.AddHeader(<span style="color: maroon">"content-disposition"</span>, <span style="color: maroon">"attachment; filename=MyExcelFile.xls"</span>);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.ContentType = <span style="color: maroon">"application/excel"</span>;</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">StringWriter</span><span style="font-size: 10pt; font-family: 'Courier New'"> sw = <span style="color: blue">new</span> <span style="color: teal">StringWriter</span>();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">HtmlTextWriter</span><span style="font-size: 10pt; font-family: 'Courier New'"> htw = <span style="color: blue">new</span> <span style="color: teal">HtmlTextWriter</span>(sw);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gvUsers.RenderControl(htw);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.Write(sw.ToString());</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.End();</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">并且还需要</span><span style="font-size: 10pt; font-family: Verdana">override</span><span style="font-size: 10pt; font-family: 宋体">一下</span><strong><span style="font-size: 10pt; font-family: Verdana">VerifyRenderingInServerForm</span></strong><strong><span style="font-size: 10pt; font-family: 宋体">方法</span></strong><strong><span style="font-size: 10pt; font-family: Verdana">(</span></strong><strong><span style="font-size: 10pt; color: blue; font-family: 宋体">这一点非常重要，否则在点击按钮后会报错，译者注</span></strong><strong><span style="font-size: 10pt; font-family: Verdana">)</span></strong><strong><span style="font-size: 10pt; font-family: 宋体">，</span></strong><span style="font-size: 10pt; font-family: 宋体">代码如下</span><strong><span style="font-size: 10pt; font-family: Verdana">:</span></strong></p>
<table style="background: silver 0% 50%; width: 100%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%">
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">public</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">override</span> <span style="color: blue">void</span> VerifyRenderingInServerForm(<span style="color: teal">Control</span> control)</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">点击导出按钮后会弹出对话框，询问您打开或保存。选择打开文件，导出到</span><span style="font-size: 10pt; font-family: Verdana">Excel</span><span style="font-size: 10pt; font-family: 宋体">的结果如下图：</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">&lt;!--[if !vml]--&gt;<img src="http://images.cnblogs.com/cnblogs_com/stswordman/GridViewExportToExcelAllYouNeed3.GIF" border="0"  alt="" /><br />
&lt;!--[endif]--&gt; &lt;!--[if !vml]--&gt;&lt;!--[endif]--&gt;</span></p>
<p style="text-align: left" align="left"><strong><u><span style="font-size: 10pt; font-family: Verdana">Exporting GridView to Excel With Style:</span></u></strong><span style="font-size: 10pt; font-family: Verdana"><br />
</span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">您是否注意到了以上代码存在一些的问题？是的，</span><span style="font-size: 10pt; font-family: Verdana">ID</span><span style="font-size: 10pt; font-family: 宋体">列开头的</span><span style="font-size: 10pt; font-family: Verdana">0</span><span style="font-size: 10pt; font-family: 宋体">都被截去了。如果你的</span><span style="font-size: 10pt; font-family: Verdana">ID</span><span style="font-size: 10pt; font-family: 宋体">是</span><span style="font-size: 10pt; font-family: Verdana">000345</span><span style="font-size: 10pt; font-family: 宋体">，导出后就编程了</span><span style="font-size: 10pt; font-family: Verdana">345</span><span style="font-size: 10pt; font-family: 宋体">。这个问题可以通过把</span><span style="font-size: 10pt; font-family: Verdana">css</span><span style="font-size: 10pt; font-family: 宋体">添加到输出流中来解决。为了使</span><span style="font-size: 10pt; font-family: Verdana">ID</span><span style="font-size: 10pt; font-family: 宋体">列正确显示，您需要将其储存为文本格式。</span><span style="font-size: 10pt; font-family: Verdana">Excel</span><span style="font-size: 10pt; font-family: 宋体">中的文本格式表示为</span><span style="font-size: 10pt; font-family: Verdana">"</span><span style="font-size: 10pt; font-family: 'Courier New'">mso-number-format:""@</span><span style="font-size: 10pt; font-family: Verdana">"</span><span style="font-size: 10pt; font-family: 宋体">。</span></p>
<table style="background: silver 0% 50%; width: 100%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%">
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">protected</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">void</span> Btn_ExportClick(<span style="color: blue">object</span> sender, <span style="color: teal">EventArgs</span> e)</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><strong><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">string</span></strong><strong><span style="font-size: 10pt; font-family: 'Courier New'"> style = <span style="color: maroon">@"&lt;style&gt; .text { } &lt;/script&gt; "</span>; </span></strong></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.ClearContent();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.AddHeader(<span style="color: maroon">"content-disposition"</span>, <span style="color: maroon">"attachment; filename=MyExcelFile.xls"</span>);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.ContentType = <span style="color: maroon">"application/excel"</span>;</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">StringWriter</span><span style="font-size: 10pt; font-family: 'Courier New'"> sw = <span style="color: blue">new</span> <span style="color: teal">StringWriter</span>();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">HtmlTextWriter</span><span style="font-size: 10pt; font-family: 'Courier New'"> htw = <span style="color: blue">new</span> <span style="color: teal">HtmlTextWriter</span>(sw);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gvUsers.RenderControl(htw);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: green; font-family: 'Courier New'">// Style is added dynamically</span></p>
            <p style="text-align: left" align="left"><strong><span style="font-size: 10pt; font-family: 'Courier New'">Response.Write(style); </span></strong></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.Write(sw.ToString());</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.End();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">public</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">override</span> <span style="color: blue">void</span> VerifyRenderingInServerForm(<span style="color: teal">Control</span> control)</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">&nbsp;在上面的代码中，我通过</span><span style="font-size: 10pt; font-family: Verdana">&#8221;style&#8221;</span><span style="font-size: 10pt; font-family: 宋体">变量来控制</span><span style="font-size: 10pt; font-family: Verdana">GridView</span><span style="font-size: 10pt; font-family: 宋体">列的样式。并通过</span><span style="font-size: 10pt; font-family: Verdana">Respnose.Write</span><span style="font-size: 10pt; font-family: 宋体">方法将其添加到输出流中。最后把样式添加到</span><span style="font-size: 10pt; font-family: Verdana">ID</span><span style="font-size: 10pt; font-family: 宋体">列。这一步需要在</span><span style="font-size: 10pt; font-family: Verdana">RowDataBound</span><span style="font-size: 10pt; font-family: 宋体">事件中完成</span></p>
<table style="background: silver 0% 50%; width: 100%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%">
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">protected</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">void</span> gvUsers_RowDataBound(<span style="color: blue">object</span> sender, <span style="color: teal">GridViewRowEventArgs</span> e)</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{ </span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">if</span><span style="font-size: 10pt; font-family: 'Courier New'"> (e.Row.RowType == <span style="color: teal">DataControlRowType</span>.DataRow)</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><strong><span style="font-size: 10pt; font-family: 'Courier New'">e.Row.Cells[1].Attributes.Add(<span style="color: maroon">"class"</span>, <span style="color: maroon">"text"</span>); </span></strong></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">&nbsp;修改的结果如下：</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">&lt;!--[if !vml]--&gt;&lt;!--[endif]--&gt; &lt;!--[if !vml]--&gt;<img src="http://images.cnblogs.com/cnblogs_com/stswordman/GridViewExportToExcelAllYouNeed4.GIF" border="0"  alt="" /><br />
&lt;!--[endif]--&gt;</span></p>
<div align="center">
<table style="background: #ffffcc 0% 50%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" height="22" cellspacing="0" cellpadding="0" width="1" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%"><br />
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="text-align: left" align="left"><strong><u><span style="font-size: 10pt; font-family: Verdana">Exporting GridView With LinkButtons and Paging:&nbsp; </span></u></strong></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">如果要导出的</span><span style="font-size: 10pt; font-family: Verdana">GridView</span><span style="font-size: 10pt; font-family: 宋体">中包含</span><span style="font-size: 10pt; font-family: Verdana">LinkButton</span><span style="font-size: 10pt; font-family: 宋体">或者分页</span><span style="font-size: 10pt; font-family: Verdana">(</span><span style="font-size: 10pt; color: blue; font-family: 宋体">出现分页码时，译者注</span><span style="font-size: 10pt; font-family: Verdana">) </span><span style="font-size: 10pt; font-family: 宋体">则将出现错误：</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">&lt;!--[if !vml]--&gt;&lt;!--[endif]--&gt; &lt;!--[if !vml]--&gt;<img src="http://images.cnblogs.com/cnblogs_com/stswordman/GridViewExportToExcelAllYouNeed5.GIF" border="0"  alt="" /><br />
&lt;!--[endif]--&gt;</span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">通过修改页文件可以修正这个问题：</span><span style="font-size: 10pt; font-family: Verdana">EnableEventValidation = "false". </span></p>
<table style="background: silver 0% 50%; width: 100%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%">
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">&lt;%<span style="color: blue">@</span> <span style="color: maroon">Page</span> <span style="color: red">Language</span><span style="color: blue">="C#"</span> <strong><span style="color: red">EnableEventValidation</span><span style="color: blue">="false"</span></strong> <span style="color: red">AutoEventWireup</span><span style="color: blue">="true"</span> <span style="color: red">CodeFile</span><span style="color: blue">="Default.aspx.cs"</span> <span style="color: red">Inherits</span><span style="color: blue">="_Default"</span> %&gt;</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">看一下导出的文件</span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: Verdana">&lt;!--[if !vml]--&gt;<br />
<img src="http://images.cnblogs.com/cnblogs_com/stswordman/GridViewExportToExcelAllYouNeed6.GIF" border="0"  alt="" />&nbsp;</span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">在导出的文件中可以看见</span><span style="font-size: 10pt; font-family: Verdana">linkbutton</span><span style="font-size: 10pt; font-family: 宋体">和</span><span style="font-size: 10pt; font-family: Verdana">dropdownlist</span><span style="font-size: 10pt; font-family: 宋体">控件，虽然</span><span style="font-size: 10pt; font-family: Verdana">dropdownlist</span><span style="font-size: 10pt; font-family: 宋体">控件显示的数据的确是用户所选的项，但怎么看也不像是一个导出文件（<span style="color: blue">我倒是觉的挺</span></span><span style="font-size: 10pt; color: blue; font-family: Verdana">cool</span><span style="font-size: 10pt; color: blue; font-family: 宋体">的：）译者注</span><span style="font-size: 10pt; font-family: 宋体">），现在应如何移除</span><span style="font-size: 10pt; font-family: Verdana">dropdownlist</span><span style="font-size: 10pt; font-family: 宋体">并显示选择的文字呢？</span></p>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">&nbsp;<br />
我写了一个</span><span style="font-size: 10pt; font-family: Verdana">DisableControls</span><span style="font-size: 10pt; font-family: 宋体">函数，用使循环的方法将</span><span style="font-size: 10pt; font-family: Verdana">linkbutton</span><span style="font-size: 10pt; font-family: 宋体">和</span><span style="font-size: 10pt; font-family: Verdana">dropdownlist</span><span style="font-size: 10pt; font-family: 宋体">替换成</span><span style="font-size: 10pt; font-family: Verdana">literal</span><span style="font-size: 10pt; font-family: 宋体">控件</span></p>
<table style="background: silver 0% 50%; width: 100%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%">
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">private</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">void</span> DisableControls(<span style="color: teal">Control</span> gv)</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">LinkButton</span><span style="font-size: 10pt; font-family: 'Courier New'"> lb = <span style="color: blue">new</span> <span style="color: teal">LinkButton</span>();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">Literal</span><span style="font-size: 10pt; font-family: 'Courier New'"> l = <span style="color: blue">new</span> <span style="color: teal">Literal</span>(); </span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">string</span><span style="font-size: 10pt; font-family: 'Courier New'"> name = <span style="color: teal">String</span>.Empty;</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">for</span><span style="font-size: 10pt; font-family: 'Courier New'"> (<span style="color: blue">int</span> i = 0; i &lt; gv.Controls.Count; i++)</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">if</span><span style="font-size: 10pt; font-family: 'Courier New'"> (gv.Controls[i].GetType() == <span style="color: blue">typeof</span>(<span style="color: teal">LinkButton</span>))</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">l.Text = (gv.Controls[i] <span style="color: blue">as</span> <span style="color: teal">LinkButton</span>).Text; </span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gv.Controls.Remove(gv.Controls[i]);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gv.Controls.AddAt(i, l);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">else</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">if</span> (gv.Controls[i].GetType() == <span style="color: blue">typeof</span>(<span style="color: teal">DropDownList</span>))</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">l.Text = (gv.Controls[i] <span style="color: blue">as</span> <span style="color: teal">DropDownList</span>).SelectedItem.Text;</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gv.Controls.Remove(gv.Controls[i]);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gv.Controls.AddAt(i, l);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">if</span><span style="font-size: 10pt; font-family: 'Courier New'"> (gv.Controls[i].HasControls())</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">DisableControls(gv.Controls[i]); </span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">} </span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">方法非常简单，只需将</span><span style="font-size: 10pt; font-family: Verdana">linkbuton</span><span style="font-size: 10pt; font-family: 宋体">和</span><span style="font-size: 10pt; font-family: Verdana">dropdownlist</span><span style="font-size: 10pt; font-family: 宋体">替换成</span><span style="font-size: 10pt; font-family: Verdana">literal</span><span style="font-size: 10pt; font-family: 宋体">控件，并将选择项赋值给</span><span style="font-size: 10pt; font-family: Verdana">literal</span><span style="font-size: 10pt; font-family: 宋体">控件的文本属性。该方法需要在导出前调用</span></p>
<table style="background: silver 0% 50%; width: 100%; border-collapse: collapse; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial" cellspacing="0" cellpadding="0" width="100%" border="1">
    <tbody>
        <tr>
            <td style="padding-right: 0cm; padding-left: 0cm; padding-bottom: 0cm; width: 100%; padding-top: 0cm" width="100%">
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: blue; font-family: 'Courier New'">protected</span><span style="font-size: 10pt; font-family: 'Courier New'"> <span style="color: blue">void</span> Btn_ExportExcelPaging(<span style="color: blue">object</span> sender, <span style="color: teal">EventArgs</span> e)</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">{</span></p>
            <p style="text-align: left" align="left"><strong><span style="font-size: 12pt; font-family: 'Courier New'">DisableControls(gvUsers);</span></strong></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.ClearContent();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.AddHeader(<span style="color: maroon">"content-disposition"</span>, <span style="color: maroon">"attachment; filename=MyExcelFile.xls"</span>);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.ContentType = <span style="color: maroon">"application/excel"</span>;</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">StringWriter</span><span style="font-size: 10pt; font-family: 'Courier New'"> sw = <span style="color: blue">new</span> <span style="color: teal">StringWriter</span>();</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; color: teal; font-family: 'Courier New'">HtmlTextWriter</span><span style="font-size: 10pt; font-family: 'Courier New'"> htw = <span style="color: blue">new</span> <span style="color: teal">HtmlTextWriter</span>(sw);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">gvUsers.RenderControl(htw);</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.Write(sw.ToString());</span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">Response.End(); </span></p>
            <p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 'Courier New'">}</span></p>
            </td>
        </tr>
    </tbody>
</table>
<p style="text-align: left" align="left"><span style="font-size: 10pt; font-family: 宋体">现在的</span><span style="font-size: 10pt; font-family: Verdana">Excel</span><span style="font-size: 10pt; font-family: 宋体">中就只剩下选中文本了</span></p>
<p style="text-align: left" align="left"><span style="font-size: 12pt; font-family: 宋体">&lt;!--[if !vml]--&gt;<img src="http://images.cnblogs.com/cnblogs_com/stswordman/GridViewExportToExcelAllYouNeed7.GIF" border="0"  alt="" /><br />
&lt;!--[endif]--&gt; &lt;!--[if !vml]--&gt;&lt;!--[endif]--&gt;</span></p>
<p><a href="http://files.cnblogs.com/stswordman/GridViewExportToExcelAllYouNeed.zip"><br />
</a></p>
<p><a href="http://files.cnblogs.com/stswordman/GridViewExportToExcelAllYouNeed.zip"><br />
</a></p>
<p>原文：http://gridviewguy.com/ArticleDetails.aspx?articleID=197</p>
<img src ="http://www.blogjava.net/jvict/aggbug/247617.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-21 13:57 <a href="http://www.blogjava.net/jvict/articles/247617.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>导出excel的四种方法 [转]</title><link>http://www.blogjava.net/jvict/articles/247613.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sun, 21 Dec 2008 05:20:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/247613.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/247613.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/247613.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/247613.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/247613.html</trackback:ping><description><![CDATA[<p>转天天博客 作者: roc<br />
http://qx.ahnw.gov.cn/user1/apeng/archives/2006/11.html<br />
<br />
据我现在所知excel有四种方法：<br />
1.自己写的excel接口，客户端不需要装excel，见灵感之源的blog:<br />
<a href="http://www.cnblogs.com/unruledboy/archive/2004/07/07/22093.aspx">http://www.cnblogs.com/unruledboy/archive/2004/07/07/22093.aspx</a></p>
<p>2.把web上的DataGrid直接导入到excel<br />
public void ExportToExcel(System.Web.UI.Control ctl) <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bool CurrCtlVisible=ctl.Visible;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctl.Visible=true;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.AppendHeader("Content-Disposition","attachment;filename=Excel.xls");&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.ContentType = "application/ms-excel"; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctl.Page.EnableViewState = false; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.IO.StringWriter tw = new System.IO.StringWriter(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Web.UI.HtmlTextWriter hw = new HtmlTextWriter(tw); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctl.RenderControl(hw); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write(tw.ToString()); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.End(); <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctl.Page.EnableViewState = true; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ctl.Visible=CurrCtlVisible;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
3.在引用里调用Microsoft.Office.Interop.Excel.dll，原理是把数据存到DataTable、DataView或DataGrid中，然后再把数据一格一格的赋到excel的cell里去。<br />
见如下代码：</p>
<p>public class ExportToExcel<br />
&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 私有成员#region 私有成员<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 数据的DataView<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private DataView dv=null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 表格标题<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string title=null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 输出文件路径<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string outFilePath=null;</p>
<p>&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 输入文件名<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string inputFilePath=System.Windows.Forms.Application.StartupPath+@" emplate.xls";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 公共属性#region 公共属性<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 数据的DataView<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public DataView DV<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; dv=value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 表格标题<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string Title<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; title=value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return title;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 输出文件路径<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public string OutFilePath<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; outFilePath=value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return outFilePath;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**//// &lt;summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 输入文件路径<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private string InputFilePath<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; inputFilePath=value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return inputFilePath;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 构造函数#region 构造函数</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public ExportToExcel()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public OutputExcel(DataView dv,string title)<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
//<br />
//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 公共方法#region 公共方法<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /**///<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void CreateExcel()<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int rowIndex=4;//行起始坐标<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int colIndex=1;//列起始坐标</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ApplicationClass myApp=null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Workbook myBook=null;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Worksheet mySheet=null;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //如果文件不存在，则将模板文件拷贝一份作为输出文件<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!File.Exists(outFilePath))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; File.Copy(inputFilePath,outFilePath,true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myApp= new ApplicationClass();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myApp.Visible=false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object oMissiong=System.Reflection.Missing.Value;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myApp.Workbooks.Open(outFilePath,oMissiong,oMissiong,oMissiong,oMissiong,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,oMissiong,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; oMissiong,oMissiong,oMissiong);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myBook=myApp.Workbooks[1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet=(Worksheet)myBook.ActiveSheet;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //取得标题<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach(DataColumn col in dv.Table.Columns)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; colIndex++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.Cells[4,colIndex] = col.ColumnName;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[4,colIndex],mySheet.Cells[4,colIndex]).HorizontalAlignment = XlVAlign.xlVAlignCenter;//设置标题格式为居中对齐<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //取得表格中的数据<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach(DataRowView row in dv)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rowIndex ++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; colIndex = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach(DataColumn col in dv.Table.Columns)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; colIndex ++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(col.DataType == System.Type.GetType("System.DateTime"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.Cells[rowIndex,colIndex] = (Convert.ToDateTime(row[col.ColumnName].ToString())).ToString("yyyy-MM-dd");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[rowIndex,colIndex],mySheet.Cells[rowIndex,colIndex]).HorizontalAlignment = XlVAlign.xlVAlignCenter;//设置日期型的字段格式为居中对齐<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else&nbsp; if(col.DataType == System.Type.GetType("System.String"))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.Cells[rowIndex,colIndex] = "'"+row[col.ColumnName].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[rowIndex,colIndex],mySheet.Cells[rowIndex,colIndex]).HorizontalAlignment = XlVAlign.xlVAlignCenter;//设置字符型的字段格式为居中对齐<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.Cells[rowIndex,colIndex] = row[col.ColumnName].ToString();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //加载一个合计行<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int rowSum = rowIndex + 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int colSum = 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.Cells[rowSum,2] = "合计";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[rowSum,2],mySheet.Cells[rowSum,2]).HorizontalAlignment = XlHAlign.xlHAlignCenter;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置选中的部分的颜色<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[rowSum,colSum],mySheet.Cells[rowSum,colIndex]).Select();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[rowSum,colSum],mySheet.Cells[rowSum,colIndex]).Interior.ColorIndex = 19;//设置为浅黄色，共计有56种</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //取得整个报表的标题<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.Cells[2,2] = title;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置整个报表的标题格式<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[2,2],mySheet.Cells[2,2]).Font.Bold = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[2,2],mySheet.Cells[2,2]).Font.Size = 22;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置报表表格为最适应宽度<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[4,2],mySheet.Cells[rowSum,colIndex]).Select();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[4,2],mySheet.Cells[rowSum,colIndex]).Columns.AutoFit();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //设置整个报表的标题为跨列居中<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[2,2],mySheet.Cells[2,colIndex]).Select();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[2,2],mySheet.Cells[2,colIndex]).HorizontalAlignment = XlHAlign.xlHAlignCenterAcrossSelection;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //绘制边框<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[4,2],mySheet.Cells[rowSum,colIndex]).Borders.LineStyle = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[4,2],mySheet.Cells[rowSum,2]).Borders[XlBordersIndex.xlEdgeLeft].Weight = XlBorderWeight.xlThick;//设置左边线加粗<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[4,2],mySheet.Cells[4,colIndex]).Borders[XlBordersIndex.xlEdgeTop].Weight = XlBorderWeight.xlThick;//设置上边线加粗<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[4,colIndex],mySheet.Cells[rowSum,colIndex]).Borders[XlBordersIndex.xlEdgeRight].Weight = XlBorderWeight.xlThick;//设置右边线加粗<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; mySheet.get_Range(mySheet.Cells[rowSum,2],mySheet.Cells[rowSum,colIndex]).Borders[XlBordersIndex.xlEdgeBottom].Weight = XlBorderWeight.xlThick;//设置下边线加粗<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myBook.Save();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myBook.Close( true,outFilePath,true);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Runtime.InteropServices.Marshal.ReleaseComObject(mySheet);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Runtime.InteropServices.Marshal.ReleaseComObject(myBook);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Runtime.InteropServices.Marshal.ReleaseComObject(myApp);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; myApp.Quit();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; GC.Collect();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; #endregion</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; }<br />
4.另外，这就是另外一种方法了，建一个SqlServer的数据源，利用Excel的外部数据源让Excel自己从数据库取数据：</p>
<p>public void ExportToExcel(string pstrSql)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel.Application pApplication;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel._Workbook xBk;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel._Worksheet xSt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Excel._QueryTable xQt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string ExcelConn = "ODBC;DRIVER=SQL Server;SERVER=localhost;UID=sa;PWD=;APP=Microsoft(R) Windows (R) 2000 Operating System;WSID=me;DATABASE=pubs";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pApplication = new Excel.ApplicationClass();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xBk = pApplication.Workbooks.Add(true);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xSt = (Excel._Worksheet)xBk.ActiveSheet;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pApplication.Cells[2,2] = this.title;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xSt.get_Range(pApplication.Cells[2,2],pApplication.Cells[2,2]).Font.Bold = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xSt.get_Range(pApplication.Cells[2,2],pApplication.Cells[2,2]).Font.Name = "黑体";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xSt.get_Range(pApplication.Cells[2,2],pApplication.Cells[2,2]).Font.Size = 22;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt = xSt.QueryTables.Add(ExcelConn,xSt.get_Range(pApplication.Cells[4,2],pApplication.Cells[4,2]),pstrSql);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.Name = "导出EXCEL";<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.FieldNames = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.RowNumbers = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.FillAdjacentFormulas = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.PreserveFormatting = false;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.BackgroundQuery = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.RefreshStyle = Excel.XlCellInsertionMode.xlInsertDeleteCells;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.AdjustColumnWidth = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.RefreshPeriod = 0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.PreserveColumnInfo = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xQt.Refresh(xQt.BackgroundQuery);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pApplication.Visible = true;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
这里的pstrSql指的是sql语句。<br />
</p>
<img src ="http://www.blogjava.net/jvict/aggbug/247613.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-21 13:20 <a href="http://www.blogjava.net/jvict/articles/247613.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>