“因为控件包含代码块,所以无法修改 Controls 集合。”

396

我试图创建一个简单的用户控件,它是一个滑块。当我在用户控件中添加 AjaxToolkit 的 SliderExtender 时,我会遇到这个错误:(*&$#()@#)。

Server Error in '/' Application. The Controls collection cannot be modified because the control contains code blocks (i.e. `<% ... %>`). Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: The Controls collection cannot be modified because the control contains code blocks (i.e. `<% ... %>`).

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[HttpException (0x80004005): The Controls collection cannot be modified because the control contains code blocks (i.e. `<% ... %>`).]    System.Web.UI.ControlCollection.Add(Control child) +8677431    AjaxControlToolkit.ScriptObjectBuilder.RegisterCssReferences(Control control) in d:\E\AjaxTk-AjaxControlToolkit\Release\AjaxControlToolkit\ExtenderBase\ScriptObjectBuilder.cs:293 AjaxControlToolkit.ExtenderControlBase.OnLoad(EventArgs e) in d:\E\AjaxTk-AjaxControlToolkit\Release\AjaxControlToolkit\ExtenderBase\ExtenderControlBase.cs:306 System.Web.UI.Control.LoadRecursive()
+50    System.Web.UI.Control.LoadRecursive()
+141    System.Web.UI.Control.LoadRecursive()
+141    System.Web.UI.Control.LoadRecursive()
+141    System.Web.UI.Control.LoadRecursive()             
+141    System.Web.UI.Control.LoadRecursive()
+141    System.Web.UI.Control.LoadRecursive()
+141    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +627


Version Information: Microsoft .NET Framework Version:2.0.50727.3074; ASP.NET Version:2.0.50727.3074

我尝试在用户控件中添加占位符,然后以编程方式将文本框和滑块扩展程序添加到占位符中,但仍然出现错误。
以下是简单的代码:
<table cellpadding="0" cellspacing="0" style="width:100%">
    <tbody>
        <tr>
            <td></td>
            <td>
                <asp:Label ID="lblMaxValue" runat="server" Text="Maximum" CssClass="float_right" />
                <asp:Label ID="lblMinValue" runat="server" Text="Minimum" />
            </td>
        </tr>
        <tr>
            <td style="width:60%;">
                <asp:CheckBox ID="chkOn" runat="server" />
                <asp:Label ID="lblPrefix" runat="server" />:&nbsp;
                <asp:Label ID="lblSliderValue" runat="server" />&nbsp;
                <asp:Label ID="lblSuffix" runat="server" />
            </td>
            <td style="text-align:right;width:40%;">                

                    <asp:TextBox ID="txtSlider" runat="server" Text="50" style="display:none;" />
                    <ajaxToolkit:SliderExtender ID="seSlider" runat="server" 
                        BehaviorID="seSlider" 
                        TargetControlID="txtSlider" 
                        BoundControlID="lblSliderValue" 
                        Orientation="Horizontal" 
                        EnableHandleAnimation="true" 
                        Length="200" 
                        Minimum="0" 
                        Maximum="100" 
                        Steps="1" />

            </td>
        </tr>
    </tbody>
</table>

问题是什么?


16
导致我的错误是在 <script> 和 <link> 标签内使用 <%= Resolve(); %> 函数。我最终解决了这个问题。而不是删除通常会导致此错误的 head 标签中的有问题代码,只需将所有有问题的代码放入 asp:ContentPlaceHolder</asp:ContentPlaceHolder> 标记中即可。 - Daniel P
包含对“@Daniel P”建议的更长解释。 - lko
谢谢Daniel P,你的评论解决了问题。我试图使用ResolveUrl来修复@font-face中的真实URL或下载Master Page中的字体 - 不幸的是,Master Page可能会从不同于路由的位置运行 - 这导致部分URL错误。所以我需要ResolveUrl来工作 - 但你解决的错误解决了这个问题。谢谢!我把我的样式放在asp:ContentPlaceHolder</asp:ContentPlaceHolder>里面。 - John Foll
22个回答

516

首先,将代码块以<%#开头而不是<%= :

<head id="head1" runat="server">
  <title>My Page</title>
  <link href="css/common.css" rel="stylesheet" type="text/css" />
  <script type="text/javascript" src="<%# ResolveUrl("~/javascript/leesUtils.js") %>"></script>
</head>

这会将代码块从 Response.Write 代码块更改为数据绑定表达式。
由于 <%# ... %> 数据绑定表达式不是代码块,CLR 不会抱怨。然后,在母版页的代码中,您需要添加以下内容:

protected void Page_Load(object sender, EventArgs e)
{
  Page.Header.DataBind();    
}

3
在切换到ASP.NET 4后,我似乎开始出现了这个问题。这是新框架特有的吗? - Corgalore
4
把我的 JavaScript 代码从 HEAD 标签移到页面底部后,问题就解决了。 - Miank
1
这是一个与.NET相关的奇怪错误。为什么要用#而不是=,我永远无法理解,虽然我已经做了多年,但真希望知道为什么! - Mark Pieszak - Trilon.io
1
如果有不需要披着斗篷的英雄,他们就存在! - Julián
2
对我有用!谢谢!! - Ben
显示剩余4条评论

283

我也遇到了这个问题,但找到了另一种解决方案。

我发现将代码块用 asp:PlaceHolder 标记包装起来可以解决这个问题。

<asp:PlaceHolder runat="server">
  <meta name="ROBOTS" content="<%= this.ViewData["RobotsMeta"] %>" />
</asp:PlaceHolder>

我使用的 CMS 在某些代码后面插入了头部区域,这限制了我添加包含各种信息(如元标记)的自定义控件块的能力,所以这是我唯一的解决方法。


13
太棒了。作为Telerik控件的过去用户,我经常使用他们的“RadCodeBlock”来实现同样的目的,但总是因为除此之外我不知道还有其他的东西(或者像其他人提到的,将代码移入专门运行服务器端的标签内),而感到烦恼。我从未知道这些占位符中可以放置内容。谢谢! - JayC
1
谢谢@JayC,RadCodeBlock是这个页面上唯一能与我继承的代码配合使用的建议,出于各种原因。 - shiser
1
这也发生在已注册的DevExpress控件中。我有两个Web应用程序,几乎具有相同的代码、配置和主页面。只有使用DevExpress的那个需要像这样的解决方法。我认为这与他们的HTTP处理程序、资源程序集或类似的东西搞砸了管道有关。我们现在正在转向第三方库,支持JQuery和MVC,这可以避免复杂的服务器端代码/处理程序。 - Tony Wall
1
实际上,只需要用<div runat="server"><%= (...) %></div>将其包装起来即可。 - Chris W
8
很简单 - 在容器中使用代码块意味着您不能再更新该容器的“Controls”。这基本上是通过将代码块放在单独的容器中来利用这种行为 - 因此,只有在您想要修改PlaceHolderControls而不是父控件时才会显示错误。 PlaceHolder是一个很好的选择,因为它没有自己的代码(不像Panel<div runat =“server”>)。尽管我通常是相反的 - 将我需要修改的控件放在PlaceHolder中。 - Luaan
显示剩余2条评论

62

1
是的,刚刚确认了,从头部删除 ASP 标签 <% %> 可以解决这个错误。 - Corgalore
+1,已确认。然而对我来说,问题脚本位于head和form元素之外。 - user420667
1
确认。对我来说非常好用。只是不要忘记检查您的主页面上的脚本,因为这是导致我麻烦的原因,我花了半个小时才弄清楚这不是我的aspx :P - Luis Hernández
是的,这对我也有效,但是为什么呢?在母版文件中的<HEAD>标记是否纯粹用于母版文件而不用于子aspx文件?我之所以问,是因为我正在尝试在驻留在母版文件中的子aspx页面中运行JS代码。 - Fandango68
2
这个答案是一个默默无闻的英雄。 - GreySage
我以一种奇怪的方式遇到了相同的错误,我的主页面中有CSS文件。它在第一页上运行正常,但在重定向后的第二页上出现错误。因此,我从head标签中删除了CSS链接,并将其粘贴到form标签的末尾。 - raw_hitt

33

将JavaScript放置在一个div标签下面。

<div runat="server"> //div tag must have runat server
  //Your JavaScript code goes here....
</div>

它会起作用的!!


6
最好使用占位符,这样就不会输出额外的HTML代码。 - Chris Haines
1
这个可以工作,尽管Visual Studio说将<div>嵌套在<head>中违反了HTML5标准。 - Adi Inbar
在我看来,如果HTML5无法验证,则不是最佳解决方案,请避免在头部使用div - PreguntonCojoneroCabrón

9
如果您在页面中使用脚本管理器,那么您可以执行相同的功能。您只需要像这样注册脚本:
<asp:ScriptManager ID="ScriptManager1" runat="server" LoadScriptsBeforeUI="true"   EnablePageMethods="true">  
<Scripts>
      <asp:ScriptReference Path="~/Styles/javascript/jquery.min.js" />
</Scripts>
</asp:ScriptManager>

ScriptManager不能将脚本添加到head部分吗? - Kiquenet

6

我曾尝试使用<%# %>,但没有成功。后来我将代码中的Page.Header.DataBind();改为this.Header.DataBind();,然后就可以正常工作了。


5

我在用户控件中遇到了同样的问题。承载控件的页面在头部标签中有注释,我删除了这些注释后,一切就正常了。一些帖子还建议将脚本从头部移除并放在正文中。


4
在我的情况下,我已经用<%# %>替换了<%= %>,并且它起作用了!

3

将JavaScript代码放在body标签内

<body> 
   <script type="text/javascript">
   </script>
</body>

2

我曾经遇到过这个问题,但是并不是在头部。我的占位符在主体中。所以我用<%#替换了所有的<%=,然后进行了操作。

protected void Page_Load(object sender, EventArgs e)
{
    Page.Header.DataBind();    
}

它成功了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接