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
- 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,
'[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
- 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.