When you think ASP, think...
Recent Articles
All Articles
ASP.NET Articles
ASPFAQs.com
Message Board
Related Web Technologies
User Tips!
Coding Tips
Search

Sections:
Book Reviews
Sample Chapters
Commonly Asked Message Board Questions
JavaScript Tutorials
MSDN Communities Hub
Official Docs
Security
Stump the SQL Guru!
Web Hosts
XML
Information:
Advertise
Feedback
Author an Article

ASP ASP.NET ASP FAQs Message Board Feedback
 
Print this Page!
Published: Wednesday, October 19, 2005

A Look at ASP.NET 2.0's Provider Model

By Scott Mitchell


Introduction


Back in 2001 I started work on an ASP.NET online messageboard application called WebForums.NET. The idea was to create an ASP.NET-based messageboard system that could easily be plugged into an existing website. One particular challenge building such an end-to-end application was providing a means for customers to be able to integrate it within their system. For example, clearly an online forum needs some sort of data store to store user information, forums, posts, and so on, but what's important is not to lock the customer into a particular data store. That is, you shouldn't say, "I'm going to have my application use Microsoft SQL Server 2000," because at that point, how are customers who use Oracle or Access going to be able to use your software?

Another issue is with integration into a customer's existing data. All online forum sites have user accounts and a means for creating new accounts; this is typically modeled in the forum's architecture as a Users table in the database. But customers might already have their own user-related database tables that already have thousands of user accounts. Or a customer might want to use the forums in an intranet setting, authenticating and storing user information against Active Directory, rather than some database table. When a forum software system creates a Users database table and says to the customer, "This is how you will store users," they alienate those customers who already have existing infrastructure and user data. Clearly this challenge faces any company or developer that's creating software to be used "in the wild."

This particular challenge arises when you build a system with a rigid API implementation. Rather than providing a means to customize the logic, a rigid API implementation hard codes the implementation details - you will use SQL Server as your backend data store... you will have a Users table in this database where all user information will be stored. This rigidity, however, can be broken quite easily using the provider design pattern. With the provider design pattern the system architect merely defines the API, the programmatic functionality offerred by the system. For an online forum application, this might include a Users class with methods like Authenticate(username, password) and GetUserDetails(username).

The beauty of the provider model is that the customer implementing the solution can specify a custom class that the system should use. This custom class must implement the system's well-defined API, but it allows for any custom implementation to be seamlessly plugged in. That is, once this API is defined, the system implementor can create a default concrete implementation - one that uses SQL Server and a Users table - that most customers can use without modification. Those customers that have a custom need - those that want to use Oracle or have user data stored in some other manner - can create classes that provide the necessary functionality and plug them into the system.

The provider design pattern is used throughout ASP.NET 2.0. There are also guidelines on how to provide this functionality in ASP.NET 1.x applications. In this article we'll examine the provider model and see how it's used in ASP.NET 2.0. Read on to learn more!

- continued -

Breaking the Rigid API Implementation


Fairly early on in my development of WebForums.NET I realized that the rigid API implementation was going to be a problem. Part of my design goal for the software was to make it as flexible and customizable as possible, and boxing users into using SQL Server and my implementation of the users data model seemed restrictive, at best. Unfortunately, I didn't have any insight into this problem, but luckily Andy Smith did. He suggested (and built!) a system that involved two pieces:
  1. A set of abstract base classes that defined the system's core functionality, and
  2. Code that would, at runtime, dynamically load a specified class that extended the abstract base class and use its functionality. Specifically, the code inspected the Web.config file, which contained a <ConfigSetting> that gave the fully-qualified name for the class to use.
With this architecture, I could define the system's functionality through a series of abstract base classes, provide concrete implementations of these classes using SQL Server 2000 and the Users table. Customers that were happy with this configuration could just use the application as-is and everything would work fine without them needing to write a line of code. Those developers who needed to customize the solution for their unique needs, however, could do so by creating their own classes that derived from the appropriate abstract base class(es). They could have this new class used by the system by simply dropping the assembly in the application's /bin directory and updating the Web.config file.

Specifically, WebForums.NET shipped with an abstract base class called DataProvider that spelled out all of the methods in the system, akin to:

public abstract class DataProvider
{
	public abstract bool AuthenticateUser(string username, string password);
	public abstract User GetUserInfo(string username);
	...
	
	public static DataProvider Instance()
	{
	  ...
	}
}

