Reuse in ASP.NET Across Domains
ASPAlliance.com: The #1 ASP.NET Community
The ASPSmith
Search
D: | Domains | Authors.aspalliance.com | Stevesmith | Articles | Reuse in ASP.NET Across Domains
Reuse in ASP.NET Across Domains

By Steven Smith

ASP.NET offers a wide array of advantages over Classic ASP, which will compel the millions of ASP developers to move to ASP.NET in a hurry. However, as with any new technology, there are tradeoffs. Not EVERYTHING is easier to do in the .NET world, and in fact some things have become more more difficult. Consider a website such as ASPAlliance.com, which provides dozens of columnists with their own web sites to use to write about and demonstrate ASP and ASP.NET. In order to provide a common look and set of functions to these columnists, it was quite easy in ASP to use an include files, which allowed everyone access to these common library functions. ASP.NET provides support for User Controls, a powerful new tool that is functionally similar to include files, but gives developers the ability to programatically control the behavior of the controls (unlike include files). These would seem to be the logical upgrade for the ASP Alliance's include files, but unfortunately this solution will not work.

Although ASP include files could be referenced by any website on the server, User Controls cannot. .NET introduces the concept of Application Domains, and does not allow one application to reference controls found in another application's domain. This means that, while the root web of ASPAlliance.com might be able to take advantage of User Controls, the columnists' webs would be unable to do so. This is a fairly large problem, since it is important that the site be able to offer these common tools and look and feel to all of its columnist websites.

Of course, that's not the end of the story. There are several options available to overcome this problem. The first and simplest option is to simply copy the User Controls to each columnist website, so that they can be referenced without crossing Application Domains. While this approach might be relatively simple and easy to implement at first, it would quickly become a maintenance nightmare as changes occurred in the User Controls and as new columnists were added to the site. This option would not be ideal.

Another option to consider is to use a shared component. There aren't too many of these floating around today, but by this time next year these component should be commonplace. Basically, a shared component is installed at the computer level, and is accessible by any application on the computer (it can be restricted, but that's another story). However, because they are shared, these custom components need to be given a strong name, which is accomplished through the use of the 'sn.exe' application included with the .NET SDK. This uses encryption to ensure that the name of the shared component will not conflict with the name of any other shared component, and in this way it is functionally similar to GUIDs in current Windows DNA programming. Since I haven't as yet written any strongly named components, I was a bit leery of this solution, because I didn't know how hard it would be to do. So far, though, this looked like the approach I would need to take, and was recommended to me by the Microsoft .NET team.

