ASP.NET AJAX Advance Tips & Tricks (10) 解决使用AJAX Extender时的页面导出(Word/Excel)问题(Extender control 'XXX'
2017-02-09 08:34
851 查看
前言:
有客户问到这么个问题:我们可以使用Response容易地将ASP.NET页面导出为Excel或Word。然而,如果有AJAX Control Toolkit的Extender在页面上的话,则会发生错误(Extender control 'XXX' is not a registered extender control)。我搜索了一下,ASP.NET forum里有很多这样的问题未能解决,故写了这个解决方案,与大家分享。
问题重现:
首先,使用Response将ASP.NET页面导出为Excel或Word,代码比较简单,如下所示:public void ExportControl(System.Web.UI.Control source, DocumentType type,string name)
{
if (type == DocumentType.Excel)
{
//Excel
Response.AppendHeader("Content-Disposition", "attachment;filename="+name+".xls");
Response.ContentType = "application/ms-excel";
}
else if (type == DocumentType.Word)
{
//Word
Response.AppendHeader("Content-Disposition", "attachment;filename=" + name + ".doc");
Response.ContentType = "application/ms-word";
}
Response.Charset = "UTF-8";
Response.ContentEncoding = System.Text.Encoding.UTF8;
source.Page.EnableViewState = false;
System.IO.StringWriter writer = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWriter = new System.Web.UI.HtmlTextWriter(writer);
source.RenderControl(htmlWriter);
Response.Write(writer.ToString());
Response.End();
}
public enum DocumentType
{
Word,
Excel
}
然而,在下面的例子中,我们将会得到一个令人厌烦的错误:
<%@ Page Language="C#" EnableEventValidation = "false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Button2_Click(object sender, EventArgs e)
{
ExportControl(this, DocumentType.Word, "ExportWord");
}
public override void VerifyRenderingInServerForm(Control control)
{
}
public void ExportControl(System.Web.UI.Control source, DocumentType type,string name)
{
if (type == DocumentType.Excel)
{
//Excel
Response.AppendHeader("Content-Disposition", "attachment;filename="+name+".xls");
Response.ContentType = "application/ms-excel";
}
else if (type == DocumentType.Word)
{
//Word
Response.AppendHeader("Content-Disposition", "attachment;filename=" + name + ".doc");
Response.ContentType = "application/ms-word";
}
Response.Charset = "UTF-8";
Response.ContentEncoding = System.Text.Encoding.UTF8;
source.Page.EnableViewState = false;
System.IO.StringWriter writer = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWriter = new System.Web.UI.HtmlTextWriter(writer);
source.RenderControl(htmlWriter);
Response.Write(writer.ToString());
Response.End();
}
public enum DocumentType
{
Word,
Excel
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" />
</div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<ajaxToolkit:CalendarExtender ID="TextBox1_CalendarExtender" runat="server" Enabled="True"
TargetControlID="TextBox1">
</ajaxToolkit:CalendarExtender>
<br />
<br />
<br />
<asp:Panel ID="Panel1" runat="server" Height="100px" Width="194px" BackColor="Chocolate">
</asp:Panel>
<ajaxToolkit:RoundedCornersExtender ID="Panel1_RoundedCornersExtender" runat="server"
Enabled="True" TargetControlID="Panel1">
</ajaxToolkit:RoundedCornersExtender>
<br />
</p>
<asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="Download" />
</form>
</body>
</html>
错误信息如下:
Server Error in '/AjaxControlToolkitWebSite2' Application.
--------------------------------------------------------------------------------
Extender control 'TextBox1_CalendarExtender' is not a registered extender control. Extender controls must be registered using RegisterExtenderControl() before calling RegisterScriptDescriptors().
Parameter name: extenderControl
分析:
显然,问题是出现在AJAX Extender上,如果把页面上的AJAX Extender全部删除,则工作正常。有此,该问题的解决思路为“在导出之前移除页面上所有的Extender”
解决方案:
使用递归方式,在导出之前移除所有AJAX Extenders:
private void DisableAJAXExtenders(Control parent)
{
for (int i = 0; i < parent.Controls.Count; i++)
{
if (parent.Controls[i].GetType().ToString().IndexOf("Extender") != -1 && parent.Controls[i].ID != null)
{
parent.Controls.RemoveAt(i);
parent.Controls[i].Dispose();
}
if (parent.Controls[i].Controls.Count > 0)
{
DisableAJAXExtenders(parent.Controls[i]);
}
}
}
如下例所示,页面可成功导出为Word/Excel:
<%@ Page Language="C#" EnableEventValidation = "false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Button2_Click(object sender, EventArgs e)
{
//DisableAJAXExtenders(this);
ExportControl(this, DocumentType.Word, "ExportWord");
}
private void DisableAJAXExtenders(Control parent)
{
for (int i = 0; i < parent.Controls.Count; i++)
{
if (parent.Controls[i].GetType().ToString().IndexOf("Extender") != -1 && parent.Controls[i].ID != null)
{
parent.Controls.RemoveAt(i);
parent.Controls[i].Dispose();
}
if (parent.Controls[i].Controls.Count > 0)
{
DisableAJAXExtenders(parent.Controls[i]);
}
}
}
public override void VerifyRenderingInServerForm(Control control)
{
}
public void ExportControl(System.Web.UI.Control source, DocumentType type,string name)
{
if (type == DocumentType.Excel)
{
//Excel
Response.AppendHeader("Content-Disposition", "attachment;filename="+name+".xls");
Response.ContentType = "application/ms-excel";
}
else if (type == DocumentType.Word)
{
//Word
Response.AppendHeader("Content-Disposition", "attachment;filename=" + name + ".doc");
Response.ContentType = "application/ms-word";
}
Response.Charset = "UTF-8";
Response.ContentEncoding = System.Text.Encoding.UTF8;
source.Page.EnableViewState = false;
System.IO.StringWriter writer = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWriter = new System.Web.UI.HtmlTextWriter(writer);
source.RenderControl(htmlWriter);
Response.Write(writer.ToString());
Response.End();
}
public enum DocumentType
{
Word,
Excel
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true" />
</div>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<ajaxToolkit:CalendarExtender ID="TextBox1_CalendarExtender" runat="server" Enabled="True"
TargetControlID="TextBox1">
</ajaxToolkit:CalendarExtender>
<br />
<br />
<br />
<asp:Panel ID="Panel1" runat="server" Height="100px" Width="194px" BackColor="Chocolate">
</asp:Panel>
<ajaxToolkit:RoundedCornersExtender ID="Panel1_RoundedCornersExtender" runat="server"
Enabled="True" TargetControlID="Panel1">
</ajaxToolkit:RoundedCornersExtender>
<br />
<br />
<asp:Button ID="Button2" runat="server" OnClick="Button2_Click" Text="Download" />
</form>
</body>
</html>
PS:
一般情况下,如果想要移除页面上的所有AJAX Extender,也可以采用JavaScript的方式:function removeall() {
var currentBehavior = null;
var allBehaviors = Sys.Application.getComponents();
for (var loopIndex = 0; loopIndex < allBehaviors.length; loopIndex++) {
currentBehavior = allBehaviors[loopIndex];
currentBehavior.dispose();
}
}
相关Case:
http://forums.asp.net/t/1405746.aspxhttp://forums.asp.net/p/1078866/2082230.aspx
http://forums.asp.net/p/1242924/2275572.aspx
相关文章推荐
- ASP.NET AJAX Advance Tips & Tricks (9) DropDownList在Firefox下的奇怪现象和解决方案——谁的BUG?
- 【Asp.Net】Sql Server数据库的连接方式
- 【ASP.NET Web API教程】2.3.3 创建Admin控制器
- ASP.NET MVC 5 (五)c#的lambda表达式、LinQ和Async异步处理
- asp中sub与function的区别
- ASP.NET下使用Combres对JS、CSS合并和压缩
- ASP.NET中相对路径的使用总结
- asp.net mvc3 数据验证(三)—自定义数据注解
- ASP.net MVC Response.End(); 之后的代码还会执行
- ASP.NET MVC4 WEB API入门 第二篇:ASP.NET MVC入门基础(1)——项目框架搭建
- .net cs后台刷新aspx页面的四种方式
- asp中如何判断数据插入成功失败
- ASP.NET MVC5----了解我们使用的@HTML帮助类
- 一、AspectJ概论
- pjax使用心得
- ASP中冒号: 和 下划线_ 的作用
- N 个 ASP.net DropDownList 无刷新联动菜单
- ASP.NET MVC5 支持PUT 和DELETE
- asp.net权限认证篇外:集成域账号登录
- ASP.NET Core MVC 中设置全局异常处理方式