关于VerifyRenderingInServerForm方法的思考

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

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值