Saturday, March 24, 2012

Exception while adding ToolkitScriptManager dynamically in OnPreInit event

Hi,

I am trying to add ToolkitScriptManager dynamically as suggested in threadhttp://forums.asp.net/p/1039254/1777798.aspx in OnPreInit event. But I am getting exception "The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)." What could be reason?

Here is code...protectedoverridevoid OnPreInit(EventArgs e)

{

if (ToolkitScriptManager.GetCurrent(this.Page) ==null)

{

ToolkitScriptManager Manager =newToolkitScriptManager();

Manager.EnablePartialRendering =true;foreach (Control cinthis.Controls)

{

if (cis System.Web.UI.HtmlControls.HtmlForm)

c.Controls.AddAt(0, Manager);

}

}

}

Here is exception

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:

Line 519: if (c is System.Web.UI.HtmlControls.HtmlForm)Line 520:Line 521: c.Controls.AddAt(0, Manager);Line 522: }Line 523: }

Any idea what could resolve this issue?

Thanks, V

Hivishant.patel,

Thanks for your post!

As far as I know, This error happens when asp.net encounterscodeblocks like <%= %>,in a UserControl andthecode-behindthe UserControl is trying to modifythecontrolscollection ofthe page (usually a LoadControl statement).

Nice solutions:

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).

TheControlscollectioncannotbemodifiedbecausethecontrolcontainscodeblocks

Solution detail snippet:

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).

Now I feel like a complete *** 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.

Related Posts:

The Controls collection cannot be modified because the control...

Error:The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)

The Controls collection cannot be modified because the control contains code blocks ...


Jin-Yu Yin - MSFT:

This error happens when asp.net encounterscodeblocks like <%= %>, or <%# %>

Hi Jin-Yu Jin,

This is not correct, but your "Solution detail snippet" also clear about this.

So

The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>)

only shown when you try to modify acontrol's control collection, when there is <%= %> in thecontrol's root childs . <%# %> not problem at all.

Example:

<asp:PlaceHolder runat="server" id="WeDynamicallyAddControlForThisInCodeBehind">

<%= DateTime.Now.ToString( ) %> <%-- Won't work! --%>

<%# DateTime.Now.ToString( ) %> <%-- Work! (Need a call to DataBind in code behind to real show something) --%>

<asp:PlaceHolder runat="server" id="SomeChild">

<%= DateTime.Now.ToString( ) %> <%-- Work!!! Because we modify the control collection of WeDynamicallyAddControlForThisInCodeBehind and not SomeChild! --%>

<%# DateTime.Now.ToString( ) %> <%-- Of course work! --%>

</asp:PlaceHolder>

<%-- Dynamic controls go here --%>

</asp:PlaceHolder>

</asp:PlaceHolder>

Codebehind:

WeDinamicallyAddControlForThisInCodeBehind.Controls.Add( ... ); //or similar to trigger the error in some case see above.


Thank you for pointing out my mistake,I've corrected it,thanks again:)


Hi Jin-Yu Yin,

Thanks for you reply.

I have visited the posts you specified before I created this post Smile All of posts you specified discuss about custom code we write for user controls, images etc. with <% %> tags inside its markup/code and we can resolve this error by updating code as specified in these post.

In my case; I am not adding any of my own user controls or images etc. I am receving error when I am trying to addToolkitScriptManager in the control list.

How can I change code for ToolkitScriptManager to resolve this error? What should I do to addToolkitScriptManagerdynamically in my base page?

Thanks, Vishant


Hi

It not means that the issue come up when you add any of user controls or images to the page.

It means that the issue come up when you add any contorl(inludeToolkitScriptManager) dynamically in thecode-behind to a page or a user contorl and there iscodeblocks like <%= %> at where the contorl add to.

For example:

<contorlA>

<%= %>

</contorlA>

When you try to add <contorlB> to <contorlA> and want to change the code to:

<contorlA>

<%= %>

<contorlB>

</contorlB>

</contorlA>

Then the error comes up,because you cann't modifythecontrolscollection ofthe contorlA as there is a <%= %>codeblocks in it.

As I mentioned in my first reply, You can resolve this issue by change the code to:

<contorlA>

<div><%= %></div>

</contorlA>

Then add contorls to contorlA dynamically without the error.

Good luck!


Hi V,

Usuallly there could be two problems when you try to add a scriptmanager/toolkitscriptmanager to a page dinamically:

a) Adding dynamically the scriptmanager to the page is tricky, because it should be donevery early in the page lifecycle (forget page_load immediatelly for this...)

This is a good thread how to do this:

Re: Is it possible to add a ScriptManager to a page dynamically?

b) The <% %> code block error.

If you follow the instruction from a) you need to eliminate all <%= %> below the form tag, except when <%= %> are in a child asp.net control of the form tag.

Ps:

Yin-Yu-Yin suggest to use this for workaround:

<contorlA>

<div><%= %></div>

</contorlA>

but this won't work!!!

You need aserver side asp.net control around your code block, for example:

<contorlA>

<asp:Panel runat="server"><%= %></asp:Panel>

</contorlA>

this should work...


No comments:

Post a Comment