您的位置:首页 > 编程语言 > ASP

[转]A Look at ASP.NET 2.0's Provider Model

2007-05-03 10:48 429 查看
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!

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:

A set of abstract base classes that defined the system's core functionality, and

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
4000
 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:

Provider Model Design Pattern and Specification, and

The Provider Model in ASP.NET 1.x

The second article looks at how to start using t
9cdc
he 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:
Understanding and Extending the Site Navigation System in ASP.NET 2.0, by David Gristwood, and

Custom Site Map Providers in ASP.NET 2.0, by Morgan Skinner

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息