One thing i’ve always wondered is why there’s no obvious possibility of developing reusable web user control libraries within Visual Studio .NET. There is the “web control library” project template, which is supposed to contain web custom controls, but there is no straightforward way of adding web user controls to that library. Maybe a lot of folks like developing web custom controls libraries, but for me the custom (or lately composite) controls don’t quite cut it. I mean, let’s face it, for a composite control (that is a control whose sole purpose in life is to bind together other existing controls) would you rather code your control’s layout or design it in markup? The answer’s obvious (if you’re not a masochist) and the balance clearly leans towards user controls, since they provide a clear “Page-like” separation between markup and code. But enough rambling, here’s the deal: although, as I said, there is no straightforward way of reusing user controls across applications, it turns out there are at least three ways to do it (that are not so straightforward :)):
1. As explained by Scott Guthrie here and here, you could basically build a reusable user control library as a web site. More to the point, you create a web site (or web application) project, add your user controls to it and compile it (meaning that you get one or more assemblies with code and one or more .ascx files representing your controls’ markup). Then, in the web site where you want to use the control library (that is, the website containg user controls), you can just add a reference to the previously built assemblies, copy the .ascx files in your website and start dropping them on the pages of your choice. The solution is pretty ok as far as I’m concerned, the only thing about it that I don’t like is that it doesn’t feel “natural”. I mean, after all, you do use a web site (or application) as a control library. While there might not be any implications to this (although there are, one that comes to mind is the inability to have any helper code in the user control website/library in asp.net 2.0, because it would have to reside in the App_Code folder and then, since there are no namespaces in the asp.net 2.0 web sites, it might collide with the App_Code of the web site it’s being used in) I’m still not quite at peace with this kind of deployment.
2. As explained in this excellent article on codeproject, you could basically build a custom control library, add a custom control to it and, for that control, also add a .ascx file by hand and set its build action to embedded resource. Then, the custom control would load the markup from the resources at runtime, do a ParseControl on it to create a control and then add the newly created control to its (the custom control’s) control collection. This solution is also pretty good, the only nasty thing is that, since the custom control is nothing more than a placeholder for the user control that gets created from the markup at runtime, the custom control must assign the correct references (from the newly Parsed control from markup) to any child controls declared in it it wants to have. For complex controls this can be a drag and although it could be automated, it would be time consuming. On the bright side, from the client’s point of view, your control is very easy to use. No need to copy .ascx files anywhere, just reference the library and you’re good to go.
3. Basically a mix of the above, it goes like this: create a class library project. Add both a code file and a .ascx file (for the markup; you will have to add the .ascx file by hand, maybe by generating it/copying it from outside visual studio in the project’s folder and then including it in the project). Because I have a short memory I usually start by copying the contents of a clean user control that VS.NET generates when you add one to a regular web site. Let your control derive from UserControl (not as in 2, from Control or CompositeControl). Build your control to your liking, you even have designer support (in VS.NET 2005 at least, haven’t tested in 2003). Now build the class library, you should get an assembly plus a number of .ascx files containing the markup. Reuse them in the same fashion described at 1. You have to be careful to delete the CodeFile attribute of the @Control directive or you will get a “file not found” error when building the web site using the control (since the .cs code file is already built into the reusable assembly). Also, when loading the control dinamically, through Page.LoadControl (note that you can also drag-and-drop the ascx file into the page in the designer and there’s nothing else you must do) be careful to add it to a runat=”server” control, such as a Placeholder, or you will get a runtime error. To wrap up, what I like about this solution is that it kinda gives me the best of both worlds (1 & 2), without incurring the “overhead” and problems of reusing an entire web site/application (as 1) and without the need to resort to mapping controls and embedding resources (as 2), while still being able to contain other code that it might need (unlike 1).
So there you have it, three ways I know of to reuse web user controls. I’d be happy to learn more if you have any ideas and, of course, any feedback on the above is greatly appreciated.
Happy reusing 😉