Posts Tagged ‘template’

MVC Template Fix

// January 2nd, 2008 // 6 Comments » // MVC

Several weeks ago I blogged about a bug I found in the CTP release of the MVC framework. The gist of the bug is that controls declared in the html portion of a page or user control could not be referenced from the code-behind of that page or user control. ScottGu posted a comment clarifying that this was due to a bug in the templates released in the CTP.

After nearly a month of following Scott's advice on how to fix the bug, I finally grew tired of such a repetitive task and have fixed the templates. You'll find a zip file containing the fix and installation instructions at the bottom of this post. Before I get into that though, let me explain the workaround (suggested by ScottGu) that I've been using until now:

The Easy, Repetitive Workaround

The problem is that the template for pages, master pages, and user controls only include the declarative HTML file and it's code-behind. The template is missing the designer file used by Visual Studio to hide the references generated by the server controls declared in your HTML. Here is what a MVC page looks like right after creation:

SimpleWorkaround-Before

You could manually create a designer class to fix this issue, but that would be a pain. Luckily Visual Studio provides us with the handy "Convert to Web Application" feature to generate the designer class for us. Simply right-click on the .ASPX (or .Master or .ASCX) and click the "Convert to Web Application" option on the context menu.

SimpleWorkaround-During

After doing so, you should see this:

SimpleWorkaround-After

Voilà! Your codebehind file for that page/control (and that page/control only) should now work as expected. Its quick and simple, but I'm sure you can imagine already the annoyance at having to do this for each and every page or control you create. That thought leads us to…

The Slightly More Complex Permanent Solution

First, an admission of guilt: I only fixed the C# templates. I apologize to any VB.Net'ers out there ahead of time.

There are four templates that must be fixed:

  1. View Master Page – A master page.
  2. View Page – A normal page.
  3. View Content Page – A page that uses a master page.
  4. View User Control – A control.

These four templates are found in two different places: the item templates folder and the item templates cache folder.

Those folders are found at: "Common7IDEItemTemplatesCSharpWeb1033" and "Common7IDEItemTemplatesCacheCSharpWeb1033" respectively (within your VS 9 root folder).

The item templates folder contains zip files which are at some point unzipped and stored in the item templates cache folder. I suppose you could just update the contents of the item templates cache folder, but I don't know if those settings would ever be written over by the item templates folder, so it is better to be safe and fix it in both places.

TemplateFix-ZipLocation

TemplateFix-CacheLocation

The contents of a typical template for pages/user controls are:

  • a vtemplate file (which serves as the manifest for the rest of the items)
  • an icon file
  • an html file (ASPX, ASCX, etc)
  • a codebehind file
  • a designer file

As you can see from the screenshot below, the templates did not include a designer file.

TemplateFix-ZipContents

In addition, the vtemplate file does not describe a designer file.

TemplateFix-TemplateFile

The fix is to add a line to the vtemplate file referencing a designer file and then add the designer file itself to the template folder/zip. The designer file should look something like:

TemplateFix-DesignerFile

I've gone ahead and done all this for you — well, actually for me, but you get the point. :-) All you need to do is download the zip file from below and follow the instructions included in the readme.txt file.

MVC Template Fix.zip (50.54 kb)

Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com

MVC Bug: Broken Codebehind

// December 11th, 2007 // 4 Comments » // MVC

Update (Jan 2): I have posted a permanent fix in the form of modified Visual Studio templates in another blog post. 

Update (Dec 11): ScottGu was kind enough to post a fix for this particular problem. It is unfortunate that you have to repeat the fix for every view you add to your project, but I guess that's why it is called a CTP! ScottGu said…

There is a bug in the file template when you create a new page – and the .designer.cs file isn't generated.
To fix this, right click on the file and choose the "Convert to Web Application" menu item. This will generate the .designer.cs file that contains your control declarations. From that point on the code-behind will be kept up to date as you make changes.


Hope this helps,


Scott


Original Post: 

It may not be a popular choice, but I'm perfectly okay with in-line code in my views as long as it doesn't contain business logic. One of the developers on my project prefers tag-based views (<asp:Blah runat="server" />) and came to me yesterday with a curious issue. I've spent some of the morning investigating the issue and it does appear that there is a bug in the newly released ASP.Net MVC Framework.

The issue? Controls declared in an ASPX are not visible to that page's codebehind.

To test this hypothesis (and make sure we hadn't somehow broken our project) I started a new "ASP.Net MVC Web Application" project (note that the bug also exists for the "ASP.Net MVC Web Application and Test" project). I then opened the Views/Home/About.aspx file and added the following line:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="About.aspx.cs" Inherits="MVCBug.Views.Home.About" %>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContentPlaceHolder" runat="server">

    <h2>Todo: Company information</h2>

    <asp:Literal ID="myLiteral" runat="server" Text="Hello World" />

</asp:Content>

 

Then I opened up the page's codebehind (Views/Home/About.aspx.cs) and added the following:

using System;

using System.Web;

using System.Web.Mvc;

namespace MVCBug.Views.Home

{

    public partial class About : ViewPage

    {

        public void Page_Load()

        {

            myLiteral.Text = "Goodbye World";

        }

    }

}

 

Ctrl+Shift+B to compile and bam, a build error: "The name 'myLiteral' does not exist in the current context."

I began to wonder if this was not supported by the MVC framework, but I took a look back at one of ScottGu's most recent articles, ASP.Net MVC Framework (Part 3): Passing ViewData from Controllers to Views, and saw that he references controls from the page's codebehind several times. I also tried using several controls besides the Literal to no avail.

To test what was going on, I commented out the reference in the Page_Load method, added a string declaration and put a breakpoint on it. When I ran the MVC application in debug mode and loaded the page I was able to see the "myLiteral" control reference. It appears that the reference is available at runtime but Visual Studio just is not able to see it at compile time. Odd.

DebugMyLiteral

For now I've told the developer to just use in-line code, but I'm well aware that many developers are loathe to do so. Thoughts? Suggestions?

Kick It on DotNetKicks.comShout It on DotNetShoutOuts.com