Enforce version changes using Pu
Enforce versioning using assembly redirection and publisher policy
Recently I encountered a scenario like this:
"I developed a web site few months back using ASP.NET, ADO.NET and MS-Access
database. The application was small one and Access is what the client wanted.
Naturally I used OleDB data provider to develop a Data Access Layer (DAL). The
DAL was also used by few more applications. The client hosted the DAL in Global
Assembly Cache (GAC) as it was being shared across many applications. So far so
good. Recently they migrated from Access to SQL Server and requested me to
provide new version of DAL now using SQL data provider. Doing so was easy but it
how all the applications will automatically use the new version? Still worse
during migration period two applications were supposed to use the older version
and rest all were supposed to use the new version automatically."
Well. The solution that I used was Publisher Policy.
As you probably know, by default any client application which is using a
shared component tries to use the exact version of the assembly with which it
was built. If the version could not be found it throws an exception. This
coupling between the client application and a specific version of the assembly
is referred as Assembly Binding.
How to change assembly binding?
There are two ways to change the default behavior of the client applications:
- Using special tags in client configuration file
- Publisher Policy
In the first way you need to put <assemblyBinding> section in the client
application's configuration file. If your client is an EXE application the
configuration file will be <exe_name>.exe.config and if your client is a web
application it will be web.config. This section allows you to configure
something called as "binding redirection". Binding redirection governs where
client's referring older versions should be redirected to. Using this approach
is good if you want only few client applications to use the new version because
it calls for change in each and every client configuration file.
Publisher Policy is a special assembly that specifies the binding
redirections. The advantage of publisher policy is that you as a supplier of the
assembly will create it and install it on the server once. All the clients
requesting older version will automatically get redirected to the new version.
You can of course configure a specific client not to use the publisher policy.
This approach is best suited for the scenario that I explained above. A word of
caution - using publisher policy wrongly can bring back DLL hell. So, use it
carefully in your application.
For the sake of completeness we will see both the approaches in action.
depending on your scenario you need to decide which one to use.
Binding redirection using configuration files
Have a look at following markup:
This is the markup that you need to put in client configuration file. Here
are the details of various tags:
- The entire <runtime> section must appear inside <configuration> tag of
the configuration file.
- Inside <runtime> tag there is <dependentAssembly> tag consists one or
more <assemblyIdentity> and <bindingRedirect> tags.
- Each <dependentAssembly> tag represents one assembly that you want to
redirect from older version to the newer
- The <assemblyIdentity> tag specifies details of the assembly such as its
name (name) and public key token (publicKeyToken)
- The <bindingRedirect> tag specifies the older version (oldVersion) that
should be redirected to the newer version (newVersion)
Example of using binding redirection via configuration files
You will find a console application called Client1 that initially uses
version 1.0 of an assembly called SharedComp.dll. Later it uses the version 1.1
of the same component by specifying the details in the configuration file.
The general steps to be followed are:
- Create a class library project called SharedComp
- Create a method called HelloWorld() that returns a string
- Specify its version number as 1.0 in the assemblyinfo file using <assemblyVersion>
- Create a string name using SN.EXE tool
- Sign your class library with the strong name
- Host the assembly in GAC using GACUTIL.EXE tool
- Create a console application
- Refer the assembly and use its HelloWorld() method
- Now repeat the same steps to create and host version 1.1 and 2.0 of the
- Run the client without any configuration file
- Create the configuration file and add the markup as shown above
- Run the client. Once specifying version as 1.1 and 2.0 and see what
See top of the article for complete source code.
Creating Publisher Policy
We know from our previous discussion that publisher policy is an assembly
which contains binding redirections. In order to create publisher policy you
need to use AL.EXE command line tool. The syntax is as shown below:
- <mypolicy.config> is an XML file containing the same markup as we used
in our previous example
- The resultant publisher policy assembly must be of the form Policy.<major_ver_of_old_assembly>.<minor_ver_of_old_assembly>.
- The publisher policy is also hosted in GAC and hence needs a strong name
Once you are ready with the publisher policy assembly, host it in GAC using
GACUTIL.EXE tool. Delete the client application's configuration file and run the
client application again. This time the client should take the new version even
if there is no client configuration file.
See top of the article for complete source code.
Versioning and sharing has its own space in component development. .NET
provides mush easier deployment through private assemblies but at times you need
to use shared assemblies anyways. Especially third party control and component
vendors find shared assemblies easy because many times licensing goes by "per
web server" basis. The vendor may want to apply patches or improvements to all
the existing applications. Assembly redirection and publisher policies can help
in such situations.