The AuthenticateUser(username, password) and GetUserInfo(username) methods spelled out two of the many methods defined by the system. The static Instance() method was the workhorse of the DataProvider class. It contained the code that inspected the Web.config file for the WebForums.NET configuration information, which indicated the fully-qualified name of the class the system was to use. The method then used reflection (with caching) to create an instance of that class and return it to the system.

WebForums.NET shipped with a class called SqlDataProvider that extended the DataProvider base class, providing concrete implementations for the assorted methods. For example, all methods in SqlDataProvider worked with data stored in a SQL Server 2000 database; the user-related methods worked with a pre-defined Users database table. A customer who wanted to change the backend functionality could create her own class that derived from DataProvider, indicating in the Web.config file that their custom class should be used. For example, the Web.config in WebForums.NET would include the following content:

<WebForumsSettings>
    <add key="DataProviderAssemblyPath" value="path" />
    <add key="DataProviderClassName" value="Namespace.Classname" />
</WebForumsSettings>

This setting information, by default, referenced the SqlDataProvider class that shipped with WebForums.NET. However, if a customer created their own implementation of the API, they could provide their class's details here, and the system would automatically start using their implementation in lieu of the default implementation.

With this architecture in place, the page developer working with the WebForums.NET could use code like the following to authenticate a user:

if (DataProvider.Instance().AuthenticateUser(username, password))
  // User is authenticated
else
  // Username/password invalid!

When the DataProvider.Instance() method is called, the configuration file is examined and an instance of the appropriate class is returned. This would be the default SqlDataProvider class if the customer has not created their own implementation; it would be their own class if they did. Once the DataProvider.Instance() method returns an instance of the appropriate provider, we can simply invoke the members of the API, AuthenticateUser() in this example.

The WebForums.NET Provider Model - An Early Prototype
Andy's provider model had a few shortcomings that have since been accounted for in Microsoft's recommendations of using the provider model. For one, WebForums.NET had a single abstract base class with all of the API defined in that one class. The downside here was that if a customer wanted to customize only a small part of the system - such as how user information was stored - he had to provide implementations for all of the methods in the system. A better approach is to create an abstract base class for each logical entity in the system. For an online messageboard application this might entail classes like UsersProvider, ForumsProvider, PostsProvider, and so on. There is a balance, however, between the number of providers you offer a customer. More providers allow for finer grained customization of the system, but increase the amount of configuration markup needed.

Also, the code I've shown as WebForums.NET's implementation of the provider model has been changed a little bit to more closely look like the code used by Microsoft in ASP.NET 2.0. Andy's ideas were the precursor to the provider model, in my opinion, although Microsoft's implementation of the provider model is cleaner and more robust.

On an aside, WebForums.NET ended up being sold to Microsoft in March 2002. Rob Howard and others added a lot of features to the system and released it for free as the the ASP.NET Forums. Today Rob and crew have turned the ASP.NET Forums into Community Server, a blogging, forums, gallery, listserv, newsreader, and so on, all rolled into one. The concepts outlined and implemented by Andy are used today in both the ASP.NET Forums and Community Server, as well as in many core ASP.NET 2.0 components.

The Benefits of the Provider Model


The provider model offers a number of benefits. First, note that there's a clean separation between the code and the backend implementation. Regardless if whether or not the code to authenticate a user is done against a SQL Server 2000 database's Users table, or if it's done against an Active Directory store, the code from the page developer's perspective is the same: DataProvider.Instance().AuthenticateUser(username, password). The backend implementation changes are transparent.

Since system architects are strongly encouraged to create a default concrete implementation, the provider model offers the best of both worlds: to those who are content with the default implementation, the system just works as expected; for those that need to customize the system, they can do so without upsetting the existing code or programmatic logic. This design pattern also makes prototyping and agile development a lot easier. For example, in the early iterations of working with the system, it might be easier to just use the default implementation. However, later you suspect you'll need to cusomize certain aspects in order to integrate the work with your company's existing systems. When that time comes, you can achieve the needed customization through the provider model, meaning your earlier work need not be changed to reflect the backend implementation changes.

Like many good design patterns, the provider model also affords separation of duties among developers. One set of developers can be tasked with mastering the system's API, while others can be tasked with focusing on the backend implementation and customization. These two groups can work on the system without stepping on one another's toes. Furthermore, if the system being worked on is an industry standard - like ASP.NET 2.0 - skills from both tasks can be easily carried over into future jobs.

