Howdy Folks,
This is the first in a series of short posts where I’ll attempt to cover the DebugApp trick as demoed in my session at TechEd NZ 2008 (yes, that was a year ago for those of you scoring at home!), but also at various other user group sessions I’ve run over the last year. I’ve posted a brief explanation on this before, but it was pretty unsatisfactory as an introduction to the magic world of DebugApping.
Here’s the whole series:
- Part 1 – What, and Why DebugApp? (This Post)
- Part 2 – Creating and debugging with a DebugApp (Coming Soon)
- Part 3 – Using the DebugApp for Productive Web Part Development (Coming Later)
Part 1: What, and Why DebugApp?
The Elevator Pitch
The DebugApp trick improves productivity in SharePoint Development, by providing an F5 debugging experience regardless of the development toolkit being used, but also as a means to rapidly develop visual web parts (web parts with user controls in them) without requiring that the user control be updated into the “12 hive” or that the application pool or IIS be recycled. This allows a more rapid dev-build-test-repeat cycle than is typical with standard web part development.
The Great Productivity Loss
As many of us have learnt over the years, SharePoint Development is not exactly “productive” when compared with traditional ASP.NET web application development. The main reason for this is the addition of an (expensive) deployment step to a “virtualised” infrastructure – rather than simply compiling a web site and then testing the changes in a browser, we need to build our code, create a WSP (assuming you’re following “best practice”), then get that WSP deployed up into SharePoint itself. Even if you’re using some form of rapid deployment technique (such as WSP Builder “Copy to 12”, or Quick Deploy in VSeWSS 1.3), that additional step still does exist and it adds time. Over a million builds, that time added up represents a significant cost, let alone the frustration caused by not having as rapid a build-test-repeat cycle as we might be used to. I’ve heard many an innocent non-SharePointy ASP.NET developer swear quite profusely over this issue. Those that understand all the other benefits SharePoint can give are generally patient, but those that don’t absolutely hate it.
In addition to this general loss of time when deploying code, there can also be a loss of productivity when building Web Parts in SharePoint (the most typical of customisations) simply due to the way they are constructed. Like Web Controls, Web Parts are “all code behind” – you build up a control tree in code, rather than working with a visual design surface that does a lot of the donkey work for you (and I’m ignoring performance implications here). Who really wants to spend their days writing code like this? (real live excerpt from MSDN) :
protected override void CreateChildControls()
{
//Create text box
newTitle = new TextBox();
newTitle.Text = "";
Controls.Add(newTitle);
//Create button
saveTitle = new Button();
saveTitle.Text = "Set Web Part Title";
saveTitle.Click += new EventHandler(saveTitle_click);
Controls.Add(saveTitle);
}
Though a trivial example, the point is that complex UI is pretty difficult to achieve just in code behind. To get around this, a lot of us develop User Controls (ASCX files) that we then load into a Web Part with one simple line of code:
Controls.Add(Page.LoadControl(“/_layouts/controltemplates/MyFolder/MyUserControl.ascx”));
This way, we can use a visual design surface to create our UI, and gain productivity in the process (again ignoring the performance cost of LoadControl()), which may be a concern in some cases but often isn’t). This is exactly the technique that the well-known “Smart Part” uses, and without any offence to the amazing Jan Tielens, at the core of it it really isn’t any smarter in what it does than the above.
So what’s the problem? Well, if building a lot of User Controls to get around the annoyance of building code-behind interfaces, you still have the “slow deployment” issue. Your ASCX file must get itself into the /12/Template/ControlTemplates directory, and the binary containing your code behind must get itself into the GAC. This is where Our Saviour the DebugApp comes in, at least during highly iterative development.
The DebugApp Trick
At a high level, the DebugApp works as follows:
- A Web Application project (which I call a DebugApp) is added to your Visual Studio solution containing other projects with the usual SharePoint stuff such as Features and custom ASPX pages.
- This DebugApp’s .CSPROJ file exists on the file system in the same folder as the root of the SharePoint web application you are primarily developing against, e.g. C:\inetpub\wwwroot\wss\VirtualDirectories\sharepoint80.
- Rather than using the “Visual Studio Development Server” (aka Cassini) for this web application, you set the Debug URL to be the root of your SharePoint site, e.g. http://localhost, and make DebugApp a StartUp project.
- The fact that you have the DebugApp as StartUp project in your solution means that when you hit F5, Visual Studio will attach to the w3wp.exe process corresponding to your SharePoint web application and automatically throw you into Debug mode. F5 debug without VSeWSS, “Attach to Process”, or other techniques – tick!
- The fact that your DebugApp .CSPROJ is located at the root of your SharePoint web application means that any ASCX files you add into that DebugApp can be referenced simply by “/MyUserControl.ascx” rather than needing them to exist in the 12 Hive CONTROLTEMPLATES folder. Thus for development (but not release) purposes, you can create User Controls/ASCX files in the DebugApp project that are built as if they were in a standard Web App, and load those into web parts using the “SmartPart” technique, or into other ASPX pages using the standard methods. Any change you make into any of these ASCX files is immediately reflected in the Web Part without any additional deployment, and any build of code is updating only a bin folder DLL without any IIS reset or forced recycle needed – it happens a lot quicker, trust me.
Now this may all seem a bit convoluted, and the lawyer on my shoulder also reminds you that this method is not particularly supported nor clever in some scenarios. But over the last couple of years this trick has saved me hours upon hours of development time, especially when I’m in that highly iterative dev-test-repeat cycle.
Join me next post in the series, and I’ll walk through creating a DebugApp from scratch and getting it to work as above.
:) Matt