Publisher policy, redirection cross major/minor version, and using the latest version

We all know there are three types of binding policies: App config, publisher policy, and admin config. I’ll ignore admin config for this discussion.

App config affects one application on multiple assemblies.
Publisher policy affects one assembly for all the applications.

Because publisher policy affects all the applications, you want to be very careful about what it applies to. For example, you don’t really want to redirect an assembly to a newer version with breaking changes, since doing so will likely break applications.

In .Net framework an assembly version consists of four parts: Major, minor, build, and revision. The guideline says assemblies should be compatible within the same major/minor version. And it is expected to have breaking changes cross major/minor version.

This guideline leads to the following recommendation:

You should only use publisher policy to redirect assembly within the same major/minor version.

In fact, this is how fusion probe for publisher policy assemblies. Given an assembly foo,, fusion will only look for assemblies with name

The problem is, fusion does not enforce what kind of redirection can be put in the publisher policy. You can put a redirection from version to version, and fusion will happy accept it and apply it.

Doing so obviously violates the recommendation above. But there is nothing stopping you from doing that.

Personally, I consider this as a bug. We should only allow publisher policy to redirect within the same major/minor version.

But we have shipped it this way. We can’t take it back. We will just have to live with it forever.

People have taken advantage of this to re-use publisher policy for the purpose of always-load-the-latest-version. Of course they have to ship publisher policy for every major/minor version combination they ever have shipped. For example, if they have shipped v1.0.0.0, v2.0.0.0, and v3.0.0.0, and they want everyone to use v3.0.0.0, they will have to ship publisher policies for v1.0 and v2.0 to redirect both v1.0 and v2.0 to v3.0.

Apparently this is not something we recommend. But you can do it nevertheless.

If you have read Jeffrey Richter’s article on the future of assembly version, you will know that those people belong to the category of machine platform. To be a machine platform assembly the AppCompat bar is extremely high. It is unlikely that many people want to be in that position.

You can ignore all of these concerns and just do it anyway.

Or you can ship the newer version of assembly without publisher policy, and selectively forward the assembly to the newer version for specific applications by issuing binding redirects in app.config for those applications. In this way you do not impact the whole system. 

Comments (12)

  1. Xavier Musy says:

    Ok, so let’s say I have MyApp.exe version 1.0 which consumes and exposes an SDK MyAppSDK.dll And, because this SDK is meant to be shared and used by third-party applications, it is installed in the GAC. Now MyApp.exe version 2.0 is released, along with MyAppSDK.dll, which *is* backwards compatible with (let’s say it has defect fixes and new functionality exposed, but is backwards compatible). Why is it then not recommended to use a publisher policy files to redirect any application which was built against MyAppSDK.dll to the latest version? Isn’t the alternative to have each one of those third party applications to have to update their configuration file to redirect to the latest MyAppSDK.dll otherwise (or worse Machine.config)? How is that better, especially given those apps don’t have control over when MyAppSDK.dll is updated, nor would want to re-deploy configuration files for their apps each time?

  2. If 3rd party apps work happiliy with MyAppSDK, why do you want to bring them up to

    Do you know how many apps are using your assembly? Are you really confident that your seem innocent changes won’t cause any problem for all the 3rd party applications?

    If you are so confident, there is really nothing stopping you from doing so.

  3. Xavier Musy says:

    I think 3rd party apps working happily is a relative term, as some could be working acceptably with defects in MyAppSDK, and the primary reason for forcing 3rd party apps to upgrade to the latest MyAppSDK would be to take advantage of defect fixes in the latest MyAppSDK. E.g., SDK feature X works with acceptable defects in v1, which now works better with no/less defects in v2. Though arguably the case can be made that 3rd parties could potentially be relying on defective behavior Y in a previous version which is no longer there in the latest. But that can be circumvented individually in the 3rd party application config file by not allowing the publisher policy redirect, correct? Question is, which is better/worse, updating all with the possibility of breaking some with the benefit of helping some/all, or updating none and forcing any to decide & redeploy?

    I think what I’m looking for is the prescribed way of doing it. Is the recommended approach to always keep every version of MyAppSDK in the GAC, and have the third party applications make the decision whether or not to upgrade via re-deployment of their configuration files? Or is SDK compatibility confidence the deciding factor on which approach to take?

    Many thanks in advance!

  4. We are going through AppCompat sweep now. There are so many seemly innocent changes that causes apps to break, partially due to our stupidity in lack of documentation, guideline and incorrect samples, partially due to developers’ errors.

    As for the scenario you are looking for, the recommendation is to keep the versions you supported, and have apps to decide to float or not by app.config, and only use publisher policy for servicing.

    This begs for the question that how many old versions do you need to keep. It is really up to your support policy.

    For certain people, they are only willing to support the lastest version. If this is the case, you can issue publisher policy to redirect to the latest version, but you will have to eat the appcompat pill as well.

    Versioning is a complex issue that I don’t think we have done a good job. The focus today is more on the SideBySide aspect. The other aspect of one-and-only-one is more or less ignored. I hope we will address this problem in the future.

    Thanks for listening to my rant.

  5. Xiangyan says:

    When we build the assembly, can we spedify the major version to be an earlier version and force it usable to earlier version framework? Say, we have an assembly built with 1.1 shipped, we want to use 2.0 to build the same assembly which could be used by both 1.1 and 2.0. Is that possible?


  6. You have to build it with .Net framework v1.1.

  7. drabe says:

    I have a .Net user control that I developed in VS.Net 2003, and I’m hosting it in MSIE as described in Works great on a system that has only .NET 1.1 installed. If I try to run it on a machine that also has .NET 2.0 beta installed, then I get all sorts of unexpected security exceptions. The IEHost log (as described in reveals that IE is using some version 2 assemblies. Is there a way for me to force it to use v1.1 assemblies in this scenario?

    <pre>Microsoft.IE.SecureFactory: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. —> System.Security.SecurityException: Request for the permission of type ‘System.Security.Permissions.UIPermission, mscorlib, Version=, Culture=neutral, PublicKeyToken=b77a5c561934e089’ failed.

    at System.Security.CodeAccessSecurityEngine.Check(PermissionToken permToken, CodeAccessPermission demand, StackCrawlMark& stackMark, Int32 checkFrames, Int32 unrestrictedOverride)

    at System.Security.CodeAccessSecurityEngine.Check(CodeAccessPermission cap, StackCrawlMark& stackMark)

    at System.Security.CodeAccessPermission.Demand()

    at System.Windows.Forms.Control.set_AllowDrop(Boolean value)

    at OpenText.Livelink.SharePoint.Client.MultiUploadCtrl.InitializeComponent()

    at OpenText.Livelink.SharePoint.Client.MultiUploadCtrl..ctor()

    The action that failed was:


    The Zone of the assembly that failed was:





  8. Hugh Williams says:

    I read <a href="">here</a&gt; that Jeff Richter has backed off the new versioning scenario as described in the ServerSide article you mentioned.

    Do you have any insight into what’s going on there?

  9. We are talking about future here so nothing is settled.

    I use Jeff’s article to introduce the concept of platform assemblies and library assemblies. That is my only purpose.