The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Bummer. I've been mucking around with some more custom databinding that integrates validation into the databinding process. One of the things the control does is automatically add 'notification' icons or error text to the page. The idea is this:
- Control(s) unbind
- If there are binding errors an Icon or Message is injected into the Control Collection
Basically the code looks something like this:
public bool AddBindingError(string ErrorMessage, wwDataBindingItem BindingItem)
{
// *** Associated control found - add icon and link id
if (BindingItem.ControlInstance != null)
this.BindingErrors.Add(new BindingError(ErrorMessage, BindingItem.ControlInstance.ClientID));
else
{
// *** Just set the error message
this.BindingErrors.Add(new BindingError(ErrorMessage) );
return false;
}
BindingItem.BindingErrorMessage = ErrorMessage;
// *** Insert the error text/icon as a literal
if (this.ShowBindingErrorsOnControls && BindingItem.ControlInstance != null)
{
LiteralControl Literal = new LiteralControl(this.GetBindingErrorMessageHtml(BindingItem));
int CtlIdx = BindingItem.ControlInstance.Parent.Controls.IndexOf(BindingItem.ControlInstance);
try
{
// *** Can't add controls to the Control collection if <%= %> tags are on the page
BindingItem.ControlInstance.Parent.Controls.AddAt(CtlIdx + 1, Literal);
}
catch {;}
}
return true;
}
And it works beautifully in most situations. The literal control creates markup that loads the appropriate image and adds the error text (if configured that way).
This all works great until you happen to have some script markup on the page using. For example if the page contains something as simple as this:
<%= DateTime.Now %>
The Controls.AddAt() call will fail with:
The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Now I feel like a complete schmuck to never have run into this before. That's one hell of an assumption to miss about ASP.NET it seems. I have tons of pages where there's <%= %> markup on it. Especially in script code to get the appropariate ClientID:
<%= this.txtCompany.ClientID %>
Luckily there's a workaround for code like this by using DataBinding expressions instead:
<%# this.txtCompany.ClientID %>
This works fine for simple expressions. The difference here is that <%= %> expressions are embedded into the ASP.NET output as part of the generated Parse Tree class, whereas the <%# %> expressions are embedded at runtime.
Another workaround is to force any script code into the content of a server control and remove it from the Page class or the Content container that you're adding controls to.
<div runat="server">
<script type="text/javascript">
function ShowCreditCard()
{
var IsPayPal = false;
for(x=0; x<4; x++ )
{
var ctl = $("<%= this.txtCCType.ClientID %>_" + x.toString());
if (ctl == null)
break;
if (ctl.value == "PP" && ctl.checked)
{
IsPayPal = true;
break;
}
}
var loCC = $("<%= this.trCreditCard.ClientID %>");
if (loCC == null)
return;
var loCC2 = $("<%= this.trCreditCardExpiration.ClientID %>");
if (IsPayPal)
{
loCC.style.display = "none";
loCC2.style.display = "none";
}
else
{
loCC.style.display = "";
loCC2.style.display = "";
}
}
</script>
</div>
This works as well, although this is also pretty ugly. In my case this is probably the easier solution though, because most of my markup expressions are doing exactly what's happening above: Embedding ClientScript Ids into JavaScript.
I still don't see why the control collection can't be modified if there are <% %> blocks on the page. Those blocks are just turned into Response.Write() commands, or raw code blocks. I don't see how this affects the Controls collection that would require this sort of error.
In my situation here I was able to get by just switching to <%# %> or wrapping sections with a server tag. Even if that's not an option the above code captures the error and goes on. This means the warning icons don't show up, but the rest of the error handling showing the summary and error control linking etc. all still works.
Can anybody think of another more reliable way to inject markup into the page dynamically from outside of the control rendering? In a previous rev of my databinding tools I had custom controls and I simply took over post rendering which was reliable. But this is not so easily done externally… I can think of possibly hooking up the Render method and calling back into my custom control, but man does that seem ugly.
The Voices of Reason
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. &lt;% ... %&gt;).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. &lt;% ... %&gt;).
http://www.aspnetresources.com/blog/code_blocks_inside_master_pages_cause_trouble.aspx
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. &lt;% ... %&gt;).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. &lt;% ... %&gt;).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. &lt;% ... %&gt;).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# More info on why the error occurs
http://west-wind.com/WebLog/posts/6148.aspx
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
I had some code like the following in my head to link a CSS:
The RssHyperLink control was causing it to break because it's trying to add a literal control in to the head for the link.
I solved it by putting in a PlaceHolder property and then putting a placeholder in to my head and then finding all of the rsshyperlink controls and passing it along.
There has to be a better way, but it's fixed it for me.
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
<link rel="stylesheet" type="text/css" href="<%=ResolveUrl("~/css/global.css")%>" media="screen" />
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
I love you
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
<asp:ImageButton runat="Server" ID="calImage" ImageUrl="/images/Calendar.gif" AlternateText="Click to show calendar" /><br />
<ajaxToolkit:CalendarExtender ID="calendarButtonExtender" runat="server" TargetControlID="txtTestedDate"
PopupButtonID="calImage" />
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Thanks!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
var moo = "<asp:Literal runat="server" id="litMonkey"></asp:Literal>";
then in the code-behind...
litMonkey.Text = objMonkey.ClientID
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Timmus
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Your blog is a gem!!! Keep up :)
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
The problem went away once I removed the <%# %> from the javascript in the header. I would not call this a 'fix' though. I was able to work around the absence of the code block in the script this time, but may not be able to in the future.
I have also managed to add some key script code dynamically in server-side code (for instance, creating variables and all the script, but add assignments to those variables server-side)
Good blog!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
When the MaskedEditExtender/CalendarExtender is used, a <LINK ...> tag to a stylesheet will result in this error. One workaround is to move the CSS file to a theme folder and add a reference to the theme in the web.config file <pages theme="themeName">. Each page needs to have the "<head>" tag replaced with "<head runat="server"> and any "<LINK ...>" tags removed.
Also, comments in the HEAD section can cause this problem. Take the following javascript example:
function DelLot()
{ // Called to delete the order.
// true means it was deleted -- false means it was not.
// return(window.showModalDialog("AskDelete.aspx?MODE=D&EBID=<%=nID%>", null,"dialogwidth:600px;dialogHeight:400px;help:no;resizable:no;scroll:no;status:no"));
}
Temporarily commenting out this javascript code, or perhaps anything in the head section, will still result in the same error when the page init event is fired. If the code block is needed, the javascript can be moved from the head section to the body section. Otherwise, you need to remove the code block completely, because commenting it out is not enough to resolve this error.
Good luck, Best, db.netDan
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Your comment has resolved my problem. I also had a code which was commented. i have removed it and problem is solved.
Thanks again.
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
I solved the problem by placing a PlaceHolder and moving the script block from head to form tag...
You saved my day!!!!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
1) Switching to <%# ... %> tags, I just get no output from these at all, no good.
2) Wrapping <script> block in a <div runat="server"> block, no effect.
3) My script is already in the <FORM> tag, so nothing I can try there.
My code is in a user control, not sure if that has anything to do with it or not. NONE of the solutions presented on the web that others are claiming are working are working for me. This pisses me off.
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Wrapping in a <div runat="server"> or a asp:PlaceHolder control should always work to ensure that <%= %> tags are isolated from the parent container. The key is to have an independent container that contains nothing else.
<script> is not affected at all by any of these - this only concerns <% %> tags.
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
<script type='text/javascript'>
<!--
(javacript goes here)
//-->
</script>
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Your post is now 2 years old, so assuming your opinions hasn't changed, what were your concerns about this approach?
<div runat="server">
<script type="text/javascript">
function ShowCreditCard()
{
}
</script>
</div>
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Just run into the same ugly problem. My workaround is to use ClientScriptManager (or in my case its AJAX'ed version, ScriptManager class, from Page_PreRender (where we have a correct ClientID):
if (!sm.IsInAsyncPostBack)
{
ScriptManager.RegisterClientScriptBlock (upDummy, upDummy.GetType (), "startup", string.Format ("var favNameClientId='{0}';", edFavName.ClientID), true);
}
This way it will embed in resulting HTML the script statement:
<script type="text/javascript">
//<![CDATA[
var favNameClientId='edFavName';//]]>
</script>
Note that this statement will be inserted at the very beginning of <body>, actually right after <script src="..."></script> blocks, so it safely can be used whenever below this point from javascripts at this page.
Also note, that this value will remain unchanged while async postbacks, so you don't need to call this method during later async postbacks, but only that's why it's wrapped in 'if'
Cheers,
Vladimir
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Chris
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
that because you can't add control
"Me.Master.FindControl("form1").Controls.Add(ctrl)"
to a form that have block (<% ... %>)
The best solution is to remove that block and try other solution
like add server side control
e.g
<a runat="server" id="lnkHome">
lnkHome.href= session("linkTitle") 'vb Code
instead of
<a href="index.aspx"><%= session("linkTitle") %> </a>
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
<div runat="server"> <script type="text/javascript" language="javascript"> ... </script> </div>
works like a charm!!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
I wish I had come across this page two years ago!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Thanks,
:)
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
I tried the <%#> <%> solution but it didn't work for me (or maybe I'm doing it wrong).
My MasterPage does not have any <%><%> code but the content page does have a couple.
Here's a snippet from the content page.
<%@ Page Title="" Language="VB" MasterPageFile="~/MasterPage.master" AutoEventWireup="false" CodeFile="page.aspx.vb" Inherits="Dashboards_page" %>
<%@ Register assembly="AjaxControlToolkit" namespace="AjaxControlToolkit" tagprefix="cc1" %>
Any ideas? Thanks in advance.
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
But, I moved my JS code from <head> to the end of the <body>, and it worked fine!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
After a lot of research, I've found a programmatic and non-programmatic way to accomplish this. You can read it here: http://mwtech.blogspot.com/2009/04/2-ways-to-load-jquery-from-aspnet.html
I hope it helps out your many readers!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
I try to have a asp:datalist with a calendar extender on edit template, but every time I run the code and put the asp:datalist in edit mode I get the same error (The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)).
thks
NS
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
and after a long time's work .
i only put the js out of the <head></head>,but between <head> and <body>.
it is works well.
My english is a little bad.
hoho~~
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
http://www.aspnetresources.com/blog/code_blocks_inside_master_pages_cause_trouble.aspx
Thanks for the details and everyone's input
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
I used WWWC for WFP from 2002-2005 and reminisce pretty fondly over it. We were using it to make AJAX-style callbacks from Flash...
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
THANKS FOR PUTTING THIS ON A BLOG!!!!!!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
For future victims, what caused the error in my case was adding a Theme for the first time to my VS2008 C# project. Replacing each <% %> with <# %> in my Default.Master got me past the error and showed some of the Theme...but it was ugly. In the end, I went back to <% %> everwhere, and simply added a <div runat=server> around each of my three asp:contentplaceholder controls since each "helpfully" comes with a generated description of each in front that is wrapped with...you guessed it...<% %> symbols to mark them as comments.
Regards,
Doug
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
http://italez.wordpress.com
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
comigo funcionou usando o <div runat="server"><%= ... %></div>
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
the Div runat Server worked like a charm , thanks God
<div runat="server">
<script type="text/javascript">
....
<% =CSharpFunction() %>
</script>
</div>
Manaf
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Yes, moving the javascript with <% %> tags from the head into the form tag works for me as well!
Cheers!
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
thanks
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
the Div runat Server really worked like a charm.
<div runat="server">
<script type="text/javascript">
....
<% =CSharpFunction() %>
</script>
</div>
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Regards,
Dyamanagowda
# re: The Controls collection cannot be modified because the control contains code blocks (i.e. &lt;% ... %&gt;).
If you can live with adding a PlaceHolder control to
your aspx-files, then you can modifiy its (the placeholders)
control collection.
Thanks for an interesting blog,
Johan Olofsson