UGTS Document #72 - Last Modified: 8/29/2015 3:23 PM
Reusing ASPX Pages

The standard model of development for ASP.NET is to have an ASPX page with a VB or CS code behind file. This model is convenient for separating UI from code, but sometimes it is not quite the level of reuse that you want. If you want to re-use both code and UI, this model falls short because of the following limitations:

  • ASPX Files are for Websites Only - ASPX files have no meaning in a class library.  You can't create them there, can't design them there, and they wouldn't compile to anything useful if they were there.
  •  Code Behind Files must be in the Same Project - the first line of an ASPX page specifies the code-behind class to inherit from.  This class MUST be from the same project.  The reason for this is that the ASP.NET compiler will compile a partial class at runtime from the ASPX and code-behind file and merge them together into the compiled DLL which is provided just in time to run the page for the user request.  If the ASPX file references a class from a different assembly which has already been compiled, then there is no way the compiler can merge these two together, the two classes will be separate, and will conflict with the compile time error,

    The type '[LibraryName].[ClassName]' in '[File]' conflicts with the imported type '[LibraryName].[ClassName]' in '[LibraryDLLFile]'.  Using the type defined in '[File]'.

    In short, the compiler will ignore the directive to inherit and only inherit from the partial class it creates, and the page will not compile.

    On the other hand, ASP.NET does support having two or more ASPX pages in the same website using the same code-behind class.  If you do this, Reflector can be used to show that the compiler will put each page in a separate DLL and each DLL will have a copy of the code behind class to merge with the specific ASPX page that references it.

    In any case, if you use ASPX with code-behind, you have to have both the ASPX and code behind file in the same website project so that the compiler can compile the two partial classes into the same DLL.

There are several possible methods to re-use UI and workaround these limitations:

  • ASHX - If the ASPX page model does not work for you, then one solution is not to use it.  You can instead create an ASHX file,  and have it instantiate a class from a class library.  The class in the class library would then do all the rendering of HTML, all the view state preservation, and all the event dispatching. Doing it this way means that you have no designer view, and that you have no benefit of any ASP.NET controls. You're completely on your own.
  • No Code Behind - Even if the ASPX file does not reference a code behind file, it will still compile, and you can still use dynamic content.  You can use direct server side tags in the ASPX file to render output from functions in a class library.
  • Shim Class - Another option is to use a code-behind file, but have it be nothing more than a shim for another reusable class in a class library.  This is a hard approach to use in most cases in that it requires a fair amount of extra work for every page you want to 're-use' in this way.  You have to have the Page class instantiate the extra reusable class, initialize it by passing in the Page object, and have that class has to walk the control tree to find all the controls that the class needs to use, and then it needs to wire itself up to all the events on the controls that it needs to handle.
  • Page Inheritance - the code behind file does not have to inherit from System.Web.UI.Page - it can inherit instead from a subclass of Page.  In this way, you can separate out some of the common page logic into a base class.
  • User Controls - Classes can inherit from WebControl and be stored in a class library for re-use.  By making most of the page composed of user controls, everything except the composition of the page can be user controls.  This can also be effectively coupled with Page Inheritance to reduce the entire page to a few declarations, having all of the heavy logic in the base page class or the user controls.  From there, all that is needed is to copy the page container files between projects, since they contain virtually no logic that is likely to change.