您的位置:首页 > 编程语言 > ASP

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.aspx

http://forums.asp.net/p/1078866/2082230.aspx

http://forums.asp.net/p/1242924/2275572.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: