asp.net - 异步 WebForms 页面中的 AjaxControlToolkit 问题
问题描述
运行异步任务的 WebForms 页面中的 AjaxControlToolkit 扩展程序(或任何其他扩展程序)存在问题。如果您的扩展程序最初是不可见的,并且您运行了一个异步任务,使其可见(例如,如果应根据您异步读取的数据确定可见性),那么您将获得以下 System.ArgumentException:
Extender control '[ControlID]' is not a registered extender control.
Extender controls must be registered using RegisterExtenderControl() before calling RegisterScriptDescriptors().
经过一番分析,这是造成这种情况的原因。
- 所有 AjaxControlToolkit 扩展程序子类的 ExtenderControl 基类
ScriptManager.RegisterExtenderControl()
在其OnPreRender
方法中调用。RegisterExtenderControl()
此外,如果在 PreRender 以外的任何阶段调用ScriptManager,都会抛出异常。 - 对于在 PreRender 阶段不可见的控件,
OnPreRender
不会调用该方法,因此不会注册扩展器控件。 - WebForms 页面在 PreRender 阶段之后和 Render 阶段之前运行所有异步任务。所以,如果你让你的扩展器在异步任务中可见,那么它在 PreRender 阶段是不可见的,只有在 Render 阶段才可见。
- 最后,扩展器控件
ScriptManager.RegisterScriptDescriptors()
在Render阶段调用,由于控件没有在PreRender阶段注册,抛出上述异常。
有没有人找到解决方法或解决方法?
这似乎是 WebForms 中的一个巨大限制,您无法在同一页面中有效地同时使用异步任务和扩展器控件。
以下是说明此问题的示例网页。
<%@ Page Async="true" MasterPageFile="~/Site.Master" Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.Page" %>
<%@ Import Namespace="System.Threading.Tasks" %>
<%@ Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="ajaxToolkit" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<asp:Panel ID="Panel1" runat="server">
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<ajaxToolkit:CalendarExtender ID="CalendarExtender1" runat="server" TargetControlID="TextBox1" />
</asp:Panel>
</asp:Content>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
Panel1.Visible = false;
RegisterAsyncTask(new PageAsyncTask(ReadAsync));
}
// Making the panel visible below will result in the following exception:
// Extender control 'CalendarExtender1' is not a registered extender control.
// Extender controls must be registered using RegisterExtenderControl() before calling RegisterScriptDescriptors().
private async Task ReadAsync()
{
Panel1.Visible = true;
await Task.CompletedTask;
}
</script>
解决方案
根据在此处https://forums.asp.net/p/2163988/6293999.aspx?p=True&t=637169211245961059 和此处https://github.com/DevExpress/AjaxControlToolkit/issues/523发布到此问题的建议 ,我已经想出了一个通用的方法来解决这个问题。
基本上,您的页面将跟踪具有扩展器的控件,并且可以在异步任务中运行时更改其可见性。然后它将在适当的时间在 PreRender 上使这些控件暂时可见以避免错误,然后在 PreRender 完成后根据需要隐藏它们。这里的关键是使用页面的新SetControlVisible
方法来设置控件的可见性。
此解决方法的完整源代码发布在此处:https ://github.com/Xomega-Net/XomegaFramework/blob/master/src/Xomega.Framework.Web/Views/WebPage.cs
推荐阅读
- java - Lucene 停用词和 nGram
- excel - 谷歌表格 - 如果在一行中找到一个单词,如何写入单元格的值
- android - 如何实现屏幕解锁计数器,即使我们关闭应用程序它也会继续计数?
- scala - Scala中参数限制为AnyRef和AnyVal时的冲突方法
- excel - 通过 excel-vba 生成和发送的 ZPL 代码打印条码
- javascript - 我如何在 react 中的 node_modules 文件夹上运行 jest 测试
- java - 通过 REST API 控制 Jenkins
- javascript - 工作箱构建不生成服务工作者
- javascript - 如何从画布上删除前一帧的矩形?
- ruby-on-rails - Rails 有很多通过关联 - 使用包含