The Provider Model in ASP.NET 2.0


ASP.NET 2.0 utilizes the provider model throughout its architecture. Many of its subsystems - Membership, Site Navigation, Personalization, and so on - utilize the provider model. Each of these subsystems provide a default implementation, but enable customers to tweak the functionality to their own needs. For example, the Site Navigation piece of ASP.NET 2.0 allows a page developer to define the navigational structure of their website. This data can then be used by a variety of Web controls, to display site maps, breadcrumbs, treeviews, or menus that highlight the site's navigation and/or show the user's location in the site. In addition to navigation-related Web controls, the site navigation API provides a bevy of methods for interacting with the website's navigation information

By default the site's navigational information must be encoded in a properly-formatted XML file. This is the data store that the default site navigation is hard-coded to use. However, ASP.NET 2.0's provider model makes it easy for you to use your own data store for site navigation. For example, in a project I'm currently working on a database contains information on what pages exist in the site and what permissions various users have for those pages. Rather than redefining this information in an XML file and having to try to keep two copies of this information up to date, in order to utilize the site navigation in ASP.NET 2.0 I will be able to simply create a provider class that works directly with the database information. Once this class is created and specified in the website's configuration, the navigation Web controls will be working against the application's custom navigation information stored in the database. (Note: as of the time of this writing, this project is still in ASP.NET 1.x. However, this example hopefully illustrates the benefit of the provider model.)

Personally I think that the provider model is one of ASP.NET 2.0's greatest features for migration. ASP.NET 2.0 offers a lot of new features that developers had to custom bake in 1.x. If these new features in 2.0 used rigid implementations, it would dissuade migration from 'living' 1.x applications that used custom solutions since many of the new ASP.NET 2.0 Web controls use these new subsystems. With the provider model in place, however, we can upgrade our 1.x apps to 2.0 and create a provider to have 2.0's new subsystems integrate with our custom baked solutions. That means when moving to 2.0 we can use the new Web controls and have them seamlessly use our existing systems thanks to the provider model.

Examples of Custom Providers...
Many developers have created custom providers to extend the built-in functionalities in the .NET Framework 2.0. In Examining ASP.NET 2.0's Site Navigation - Part 4 I show how to build a custom site map provider that bases the site map's structure on the physical file system structure. Jeff Prosise has created a custom site map provider for SQL Server.

On the membership, roles, and providers front, Scott Guthrie lists a number of custom providers in his ASP.NET 2.0 Membership, Roles, Forms Authentication, and Security Resources page. I've created a custom provider profile that serializes profile data to XML files; check it out at Examining ASP.NET 2.0's Membership, Roles, and Profile - Part 7. There's also a normalized custom SQL profile provider available from Microsoft.

See Microsoft's ASP.NET 2.0 Providers documentation for more information!

For More Information...


With the provider model an important architectural piece in ASP.NET 2.0, Microsoft has published a number of articles on this topic. If you are interested in learning more I'd encourage you to start with Rob Howard's two articles: The second article looks at how to start using the provider model in your ASP.NET 1.x applications. There are also a pair of articles discussing the provider used by the Site Navigation piece in ASP.NET 2.0: There's also a Provider Toolkit released by Microsoft, which aids in creating providers for ASP.NET 2.0, and an article titled ASP.NET 2.0 Provider Model, which is over 120 printed pages of provider goodness.

Conclusion


When creating systems that will be used by a number of customers with varying requirements, a rigid API implementation can rightfully cause a scare. A rigid implementation forces customers to meet, agree to, and become locked into the system architect's vision. Companies are oftentimes more interested in applications and frameworks that will work with their existing solutions rather than forcing them to coerce their solutions to work with the vendor's.

The provider model is one way to break the rigid implementation problem. With the provider model, the system is flexible enough to be able to use any class that extends a particular base class. Therefore, customers can create their own derived classes that include their custom logic and business rules. This new class can be seamlessly plugged into the system, without disturbing existing code shipped with the application or any new, custom code that has since been created. The provider model is heavily used in ASP.NET 2.0; the concepts can be applied to ASP.NET 1.x applications as well.

Happy Programming!

  • By Scott Mitchell



  • ASP.NET [1.x] [2.0] | ASPMessageboard.com | ASPFAQs.com | Advertise | Feedback | Author an Article