异步 WebForms 页面中的 AjaxControlToolkit 问题
AjaxControlToolkit issue in Async WebForms pages
运行 异步任务的 WebForms 页面中的 AjaxControlToolkit 扩展程序(或任何其他扩展程序)存在问题。如果您的扩展程序最初不可见,并且您 运行 一个异步任务使其可见(例如,如果可见性应根据您异步读取的数据确定),那么您将得到以下内容 System.ArgumentException:
Extender control '[ControlID]' is not a registered extender control.
Extender controls must be registered using RegisterExtenderControl() before calling RegisterScriptDescriptors().
经过一番分析,原因如下。
- ExtenderControl base class,所有 AjaxControlToolkit 扩展器
subclass,在其调用
ScriptManager.RegisterExtenderControl()
OnPreRender
方法。此外,ScriptManager 会抛出异常
如果 RegisterExtenderControl()
在除
预渲染。
- 对于在 PreRender 阶段不可见的控件,
OnPreRender
方法不会被调用,因此扩展器
控件将不会被注册。
- WebForms 页面 运行 所有异步任务 在 PreRender 阶段 之后,以及
在渲染阶段之前。所以,如果你让你的扩展器可见
异步任务,那么它在 PreRender 中还不可见
阶段,并且只在渲染阶段。
- 最后,扩展器控制调用
ScriptManager.RegisterScriptDescriptors()
在渲染阶段,
由于控件没有被抛出上述异常
在 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
运行 异步任务的 WebForms 页面中的 AjaxControlToolkit 扩展程序(或任何其他扩展程序)存在问题。如果您的扩展程序最初不可见,并且您 运行 一个异步任务使其可见(例如,如果可见性应根据您异步读取的数据确定),那么您将得到以下内容 System.ArgumentException:
Extender control '[ControlID]' is not a registered extender control.
Extender controls must be registered using RegisterExtenderControl() before calling RegisterScriptDescriptors().
经过一番分析,原因如下。
- ExtenderControl base class,所有 AjaxControlToolkit 扩展器
subclass,在其调用
ScriptManager.RegisterExtenderControl()
OnPreRender
方法。此外,ScriptManager 会抛出异常 如果RegisterExtenderControl()
在除 预渲染。 - 对于在 PreRender 阶段不可见的控件,
OnPreRender
方法不会被调用,因此扩展器 控件将不会被注册。 - WebForms 页面 运行 所有异步任务 在 PreRender 阶段 之后,以及 在渲染阶段之前。所以,如果你让你的扩展器可见 异步任务,那么它在 PreRender 中还不可见 阶段,并且只在渲染阶段。
- 最后,扩展器控制调用
ScriptManager.RegisterScriptDescriptors()
在渲染阶段, 由于控件没有被抛出上述异常 在 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