Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1

In my last post, I announced the happy news that the Release Candidate for ASP.NET MVC is available. In this post, I say mea culpa for a known bug within this release.

This bug is a consequence of a change we made in our default template. We know have a content placeholder in the <head> section of the Site.master page.

<head runat="server">
    <asp:ContentPlaceHolder ID="head" runat="server">
        <title></title>
    </asp:ContentPlaceHolder>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

The benefit here is that it makes it easy to specify view specific scripts, style sheets, and title tags from the specific view, like so.

<asp:Content ID="indexHead" ContentPlaceHolderID="head" runat="server">
    <title>Home Page</title>
    <style type="text/css">
        /* Some style specific to this view */
    </style>
</asp:Content>

Long story short, if the Header control (aka <head runat="server" />) doesn’t see a title tag as a direct child of itself, it renders an empty title tag in order to ensure the page has valid HTML. This results in having two title tags, the one you intended and an empty one.

We put in a fix for this whereby we modify the controls collection of the header control, but the fix itself causes a problem when you have code nuggets within the <head> section. For example, the following causes an exception.

<head runat="server">
    <script src="<%= Url.Content("~/foo.js") %>" type="text/javascript">
    </script>
    <asp:ContentPlaceHolder ID="head" runat="server">
        <title></title>
    </asp:ContentPlaceHolder>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

The exception this causes is:

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

We unfortunately didn’t find this until very recently. The current workaround is simple. Place the script tag within a normal PlaceHolder control.

<head runat="server">
    <asp:PlaceHolder runat="server" id="mainScripts">
        <script src="<%= Url.Content("~/foo.js") %>" type="text/javascript">
        </script>
    </asp:PlaceHolder>
    <asp:ContentPlaceHolder ID="head" runat="server">
        <title></title>
    </asp:ContentPlaceHolder>
    <link href="../../Content/Site.css" rel="stylesheet" type="text/css" />
</head>

We have one simple solution to this we are bouncing around, and are investigating alternative solutions. We apologize for any inconveniences this may cause.

Technorati Tags: ,

What others have said

Requesting Gravatar... Jamie Jan 27, 2009 4:44 PM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
Couldn't you just not have the runat="server" part? I took that out of my master pages and they work just fine.
Requesting Gravatar... Mike G. Jan 27, 2009 4:46 PM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
Why is the runat="server" on the header tag?
Requesting Gravatar... Some guy Jan 27, 2009 5:12 PM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
I had come up with a work around that had been working for me so far.

\head runat="server" visible="false" /\
\head runat="server" \
\title\ /%=Page.Title ?? "Default Title"%/ \/title\
\/head\

/ are actually greater/less than, just don't know if they are going to be escaped or not...
Requesting Gravatar... Some guy Jan 27, 2009 5:13 PM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
Psh... I mean't the other one to not have a runat tag...
Requesting Gravatar... Michael Carr Jan 27, 2009 5:40 PM
# Slight improvement to the default "head" ContentPlaceHolder
I made what I believe is a slight improvement to the default ContentPlaceHolder "head".

Old default (from your code above):
<asp:ContentPlaceHolder ID="head" runat="server">
<title></title>
</asp:ContentPlaceHolder>

New default:
<asp:ContentPlaceHolder ID="head" runat="server">
<title><%= Page.Title %></title>
</asp:ContentPlaceHolder>

Then, for 99% of my views I can set the title like this:
<%@ Page Title="My Page Title" Language="C#" ... %>

For the minority of views that need special treatment, I can override the default by implementing a distinct content control for "head".
Requesting Gravatar... Michael Carr Jan 27, 2009 8:28 PM
# Never mind my previous suggestion...
It results in duplicate <Title></Title> tags... foiled again!

Can you just deactivate all the non-MVC parts of ASP.NET please?? :)
Requesting Gravatar... Simon Jan 27, 2009 8:52 PM
# what does runat='server' even mean anymore !
for anyone reading this confused about what runat="server" even means in MVC here's a useful stackoverflow post about what the consequences are of runat="server" for MVC. theres some notes in there about TITLE which may or may not be relevant anymore with the change to the template : stackoverflow.com/.../what-is-the-status-of-run...
Requesting Gravatar... gandjustas Jan 28, 2009 12:23 AM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
This problem is solved simply by removing runat="server" attribute.
Is this attribute necessary?
Requesting Gravatar... mogadanez Jan 28, 2009 3:37 AM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
This issue not new for ASP.NET MVC. this was know from ASP.NET 1.1
i was write post about it aprox year ago
blogs.gotdotnet.ru/.../PermaLink.aspx
Requesting Gravatar... HB Jan 28, 2009 7:13 AM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
Apparently Url.Content("~/somepath") and Url.Action("someaction") was changed, because they no longer put a / at the start.

Is this correct, or is there a new method to use? It's a pain having to go back and change all these methods.
Requesting Gravatar... freddy Jan 28, 2009 7:39 AM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
As mogadanez said, this issue has been on web forms for quite some time. If you do have a fix, talk with the guys at the web form team, so it is fix in there as well - collaboration :)
Requesting Gravatar... Steve Jan 28, 2009 8:24 AM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
Hey Phil, can you update your Areas code and blog about a new one using RC1... :)

Requesting Gravatar... Steve Jan 28, 2009 3:25 PM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
By the way, all my 'UpdateModel' calls that worked perfect in Beta are throwing errors now.

Any ideas of why this is failing on me now ?
Requesting Gravatar... André Jan 29, 2009 8:10 AM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
I'm having the same problem as Steve.
In beta version I use like this:
UpdateModel(product, "Product", form);
In RC1 it doesn't work! How to fix it?
Requesting Gravatar... Andre Jan 29, 2009 8:41 AM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
Hi all,
I've found the solution to the "UpdateModel" problem at Scott Gu's blog:
"UpdateModel accepts a ValueProvider, and there is a ToValueProvider() method on FormCollection that you can use to create one from a FormCollection. However - in general you shouldn't need to-do this. Instead I'd recommend not specifying a ValueProvider within your Controller action and have it update using the default Request.Forms collection. For unit testing purposes, you can then set the Controller.ValueProvider property within your unit test and populate it using the ValueProvider collection class that is built into ASP.NET MVC. You can then invoke the action method within the test and the UpdateModel() call will use the ValueProvider you've populated to set the values."
Requesting Gravatar... Trevor Jan 29, 2009 8:48 PM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
Can you explain what this part of the update was meant to provide? I mean I can already have a contentplaceholder in the head section in the beta version. That works just fine for including css and js files? I'm a little confused
Requesting Gravatar... yazılım Mar 19, 2009 5:54 AM
# re: Controls Collection Cannot Be Modified Issue with ASP.NET MVC RC1
I do get duplicate title tags. So I just use Page.Title="asdad" i my views. It works but i have no idea if this is the right way

What do you have to say?

(will show your gravatar)
Please add 6 and 4 and type the answer here: