WCF Security: WCF Performance & ProtectionLevel – Part 2

In the previous post, we have stated the several problems not being able to configure ProtectionLevel for different endpoint declaratively using configuration files. In this post, we address this issue and thereby, describe how to specify ProtectionLevel for multiple endpoints of a service using .config file.

Outline. In this post, we start by stating motivation of specifing ProtectionLevel for multiple endpoints of a service declaritvely instead of programmatically. Then, we discuss the steps to achieve it.

Motivation: ProtectionLevel for Multiple Endpoints

Basically, ProtectionLevel enforces a security requirement on request and response messages in the channel, and all the consumer of the message must conform to that requirement; anything otherwise results in runtime exception. In the last post, we have described how to configure ProtectionLevel at different level of WCF messaging stack and observed that it can only be set programmatically in the contract of a WCF service, which unfortunately has impacts on all the preconfigured bindings.

For instance, consider that we would like to have two different endpoints to use different ProtectionLevel. In addition, we want to make it configurable so that we can the security behavior of the endpoint conveniently after it has been deployed.

Are these requirements practical? To answer that, consider following case: we have only one endpoint and we are using message level security with wsHttpBinding (or ws2007httpbinding preferable one for internet based WCF Service). For internet users consuming this service, we are using ProtectionLevel.EncryptAndSign because of the security requirement imposed for our application. However, in case of local intranet, we don’t want to take the overhead of
ProtectionLevel.EncryptAndSign rather would like to use ProtectionLevel.Sign to make the service a bit more responsive and efficient by getting rid of the overhead of encryption of requests and responses. Most importantly, we don’t need ProtectionLevel.EncryptAndSign for the messages in this context as per security policy. Out of the box, there is no features available that can enable the use of different ProtectionLevel in these cases.

Obviously, there is one naive approach to host to service twice by compiling the code in 2 different ProtectionLevel. At 1 to 10 scale, how would you rate this solution ? Ok , then let’s move on…

Thus, what we need is to make two different endpoints to work with different ProtectionLevel, and using custom endpoint behavior, it can be achieved. Thus, the internet users will be able to use the wsHttpBinding with default ProtectionLevel, while the intranet users use the less secure– ProtectionLevel.Sign. The next section shows how to achieve this.

ProtectionLevel Configuration via Custom Endpoint Behavior

To do this, we have following these steps.First we have to create a Custom EndpointBehavior by implementing IEndpointBehavior as below –

public class MessageSecurityBehavior:IEndpointBehavior
{
public ProtectionLevel ProtectionLevel { get; set; }
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
//Do nothing
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
//Do nothing
}
public void Validate(ServiceEndpoint endpoint)
{
//Do nothing
}
public void AddBindingParameters(ServiceEndpoint serviceEndpoint, BindingParameterCollection parameters)
{
//Setting the ProtectionLevel at the Service Contract
serviceEndpoint.Contract.ProtectionLevel = ProtectionLevel;
parameters.Remove<channelprotectionrequirements>();
ChannelProtectionRequirements requirements = new ChannelProtectionRequirements();
parameters.Add(requirements);
MessagePartSpecification unprotectedBody = new MessagePartSpecification();
MessagePartSpecification protectedBody = new MessagePartSpecification(true);
switch (ProtectionLevel)
{
case ProtectionLevel.None:
requirements.OutgoingSignatureParts.AddParts(unprotectedBody, "*");
requirements.IncomingSignatureParts.AddParts(unprotectedBody, "*");
requirements.OutgoingEncryptionParts.AddParts(unprotectedBody, "*");
requirements.IncomingEncryptionParts.AddParts(unprotectedBody, "*");
break;
case ProtectionLevel.Sign:
requirements.OutgoingSignatureParts.AddParts(protectedBody, "*");
requirements.IncomingSignatureParts.AddParts(protectedBody, "*");
requirements.OutgoingEncryptionParts.AddParts(unprotectedBody, "*");
requirements.IncomingEncryptionParts.AddParts(unprotectedBody, "*");
break;
case ProtectionLevel.EncryptAndSign:
requirements.OutgoingSignatureParts.AddParts(protectedBody, "*");
requirements.IncomingSignatureParts.AddParts(protectedBody, "*");
requirements.OutgoingEncryptionParts.AddParts(protectedBody, "*");
requirements.IncomingEncryptionParts.AddParts(protectedBody, "*");
break;
}
}
}
view raw Listing1.cs hosted with ❤ by GitHub

Then, we create a BehaviorElement by extending BehaviorExtensionElement to make the behavior configurable through config file.

/// <summary>
/// Represents Element to set the ProtectionLevel to different Endpoint using configuration
/// </summary>
public class MessageSecurityBehaviorElement : BehaviorExtensionElement
{
private const string PROTECTION_LEVEL_ELEMENT_NAME = "messageProtection";
public override Type BehaviorType
{
get
{
return typeof(MessageSecurityBehavior);
}
}
protected override object CreateBehavior()
{
return new MessageSecurityBehavior { ProtectionLevel = this.ProtectionLevel };
}
[ConfigurationProperty(PROTECTION_LEVEL_ELEMENT_NAME)]
public ProtectionLevel ProtectionLevel
{
get
{
return (ProtectionLevel)base[PROTECTION_LEVEL_ELEMENT_NAME];
}
set
{
base[PROTECTION_LEVEL_ELEMENT_NAME] = value;
}
}
private ConfigurationPropertyCollection properties = null;
protected override ConfigurationPropertyCollection Properties
{
get
{
if (this.properties == null)
{
ConfigurationPropertyCollection propertys = new ConfigurationPropertyCollection();
propertys.Add(new ConfigurationProperty(PROTECTION_LEVEL_ELEMENT_NAME, typeof(ProtectionLevel), null, ConfigurationPropertyOptions.IsRequired));
properties = propertys;
}
return properties;
}
}
}
view raw Listing2.cs hosted with ❤ by GitHub

Thus the coding part this done. Let’s start configuring. To do so, first thing that needs to be done is to add a behaviorExtensions inside system.serviceModel>behaviorExtensions specifying the newly created custom Endpoint behavior :

<system.servicemodel>
<extensions>
<behaviorExtensions>
<add name="messageProtection" type="TestService. MessageSecurityBehaviorElement, TestService"/>
</behaviorExtensions>
</extensions>
<!--Rest of the configuration-->
</system.servicemodel>

Then, we create a endpoint behavior like below:

<system.servicemodel>
<behaviors>
<endpointBehaviors>
<behavior name="noneProtectionLevelForEndPoint">
<messageProtection protectionLevel="None"/>
</behavior>
</endpointBehaviors>
</behaviors>
<!--Rest of the configuration-->
</system.servicemodel>

Now, if we need to use a similar ProtectionLevel that we configured at the previous step in any endpoint , we simply need to add it as behaviorConfiguration, and we are done.

<system.servicemodel>
<!-- Rest of the configuration-->
<endpoint address="wsHttp"
binding="wsHttpBinding"
name="wsBinding.ModeMessage.CredentialNone.BindingName"
contract="TestService.ITestService"
behaviorConfiguration="noneProtectionLevelForEndPoint">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</system.servicemodel>

More on MessageSecurityBehavior

So far, we have described how to configure ProtectionLevel at runtime. Next we explain MessageSecurityBehavior. By changing the ChannelProtectionRequirement of an Endpoint, the new custom behavior impacts requests and responses of the channel. Moreover, the contract also binds to the configured ProtectionLevel. Then, the two different MessagePartSpecification was created, where 1st one is an empty MessagePartSpecification, and 2nd one refers to the MessagePartSpecification which contains body.

Depending of different value ProtectionLevel, the MessagePartSpecification are set to ChannelProtectionRequirements.

For instance, in case ProtectionLevel.Sign, in OutgoingSignatureParts and IncomingSignatureParts of ChannelProtectionRequirements MessagePartSpecification that included Body is being added to be signed from client to the server and again back to client from server. However, in this case , encryption is not needed, so in OutgoingEncryptionParts and IncomingEncryptionParts , empty MessagePartSpecification is added, and that results in unencrypted messages.

Conclusion

In this post, we show how to declaritively specify the ProtectionLevel for multiple endpoints exposed by a WCF service. Though it’s not difficult to update the ProtectionLevel at runtime, we must note that client and server always conform to the ProtectionLevel requirement, and as a consequence, updating the ProtectionLevel at runtime might results in updating the clients configuration/code.

Additional Links

  1. WCF Security: WCF Performance & ProtectionLevel – Part 1 : https://adilakhter.wordpress.com/2009/08/06/wcf-security-wcf-performance-protectionlevel-part-1/
  2. Custom WCF Behaviors through App.Config :http://winterdom.com/2006/10/customwcfbehaviorsthroughappconfig
  3. Configuring ProtectionLevel : http://blogs.msdn.com/drnick/archive/2008/03/10/configuring-protection-level.aspx
  4. Fundamentals of WCF Security : http://www.code-magazine.com/article.aspx?quickid=0611051
Advertisement

Inside Static Constructor (.cctor)

The primary objective of using a static constructor (also known as, type constructor, class constructor or .cctor) is to initialize static members of a type, or performing some operations, which seems to be preconditions for performing any operation on a particular type, or an instance of the type. Furthermore, it is useful in creating wrapper of unmanaged classes, when the constructor can call LoadLibrary method.

It can only be defined as a static member of a type as follows:

public class StaticConstructorDemo{
    static ILogger _logger;
    static StaticConstructorDemo(){
        // ... initial setup 
        _logger = new TextLogger();
    }
}

Few notable facts about static or type constructor:

[1] Type constructor will be called just once after its being loaded in the application domain. Timing when it will be called is completely depends on CLR.  But it will surely be called before instantiation of any object from the type or before any invocation of a static method. So, it might be the right place for executing those codes that are needed to be executed just once and before any methods (static/instance) of the class invoked. There is not specific order mentioned for execution of .cctor in inheritance/association scenario. Order on which the .cctor will get executed completely depends on the CLR.

[2] Type constructor is thread safe. So, only one thread in the app-domain can run this constructor, as CLR ensures the thread safety of .cctor. If multiple thread try to access a .cctor, only one thread will eventually be successful to get a mutually exclusive lock on the type constructor while other thread will be blocked. After the current thread complete its execution of .cctor, other thread will wake up and monitor that .cctor has been executed before. Hence, they will just return without executing the .cctor.

[3] Any access modifier before the type constructor is not allowed, otherwise it results in following compile time error: “access modifiers are not allowed on static constructors“.

[4] It does not accept any arguments, and can be applied to both value and reference types.

Exception Handling

Consider following code–

public class StaticConstructorExceptionDemo{
  public static int Result = 0;
  static StaticConstructorExceptionDemo{
    int test = 0;
    Result = 100/test; // throws DivideByZeroException
  }
}

When static property Result is accessed for the first time (after being loaded in the current context), we expect a DivideByZeroException to be thrown from StaticConstructorExceptionDemo(). In contrast, it gets TypeInitializationException.

However, it is worth noticing that the _innerException is actually pointing to an instance of DivideByZeroException.

Therefore, please underscore the following important points while handling exceptions related to type constructor.

[1] We should not throw exception from the type constructor unless we come to a conclusion that the type is unusable for further usage. Due to any unhandled exception, type becomes completely unusable in the currently loaded appdomain (context).

[2] In case of any exception inside type constructor, we should expect an instance of TypeInitializationException, which refer to the original exception as its inner-exception.

Performance Optimization

By utilizing static members, we get motivated to implement singleton pattern in the following manner–

public class FileSystemLogger:ILogger
{
public static FileSystemLogger Instance =
new FileSystemLogger();
// ILogger Implementation
}
view raw gistfile1.cs hosted with ❤ by GitHub

Alternatively, we can implement it by utilizing by introducing a type constructor:

public class FileSystemLoggerWithCCTOR:ILogger{
public static FileSystemLoggerWithCCTOR Instance;
static FileSystemLoggerWithCCTOR(){
Instance = new FileSystemLoggerWithCCTOR();
}
}
view raw gistfile1.cs hosted with ❤ by GitHub

Although both class functionally looks quite similar, there is a subtle difference between them. If we fire up ILDASM, we can see an extra attribute added in FileSystemLogger, which is missing in FileSystemLoggerWithCCTOR— “beforefieldinit”.

According to MSDN, it “specifies that calling static methods of the type does not force the system to initialize the type“.

As we can see, in first class FileSystemLogger, CLI mark the class with beforefieldint that means that calling the methods of FileSystemLoggerdoes not enforce static field initialization. The reason CLI does this: as per CLI specification, it is expensive to ensure that static fields are initialized before any of the static method get called. When multiple application domain comes into account, it become more expensive.

However, CLI enforce static field initialization when any of the static field is accessed. On the other hand, FileSystemLoggerWithCCTOR has a static constructor which results in an assurance from the CLI that static constructor will get called before any static member would be invoked, which in turn, initializes all the static members of the class. However, that means, performance optimization using beforefieldinit is no longer possible with this implementation.

Conclusion

We have to use type constructor with care. We should consider not to use type constructors as long as we can, to enable performance optimization by CLI via beforeFieldInit.

Hope it helps. Thanks for visiting the blog!


See More

[1] C# and beforefieldinit
[2] Static Constructors Demystified
[3] CLR via C#
[4] Static Constructor on MSDN


Revisions

[R-2: 30-03-2013] Minor formatting changes.
[R-1: 29-03-2013] Updated formatting to make this post more consistent with current CSS.

Code Snippet: Adding a File to .net Resource

Last few days, I was thinking to jot down all the code snippet that I used very frequently.  Here comes the first one –

Today’s post will be covering a simple aspect of every .net project where one has to add files in Resource and get it from there for further processing.

To Add & Get the file from the resource , we have to –

1. Select the file that we want to put in the resource –

image

 

And from the property window, set the Build Action = “Embedded Resource”.

 

2. To get file from the resource, we have to write following few lines of codes –

 

image

In this code snippet , as we can see , I am getting the resource from the Assembly Menifest and returning it as XmlReader to the caller as –

 

image

And we are done.

.Net Provider Pattern – Designing decoupled and extensible Component for .Net Application

Provider design pattern of .Net Framework 2.0 facilitates an approach to design components in a decoupled and extensible manner. In this post, we investigate this design pattern, and show how we can utilize it to make components decoupled while providing extension points for configuration. To do so, we present the outline of today’s discussion as follows-–

Outline

  1. What is Provider Design Pattern?
  2. Walkthough: Using Provider Pattern

  3. Advantages
  4. Conclusion

What is Provider Design Pattern?

Provider pattern is a way in .Net Framework 2.0 to design extensible and decoupled Component. Ron Howard mentioned –

“A provider is simply a contract between an API and the Business Logic/Data Abstraction Layer. The provider is the implementation of the API separate from the API itself.”

Provider pattern is a way to get rid of the coupling among the components while making the components extensible. Main reason for our today’s discussion on Provider Pattern is its wonderful ability to publish the API and at the same time make the API pluggable; that is– it gives us the flexibility to choose the API that is best suited for the application rather than the one developed by API developer. And from an API developer perspective, it allows them to create an extension point for the API where clients of the framework can extend the functionality in their own way.

In the next section, we walk-through an example, which builds a component using provider design pattern.

Provider Pattern in Action

The basic idea behind the provider pattern is to have multiple ConcreteProviders and selecting one of them depending on configuration (just a change in ‘*.config file can lead to completely different provider to perform the operation) at the runtime by avoiding writing huge amount of code and coupling among the components. Provider pattern completely abstract the decision of which provider to use out of programming interface. That way we can say that, it has some kind of dependency injection/inversion flavor, but it does not use any kind of container like Windsor or Spring.net.

We first consider a simple and contrived problem (designed only for illustrative purpose), which is used throughout today’s discussion. We have the following simple domain object: User and we need a persistence media to store(/Save) and retrieve(/Get) it.

User class

This class is responsible for communicating with the physical persistence media. PersistenceManager has only two jobs.

  1. public static void Save<T>(T obj)
  2. public static T Get<T>()

Consider that this implementation as of now only supports two persistence media: SQL Server2005 and Xml (via File system). Depending on the clients’ need, we will be using any one of them at the runtime, keeping in mind that in future client might use some other persistence media like Oracle, mySql or whatever.

If we are not familiar with provider pattern, we would solve this problem using any dependency injection container (e.g. Windsor/Spring.Net/Unity), or introducing factory method to instantiate the desired component at the runtime; that is, either we had to introduce new code (write and manage) or new vocabulary to grasp (with dependency injection container) while providing custom solution. Truly that would be an overhead if we would like to solve only this problem. Then, why do we not use something from .Net2.0 when it is providing it (e.g. as in Asp.net Membership)?

A solution with .Net provider design pattern consist of following basic parts–

  1. API class (PersistenceManager) to publish API(save and get). It is also responsible to instantiate a ConcreteProvider depending on the configuration.
  2. Domain specific Abstract Provider (PersistenceProviderBase) a.k.a. Application ProviderBase inherited from ProviderBase class of System.Configuration.Provider namespace.
  3. ConcreteProviders (XmlPersistenceProvider and SqlPersistanceProvider) inherited from domain specific Abstract Provider.
  4. Custom Configuration Section to configure the Providers and a class inherited from ConfigurationSection to represent it in .Net.

The following diagram shows different parts of provider design pattern that we intend to discuss one by one.

Basic parts of Provider Design pattern

We begin with a custom Configuration section.

Custom Configuration Section

In order to make the provider pattern pluggable and flexible, evidently we have to devise a wat to configure the providers at the runtime. Application configuration via .config is probably the best approach to link communication between the available providers and configuration.

To achieve this, we need to add a class inherited from ConfigurationSection to handle the configuration of providers:

Class to store custom Configuration Section

Following is an example of the custom section for the Persistence Provider.

<PersistenceProvider defaultProvider="XmlPersistenceProvider">
<providers>
<add name="XmlPersistenceProvider" type="ProviderPattern.XmlPersistenceProvider, ProviderPattern" PersistenceMediaConnectionString="C:\PersistenceMedia\DocumentInfos.xml"/>
<add name="SqlPersistenceProvider" type="ProviderPattern.SqlPersistenceProvider, ProviderPattern" PersistenceMediaConnectionString="[Your database connection string]"/>
</providers>
</PersistenceProvider>

Important attributes to note here:

defaultProvider:
Indicates the default ConcreteProvider.
PersistenceMediaConnectionString:
Defined to provide extra information needed to the Concrete Provider. For example , XmlPersistenceProvider will save the information about the domain object in the path specified and SqlPersistenceProvider use the value specified as the connection string to the database.

We can also define other attributes as required, which can be used to initialize the ConcreteProvider (e.g. logFilePath). Benefit of such approach is that we can return to this custom configuration, and change ConcreteProvider at the runtime.

Next we move on to explore the PersistenceManager class whose responsibility is to initialize the ConcreteProvider depending on the configuration section and publish the APIs.

PersistenceManager

PersistenceManager is the major gateway to the concrete provider as I mentioned earlier that it communicates directly with the underlying persistence media using one of the concrete provider to perform the operation (e.g. Save/Get) that it exposes.

Save method of PersistenceManager is outlined as follows.

public static void Save<T>(T obj){
if (DefaultProvider == null){
Instantiate(
PersistenceProviderConfigSection.GetPersistenceConfigSection());
}
DefaultProvider.Save<T>(obj);
}
view raw save.cs hosted with ❤ by GitHub

Get method of PersistenceManager is described next.

public static T Get<T>(){
if (DefaultProvider == null){
Instantiate(PersistenceProviderConfigSection.GetPersistenceConfigSection());
}
return DefaultProvider.Get<T>();
}
view raw get.cs hosted with ❤ by GitHub

If we look at the PersistenceManager closely, the static Instantiate method, that instantiate the provider based on the Configuration from PersistenceProviderConfigSection. In order to do that, we use a built-in support feature of the .Net Framework2.0, which is core to this desing pattern: we will use ProvidersHelper class of System.Web.Configuration namespace. The ProvidersHelper.InstantiateProviders method initializes the ConcreteProviders by calling the Intialize() method of the ConcreteProviders (we come back to this point in the next section again).

private static void Instantiate(PersistenceProviderConfigSection configSection){
if (Providers == null)
SetupProvider(configSection);
}
private static void SetupProvider(PersistenceProviderConfigSection config){
if (config == null)
throw new Exception("PersistenceProvider are not configured to be used with this application");
Providers = new PersistenceProviderCollection();
ProvidersHelper.InstantiateProviders(config.Providers, Providers, typeof(PersistenceProviderBase));
DefaultProvider = Providers[config.DefaultProvider] as PersistenceProviderBase;
}
view raw Instantiate.cs hosted with ❤ by GitHub

Therefore, the DefaultProvider property in PersistenceManager always refers to the default ConcreteProvider specified in the configuration. Another alternative is to use reflection to instantiate ConcreteProvider.

Now, we describes the details of the ConcreteProvider, and how it gets initialized when we call ProvidersHelper.InstantiateProviders(config.Providers, Providers, typeof(PersistenceProviderBase)).

Application ProviderBase and Concrete Providers

In short, Application ProviderBase class or Domain-specific ProviderBase provides the abstract version of the functionality exposed by the API class, and the responsibilities of the ConcreteProviders is to implement those API in their own way. As we can see next figure, our Application ProviderBase- PersistenceProviderBase implements IPersistenceProvider, which describes the API exposed by PersistenceManager class.

PersistenceProviderBase

ProviderBase class belongs to System.Configuration.Provider namespace, which contains all the member to be implemented by the ConcreteProviders. It contains properties to describe ConcreteProviders, such as, Name and Description. Initialize() is used to initilize providers. PersistenceProviderBase is the mirror of API or services that ConcreteProvider facilitates.

As shown below, two ConcreteProviders extends PersistenceProviderBase and provides implementation of Save and Get specific to the context of a particular provider.

ConcreteProviders and their members

In addition to that, in Initalize() method, concrete providers also initialize associated properties configured through web.config. For instance,

  • _PersistenceMediaPath of the concrete providers will be initialized with the value ofPersistenceMediaConnectionString from web.config.
  • Name and Description will be initialized.

Following code outlines the initialization process of SqlPersistenceProvider.

public override void Initialize(string name, NameValueCollection config)
{
name = string.IsNullOrEmpty(name) ? "SqlPersistanceProvider" : name.Trim();
base.Setup("SqlPersistanceProvider", "SqlPersistanceProvider saves the T to SQL DB", config);
_PersistenceMediaPath = config[PersistenceMediaPathKeyName];
//Call the base class to initialize
base.Initialize(name, config);
}
view raw init.cs hosted with ❤ by GitHub

To illustrate initilization of a ConcreteProvider, we show following snapshot taken from the debug-mode.

init of a concrete provider

After initialization, we are only left with the Provider-specific implementation of the abstract functionality of the PersistenceProviderBase, i.e., Save/Get. Every provider will implement in their own way. For instance, if we consider XmlPersistenceProvider, it will implement the Save/Get method as follows, whereas, SqlPersistenceProvider typically stores and retrieves from Sql Server.

public override void Save<T>(T obj)
{
string serailzedObj = SerializeHelper.Serialize(obj);
File.WriteAllText(_PersistenceMediaPath, serailzedObj);
}
public override T Get<T>()
{
string stringContent = File.ReadAllText(_PersistenceMediaPath);
if (!String.IsNullOrEmpty(stringContent))
return ((T)SerializeHelper.Deserialize(typeof(T), stringContent));
return default(T);
}

Advantages

Why would we adopt provider design pattern?– To create loosely coupled components that are extensible from an application perspective.

Revisiting custom ConfigurationSection we have implemented, we set XmlPersistenceProvider as the default PersistenceProvider. If we want to use SqlPersistenceProvider we can simply change in the value of the defaultProvider in the web.config file and our client can start using the SqlPersistenceProvider at runtime.

<PersistenceProvider defaultProvider="SqlPersistenceProvider">
<providers>
<add name="XmlPersistenceProvider" type="ProviderPattern.XmlPersistenceProvider, ProviderPattern" PersistenceMediaConnectionString="C:\PersistenceMedia\DocumentInfos.xml"/>
<add name="SqlPersistenceProvider" type="ProviderPattern.SqlPersistenceProvider, ProviderPattern" PersistenceMediaConnectionString="[Your database connection string]"/>
</providers>
</PersistenceProvider>

If requires, any additional provider can simply be added by extending any ConcreteProvider, or by implementing IPersistenceProvider, as shown below.

MySqlPersistenceProvider

As in other providers, this new provider can also be configured during run-time as follows.

<PersistenceProvider defaultProvider="MySqlPersistenceProvider">
<providers>
<add name="XmlPersistenceProvider" type="ProviderPattern.XmlPersistenceProvider, ProviderPattern" PersistenceMediaConnectionString="C:\PersistenceMedia\DocumentInfos.xml"/>
<add name="SqlPersistenceProvider" type="ProviderPattern.SqlPersistenceProvider, ProviderPattern" PersistenceMediaConnectionString="[Your database connection string]"/>
<add name="MySqlPersistenceProvider" type="ProviderPatternExplored.MySqlPersistenceProvider, ProviderPatternExplored" PersistenceMediaConnectionString="[Your my sql database connection string]"/>
</providers>
</PersistenceProvider>

Conclusion

In this post, we have shown how we can utilize .net provider design pattern to make a component loosely couple and extensible. Note that in the example implementation, we have used ProvidersHelper class of System.Web,Configuration while building the component. However, we can easily get rid of adding reference to System.Web namespace, by implementing ProvidersHelper class; alternatively reflection can be used during instantiation of concrete providers.

We highly appreciate any question or query regarding this post. Thanks!


Revision

[R-1: 04-04-2013] Porting this blog-post from its weblogs.asp.net page.

Add Result File with TestContext

This is the last post of the series regarding TestContext. The other posts of this series include:

On Unit Testing:

Usage of TestContext:

In this post, we discuss another member of TestContext called AddResultFile, which is defined as follows.

void AddResultFile(string filename)

Through TestContext.AddResulFile, additional files can be added with the test results. This additional files will be stored in the unique folder created for current test run, as mentioned. This might be useful in some cases, for example, if we are validating our objects with some external resource, like schema— we can store the schema with our test result so that we can validate our test result later on after test run.