Thinking about it some more, though, I hit upon what seems like an obvious solution now. Web Services. See, recently ASPAlliance.com has linked up with several other organizations and has spun off one organization of its own, each with their own web sites, and not only would this solution allow columnist websites to use the library functions and look and feel of the Alliance site, but it would also allow these other websites to do the same thing. Essentially, this would kill two birds with one stone. For those of you are who are not yet familiar with Web Services, I recommend reading about them here:
Intro to Web Services (http://aspalliance.com/quickstart/aspplus/doc/webservicesintro.aspx)
The Rise of Web Services (http://www.aspalliance.com/articles/riseofwebservices.aspx)

There are some down sides to using web services in this manner. First of all, there is the obvious overhead -- any page that uses a web service to get its layout is essentially going to use an extra web request (or two if it has a header and a footer it gets as separate methods) every time it is requested. This sounds like a big deal until you realize that a typical page with a handful of images and perhaps a CSS or Javascript reference has as many as a dozen or more separate requests already. The second issue is performance. Especially when the server has just started, the web service is going to be slow to respond. A wait time of 10 seconds is not unreasonable (and is in fact what I'm using here). If two of these requests were required on every page, obviously performance would be atrocious. To this I have one thing to say: caching. We're talking about relatively static page layout here -- a perfect candidate for caching. I cache it everywhere. I cache my template pages that hold the layout for my web service to grab. I cache it at the web service level itself (each Web Method). Sometimes I integrate the navigation into a user control and I cache the user control. And of course, I enable Output Caching on nearly every ASP.NET page on my site, simply because it dramatically increases the performance and scalability of the site. For more on caching, you can read my overview of output and fragment caching.

Now, having come up with the high-level solution to my problem (since I run the ASP Alliance, it was MY problem, after all), all that remained was to flesh out a few details. How would I organize the services? How would columnists and other websites take advantage of them? How would I make them easy to manage, since they are compiled code without a GUI, and therefore not as easy to build as User Controls or Web Forms. To answer these in reverse order, here is what I have one and plan to do:

  • Build Data Access Components -- Using the IBuySpy Store as an example, I am building data access components in C# to access my SQL Server 2000 database that the ASP Alliance site currently uses to manage much of its content.
  • Build template .ASPX pages -- For each individual piece of GUI/look that I want to expose as a web service, I am building it as its own web form. Currently, these simply output HTML, but I may redesign them to be XSL templates that are then applied to XML data. For now I'm following the KISS principles, and keeping it simple.
  • Write the web services -- As I write this, I'm in the process of writing the actual web services that will return the HTML that is to be used by different websites. The finished version is now in beta testing (as of 7/13/01), and you can check it out at http://aspalliance.com/webservices/.
  • Deploy and Document -- In order to make deployment as painless as possible, I may resort to using a compiled control/assembly that knows how to connect to my web services and already has the proxy code compiled into it, making it much easier for novice ASP.NET developers to use (copy it into /bin/; that's it.). In my tests so far, I have simply been using <asp:literal> controls and replacing their Text with the return value of the Web Service call. I could switch to using User Controls for this, but I am hesitant to do so because of the deployment and management issues already described. Right now it involves two lines of code to drop the literal on the .aspx page and set its value in the codebehind.

Other Options (added 6 October 2001):

I recently had a reader (Paul Jenkinson) suggest to me another way to attain reuse of User Controls across application domains in ASP.NET. It requires a bit more server access (or ADSI coding) than using web services as I have described, but otherwise seems to be a cleaner solution (except it doesn't allow other sites to use the controls, but that may be preferred anyway). Anyway, here is Paul's suggestion:

I have been thinking about this article and have found an alternative solution, you may have already discount this, if so I would like to hear your reasons.

This is the scenario :

1) You have a number of web applications set up in IIS: webapp1: points to local folders C:\myweb\app1 webapp2: points to local folders C:\myweb\app2 webapp3: points to local folders C:\myweb\app3

2) webapp1 contains a normal folder named 'shared' which contains a number of user controls or other content you want to share with the other web applications. The shared folder exists on the local hard drive in C:\myweb\app1\shared, this is the master copy and does not exist on the local hard drive for webapp2 or webapp3.

3) To share the content, use IIS manager to set up a sub virtual directory named 'shared' under webapp1 and webapp2 which points to C:\myweb\app1\shared.

More Other Options (added 31 October 2001):

Building on Paul's solution above, another reader (Scott Catharall) added this:

The following are the steps (tried and tested) involved in sharing user controls from a single location for many web applications using .NET. The compilation of these steps was due to a collaborative effort between John Casagrande, Scott Catherall, Reed Comire and Richard Evans all from USC. Inspired by the article by Steven Smith who referenced Paul Jenkinson who in turn suggested that this should be possible.

Step 1: Create a web application project. This project should contain the user controls to be shared by other applications. For this example we use the name "Common". Create and build user controls from this project. In this example we will use "MyControl.ascx".

Step 2: Create a virtual directory in each application that will use the shared user controls. This is done using the IIS manager. For this example the application is "App1". From within IIS right click on the "App1" application, select New>Virtual Directory. Browse to the "Common" application. In the example we name the virtual directory "Common".

Step 3: Create a reference from the using application to the shared application. For example from the "App1" application project within Visual Studio, create a reference to "Common". Right click the references folder in the solution explorer. Select "Add Reference", then "Browse" to the "Bin" folder of the shared application and select the dll. In this example we browse to c:\inetpub\wwwroot\common\bin\common.dll.

Step 4: To use the user control on a page in the using application register the user control. For this example we use the user control in "MyPage.aspx" in the "App1" application. The first line of the aspx page is <% register ... src="common\MyControl.ascx" %>.

Step 5: Finally, in the code behind set the type for the user control. In this example we insert the line Protected WithEvents Control1 As Common.MyControl If in your user control you use namespace then the line would be: Protected WithEvents Control1 As Common.MyNamespace.MyControl

The only drawback we see using this method is that you cannot use the Visual Studio GUI for dragging and dropping the usercontrol onto your aspx page.

Summary

When all is said and done, YOU could consume the look and feel functions exposed by ASP Alliance, if you wanted to do so. Relationships with third parties such as ASPIN.com and http://jobs.aspalliance.com/ involving separate websites will be easy to build while maintaining a unified look and feel for the site. Although this started out as a disadvantage of ASP.NET (the inability to share User Controls), in the end the solution to the problem will provide much more value than was possible with Classic ASP.





ASP.NET Developer's Cookbook, By Steven Smith, Rob Howard, ASPAlliance.com 

ASP.NET By Example, By Steven Smith 




Steven Smith, MCSE + Internet (4.0)
Last Modified: 6/12/2009 10:58:22 AM
History: 6/12/2009 10:58:22 AM