博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于VerifyRenderingInServerForm方法的思考(转)
阅读量:5879 次
发布时间:2019-06-19

本文共 3699 字,大约阅读时间需要 12 分钟。

问题背景

在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文件,我们唯一的办法,就是阻止系统掉用控件的检查方法,防止抛出异常,导致系统调用默认的输出方法,从而导致整个页面的控件都被导出。

 

转载地址:http://hldix.baihongyu.com/

你可能感兴趣的文章
Android跨进程通信 AIDL使用
查看>>
ajax常见面试题
查看>>
结合kmp算法的匹配动画浅析其基本思想
查看>>
vue进行wepack打包执行npm run build出现错误
查看>>
nginx搭建
查看>>
【d3.js v4基础】过渡transition
查看>>
VUEJS开发规范
查看>>
Android系统的创世之初以及Activity的生命周期
查看>>
彻底解决Linux下memcached的安装
查看>>
人人都会数据采集- Scrapy 爬虫框架入门
查看>>
Android网络编程11之源码解析Retrofit
查看>>
esxi主机之添加新用户的访问权限
查看>>
AD账户被锁信息通知脚本
查看>>
数据集市和数据仓库的关系
查看>>
python 断言
查看>>
在Centos 5.6下面利用instant 安装oracle客户端
查看>>
用虚拟环境保存库文件--Python打包
查看>>
NoSQL数据库一MongoDB基本使用
查看>>
/proc/sys/vm/drop_caches用法备忘
查看>>
selinux 常用命令
查看>>