Writing Other Providers
With the provider-based feature designed and written, you can develop additional providers very easily. Without actually developing any payment-gateway-interface details, here's how you would write a provider to interact with the CyberSource Payment Gateway.
First, create a new project and reference the assembly containing the base class, which in this case is the assembly that contains all the code written so far. Call this new provider class CyberSourcePaymentProcessingProvider. The class code begins by inheriting from PaymentProcessingProvider. The process from here on is identical to the TestPaymentProcessingProvider class so I won't repeat it. The only definite difference would be in the implementation of the two ProcessPayment
methods. These methods communicate directly with the CyberSource payment gateway API. How CyberSource implements this functionality is specific to that API and beyond the scope of this article. Some payment gateway APIs involve referencing a .NET component that they provide, while others are completely service-oriented and offer either a web service or a WCF service with which you can interface. Every payment gateway is different; it's up to you familiarize yourself with whichever one you choose.
Now, I just used the words "definite difference" because there is also a "possible difference" in the way I would code this provider as opposed to the test provider earlier. This difference lies in the Initialize
method. Remember, the goal of the code in this method is to read the config argument and set the variables defined in the provider's base class. If you find that the number and name of possible configuration attributes differs from provider to provider (for this same feature of course), then the Initialize
method will check for and act upon more or fewer config values. If you anticipate that this will never be the case for your provider-based feature, then you can place the Initialize
method override and all its code in the provider base class itself—PaymentProcessingProvider in this example. Then the actual provider classes need do nothing but provide implementations of all the action methods.
After completing the new provider, compile it and make the assembly available to whatever client will be using it. Referencing the assembly is not necessary. In fact, one of the ideas here is that you can add a provider to your system, install it in the configuration file, and possibly even set it as the default provider—all without having to recompile or redeploy your application. Because provider classes are instantiated in a late-bound fashion (see the sidebar "Late Bound Instantiation
"), they simply need to be within the scope of your application. However, your application does need to reference the core assembly—the one with the provider base class, the configuration class, and the static factory class.
Accessing Any Provider
Because the static factory class prepares all the configured providers for use, whether they're the default provider or not, you can access any of them directly. For example, suppose you have configured three providers in your configuration, called TestProvider, CyberSource, and AuthorizeNet. You may have the defaultProvider
attribute set to CyberSource but all the providers are available through the Providers
property of the PaymentProcessing factory class.
The client application may not, and should not, know of the existence of the concrete provider classes, but it does know and has access to the base class from which they all inherit. Therefore, to access the non-default AuthorizeNet provider directly, you can do this:
// In C#:
PaymentProcessingProvider provider =
' In VB:
Dim provider As PaymentProcessingProvider = _
Now you can use the provider
variable to call the ProcessPayment
This is the technique that the ASP.NET Security Controls use internally when you set their MembershipProvider property to target a specific provider; otherwise they use whatever is the default provider.
During the course of this article, I've referred to this model by its common name: the ASP.NET Provider Model. But the truth is that the ASP.NET Provider Model is not restricted to ASP.NET applications only. The story that I heard is that it was developed by members of the ASP.NET team, and while it's used throughout the ASP.NET framework, it can certainly be used from any other type of .NET client as well. That client must reference System.Web.dll
, which is where all the code resides. In my humble opinion, placing all the required classes for this model in this assembly was a mistake. It's an important enough model to merit its own assembly. Unfortunately, I've encountered many developers that refuse to reference System.Web.dll
from a Windows Forms application or from a business layer. Those developers say it's a UI DLL and does not belong in a business layer, or that it's a web DLL and does not belong in a Windows Forms application. I look at it this way: it's a framework DLL and I treat it just like I do System.dll
; the model is too powerful to give up on just because you're not using ASP.NET.
In this article, you've seen a very specific real-world implementation of the Strategy Design Pattern known as the ASP.NET Provider Model. Used correctly, this model can add some great extensibility to your applications. It can also help you design applications when you're uncertain about some of the architectural decisions. You can design some features of your application to be provider-based features, and then write a provider that accesses and acts upon that data in an immediate object-oriented fashion, and later write another provider that acts as a proxy to a service somewhere. You are limited only by your own needs and creativity, but like every other architectural, design, and development technique, learn and use this as just one tool in your arsenal. One thing is for certain. Swappable providers are a great way to accommodate customers who "change their minds" (even though we all know that never, ever happens