关于VerifyRenderingInServerForm方法的思考
2010-01-24 13:40
330 查看
问题背景
在BS项目中,把分页的gridview的数据(不只是导出当前页的数据),全部导出为Excel文件(这里特指绘制页面的方式),碰到三个问题;
问题1,身份证编号数字不能正常显示(后面几位变成0并且会显示成科学计算符)
问题2,虽然,我在demo中,直接把gridview的数据绘制出来,结果页面上的所有控件都绘制出来了
解决问题
第一个问题很好解决,google了下,发现将 GridView 导出Excel 时,身份证号码被改为科学计数法显示,所有,我们只要改变一下身份证编号的数据类型就可以了
比如改成字符类。
我们在导出的时候把类型改掉
//
注意gridView.Rows[count].Cells[3]
for
(
int
count
=
0
; count
<
gridView.Rows.Count; count
++
)
{
gridView.Rows[count].Cells[
3
].Text
=
"
'
"
+
gridView.Rows[count].Cells[
3
].Text;
}
这里,我把数字类型改成了字符类型,而且在身份证编号前加了个“'”号,这样就解决了数字过长,尾数都变成0的问题,而且也解决了身份证号码被改为科学计数法显示的问题。
至于第二个问题,比较麻烦,我跟踪了好几次,都没有发现原因,先来看完整的demo
/**/
///
<summary>
///
导出数据到Excel、Word表格
///
</summary>
///
<param name="gridView"></param>
///
<param name="hideColumns">
需要隐藏的列的索引
</param>
///
<param name="fileExt">
文件名后缀
</param>
public
static
void
Export(System.Web.UI.WebControls.GridView gridView,
int
[] hideColumns,
string
fileExt)
{
HttpContext context
=
HttpContext.Current;
try
{
context.Response.ClearContent();
context.Response.Clear();
context.Response.ContentEncoding
=
System.Text.Encoding.UTF7;
context.Response.AddHeader(
"
content-disposition
"
,
string
.Format(
"
attachment; filename=Page{0}.{1}
"
, gridView.PageIndex
+
1
, fileExt));
switch
(fileExt.ToLower())
{
case
"
xls
"
:
default
:
context.Response.ContentType
=
"
application/excel
"
;
break
;
case
"
doc
"
:
context.Response.ContentType
=
"
application/word
"
;
break
;
}
System.IO.StringWriter sw
=
new
System.IO.StringWriter();
HtmlTextWriter htw
=
new
HtmlTextWriter(sw);
//
注意gridView.Rows[count].Cells[3]
for
(
int
count
=
0
; count
<
gridView.Rows.Count; count
++
)
{
gridView.Rows[count].Cells[
3
].Text
=
"
'
"
+
gridView.Rows[count].Cells[
3
].Text;
}
//
for (int i = 0; i < gridView.Controls.Count; i++)
//
{
//
if (gridView.Controls[i].GetType() == typeof(Button))
//
{
//
gridView.Controls.Remove(gridView.Controls[i]);
//
}
//
}
if
(hideColumns
!=
null
)
{
foreach
(
int
columnIndex
in
hideColumns)
{
if
(columnIndex
<
gridView.Columns.Count)
{
gridView.Columns[columnIndex].Visible
=
false
;
}
}
}
//
如果HeaderRow里的控件是button的话,则把它替换成文本
foreach
(TableCell tc
in
gridView.HeaderRow.Cells)
{
//
TableCell里的每个Control
foreach
(Control c
in
tc.Controls)
{
//
如果控件继承自接口IButtonControl
if
(c.GetType().GetInterface(
"
IButtonControl
"
)
!=
null
&&
c.GetType().GetInterface(
"
IButtonControl
"
).Equals(
typeof
(IButtonControl)))
{
//
如果该控件不是“导出Excel”按钮则把button转换成文本
tc.Controls.Clear();
tc.Text
=
((IButtonControl)c).Text;
}
}
}
//
清空页脚控件
if
(gridView.BottomPagerRow
!=
null
)
gridView.BottomPagerRow.Controls.Clear();
//
.f.Cells[2].Controls.Clear();
//
将服务器控件的内容输出到所提供的 System.Web.UI.HtmlTextWriter 对象中
gridView.RenderControl(htw);
context.Response.Write(sw.ToString());
context.Response.End();
}
catch
(Exception ex)
{
}
}
注意,红色和黄色的两行代码,其作用就是把gridview的页脚控件清除掉,不导出到Excel文件,以免影响Excel的美观。
事实上,很多情况,都不是我们一开始就能全部考虑得到的,比如我在清除gridview的页脚控件的时候,忘记考虑gridview有时候,数据不满一页的时候,就没有页脚控件,如果不加判断if
(gridView.BottomPagerRow
!=
null
)
,在清除页脚控件的时候,肯定会报null异常。
事实上,只要在发生异常,代码的调度直接进入catch块中,那么我们自定义的输出代码就不会执行context.Response.Write(sw.ToString()),系统转而把整个页面都输出来了,所有我们就会看到不需要的一些控件也被导出来了。
事实上,问题到此,并没有完全解决,还是会把真个页面上的控件都导出来。
我们先休息一下,我们会发现,当我们点击导出Button的时候,响应给我们的输出流是一个excel页,而非默认的aspx页(context.Response.ContentType
=
"
application/excel
"
;
),这样新的问题又来了,页面上的控件在rendering的时候,都会调用VerifyRenderingInServerForm方法,来检查当前控件是否在ServerForm标记内(调试过,确实如此)。很明显,我们输出的文档类型是"
application/excel
"
,而非默认的"text/html"类型,控件当然不在Form之中,因此也会抛出异常(控件不在Form中的异常),结果,系统又调用默认的输出流,把整个页都导出来了(shit)。
这个问题,很好解决,重写VerifyRenderingInServerForm方法,什么事也不干(也就是阻止系统调用默认的VerifyRenderingInServerForm方法)
public
override
void
VerifyRenderingInServerForm(System.Web.UI.Control control)
{
//
base.VerifyRenderingInServerForm(control);
}
总结
问题的关键是导出excel的时候,输出文件已经不是合法的aspx文件,我们唯一的办法,就是阻止系统掉用控件的检查方法,防止抛出异常,导致系统调用默认的输出方法,从而导致整个页面的控件都被导出。
在BS项目中,把分页的gridview的数据(不只是导出当前页的数据),全部导出为Excel文件(这里特指绘制页面的方式),碰到三个问题;
问题1,身份证编号数字不能正常显示(后面几位变成0并且会显示成科学计算符)
问题2,虽然,我在demo中,直接把gridview的数据绘制出来,结果页面上的所有控件都绘制出来了
解决问题
第一个问题很好解决,google了下,发现将 GridView 导出Excel 时,身份证号码被改为科学计数法显示,所有,我们只要改变一下身份证编号的数据类型就可以了
比如改成字符类。
我们在导出的时候把类型改掉
//
注意gridView.Rows[count].Cells[3]
for
(
int
count
=
0
; count
<
gridView.Rows.Count; count
++
)
{
gridView.Rows[count].Cells[
3
].Text
=
"
'
"
+
gridView.Rows[count].Cells[
3
].Text;
}
这里,我把数字类型改成了字符类型,而且在身份证编号前加了个“'”号,这样就解决了数字过长,尾数都变成0的问题,而且也解决了身份证号码被改为科学计数法显示的问题。
至于第二个问题,比较麻烦,我跟踪了好几次,都没有发现原因,先来看完整的demo
/**/
///
<summary>
///
导出数据到Excel、Word表格
///
</summary>
///
<param name="gridView"></param>
///
<param name="hideColumns">
需要隐藏的列的索引
</param>
///
<param name="fileExt">
文件名后缀
</param>
public
static
void
Export(System.Web.UI.WebControls.GridView gridView,
int
[] hideColumns,
string
fileExt)
{
HttpContext context
=
HttpContext.Current;
try
{
context.Response.ClearContent();
context.Response.Clear();
context.Response.ContentEncoding
=
System.Text.Encoding.UTF7;
context.Response.AddHeader(
"
content-disposition
"
,
string
.Format(
"
attachment; filename=Page{0}.{1}
"
, gridView.PageIndex
+
1
, fileExt));
switch
(fileExt.ToLower())
{
case
"
xls
"
:
default
:
context.Response.ContentType
=
"
application/excel
"
;
break
;
case
"
doc
"
:
context.Response.ContentType
=
"
application/word
"
;
break
;
}
System.IO.StringWriter sw
=
new
System.IO.StringWriter();
HtmlTextWriter htw
=
new
HtmlTextWriter(sw);
//
注意gridView.Rows[count].Cells[3]
for
(
int
count
=
0
; count
<
gridView.Rows.Count; count
++
)
{
gridView.Rows[count].Cells[
3
].Text
=
"
'
"
+
gridView.Rows[count].Cells[
3
].Text;
}
//
for (int i = 0; i < gridView.Controls.Count; i++)
//
{
//
if (gridView.Controls[i].GetType() == typeof(Button))
//
{
//
gridView.Controls.Remove(gridView.Controls[i]);
//
}
//
}
if
(hideColumns
!=
null
)
{
foreach
(
int
columnIndex
in
hideColumns)
{
if
(columnIndex
<
gridView.Columns.Count)
{
gridView.Columns[columnIndex].Visible
=
false
;
}
}
}
//
如果HeaderRow里的控件是button的话,则把它替换成文本
foreach
(TableCell tc
in
gridView.HeaderRow.Cells)
{
//
TableCell里的每个Control
foreach
(Control c
in
tc.Controls)
{
//
如果控件继承自接口IButtonControl
if
(c.GetType().GetInterface(
"
IButtonControl
"
)
!=
null
&&
c.GetType().GetInterface(
"
IButtonControl
"
).Equals(
typeof
(IButtonControl)))
{
//
如果该控件不是“导出Excel”按钮则把button转换成文本
tc.Controls.Clear();
tc.Text
=
((IButtonControl)c).Text;
}
}
}
//
清空页脚控件
if
(gridView.BottomPagerRow
!=
null
)
gridView.BottomPagerRow.Controls.Clear();
//
.f.Cells[2].Controls.Clear();
//
将服务器控件的内容输出到所提供的 System.Web.UI.HtmlTextWriter 对象中
gridView.RenderControl(htw);
context.Response.Write(sw.ToString());
context.Response.End();
}
catch
(Exception ex)
{
}
}
注意,红色和黄色的两行代码,其作用就是把gridview的页脚控件清除掉,不导出到Excel文件,以免影响Excel的美观。
事实上,很多情况,都不是我们一开始就能全部考虑得到的,比如我在清除gridview的页脚控件的时候,忘记考虑gridview有时候,数据不满一页的时候,就没有页脚控件,如果不加判断if
(gridView.BottomPagerRow
!=
null
)
,在清除页脚控件的时候,肯定会报null异常。
事实上,只要在发生异常,代码的调度直接进入catch块中,那么我们自定义的输出代码就不会执行context.Response.Write(sw.ToString()),系统转而把整个页面都输出来了,所有我们就会看到不需要的一些控件也被导出来了。
事实上,问题到此,并没有完全解决,还是会把真个页面上的控件都导出来。
我们先休息一下,我们会发现,当我们点击导出Button的时候,响应给我们的输出流是一个excel页,而非默认的aspx页(context.Response.ContentType
=
"
application/excel
"
;
),这样新的问题又来了,页面上的控件在rendering的时候,都会调用VerifyRenderingInServerForm方法,来检查当前控件是否在ServerForm标记内(调试过,确实如此)。很明显,我们输出的文档类型是"
application/excel
"
,而非默认的"text/html"类型,控件当然不在Form之中,因此也会抛出异常(控件不在Form中的异常),结果,系统又调用默认的输出流,把整个页都导出来了(shit)。
这个问题,很好解决,重写VerifyRenderingInServerForm方法,什么事也不干(也就是阻止系统调用默认的VerifyRenderingInServerForm方法)
public
override
void
VerifyRenderingInServerForm(System.Web.UI.Control control)
{
//
base.VerifyRenderingInServerForm(control);
}
总结
问题的关键是导出excel的时候,输出文件已经不是合法的aspx文件,我们唯一的办法,就是阻止系统掉用控件的检查方法,防止抛出异常,导致系统调用默认的输出方法,从而导致整个页面的控件都被导出。
相关文章推荐
- 关于VerifyRenderingInServerForm方法的思考
- 关于VerifyRenderingInServerForm方法的思考
- 关于VerifyRenderingInServerForm方法的思考(转)
- VerifyRenderingInServerForm和EnableEventValidation引发的两个问题
- Render Control to HTML String. VerifyRenderingInServerForm Method
- VerifyRenderingInServerForm和EnableEventValidation引发的两个问题
- VerifyRenderingInServerForm和EnableEventValidation引发的两个问题
- 在VS2005中 GridView导入Excel的两点小技巧 VerifyRenderingInServerForm
- 关于VC++6.0加载控件出现Unable to register this add-in because its DllRegisterServer returns an error 的解决方法
- 关于The target "GetCopyToOutputDirectoryContentProjectItems" does not exist in the project.的解决方法
- 关于使用jquery.form.js上传文件同时提交表单的方法
- Extjs6关于Ajax和form表单提交以及store请求session超时的处理方法
- 关于java字节流的read()方法返回int型而非byte型的思考
- .NET 关于从客户端(...)中检测到有潜在危险的Request.Form 值的处理办法 找不到方法:System.Web.UnvalidatedRequestValues报错的处理方案(待完善)
- [软件工程]关于SEMAT方法的思考和银弹问题的探索
- 关于部署zabbix时提示zabbix server is not running错误的处理方法
- SQL SERVER中关于exists 和 in的简单分析
- 关于cocos2d-x几种画图方法的用法与思考
- 关于软件防止破解的思考,如何避免简单的跳转指令型的验证方法,如何设置更复杂的验证方式。
- 关于cocos2d-x几种画图方法的用法与思考