How to get Enterprise Library working with SharePoint

Posted Wednesday, September 5, 2007 5:41 PM by C-Dog's .NET Tip of the Day

Once again, the most seemingly simple task with SharePoint has proved to be incredibly difficult. Continuing with my commitment to post the most information possible about SharePoint oddities, here is today's post. My goal today, I thought was simple. I wanted to use Enterprise Library to log errors in the application. I knew I would have to apply some code access security but I was prepared for that. I had no idea what a chore it was going to be.

I created a wrapper library for the Enterprise Library logging. I created a manifest file and I made sure to give explicit permission to the following DLLs Microsoft.Practices.EnterpriseLibrary.Common, Microsoft.Practices.EnterpriseLibrary.Data, Microsoft.Practices.EnterpriseLibrary.Logging, Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll, Microsoft.Practices.ObjectBuilder. I deployed my solution, tried my test page, only to find an error message saying partially trusted callers were not allowed. After examining the source code, I noticed that the AssemblyInfo file did not have the required AlllowPartiallyTrustedCallers attribute. So I thought fine, I'll just throw it in the GAC (against my own standards) and see if that works. Of course, it didn't work. It turns out ObjectBuilder also does not have AllowPartiallyTrustedCallers either.

The odd thing is that Microsoft released a patch for the 2.0 verison of Enterprise Library to allow partially trusted calers and supposedly it worked great. They claimed that it had that support also in the 3.1 release notes but in fact it is not there and it does not work. The reason being, that the assemblies are strongly named and none of the AssemblyInfos have the necesary attribute.

So how do we fix it? Well there are two options, both of which suck. For both options, you have to start by downloading the source code to ObjectBuilder (its on CodePlex). Open the solution, add the AllowPartiallyTrustedCallers attribute and compile it. Copy the dll it produces to the lib folder of your enterprise library. After you have done that, time to pick an option.

Probably the more correct way is to edit every AssemblyInfo file in Enterprise Library (including the unit tests) and add the AllowPartiallyTrustedCallers attribute. At the same time, you also have to add your own strong name key to every project as well. There are 38 projects in Enterprise Library so this definitely could be time consuming. You could shorten this list some by just doing the blocks you are interested in (i.e. just Logging), but it still quite a bit of effort. This also requires that your calling assemblies be strong names as well of course.

Option 2. Add the AllowPartiallyTrustedCallers attribute to the assemblies you need and recompile Enterprise Library without a strong name key. If you're only dealing with one application block, this is certainly faster. However, you have to modify every reference to the Enterprise Library dlls and remove the public key token (since its no longer signed). This is kind of a pain too, but its not too bad.

Either way you go, either everything has to be signed or nothing is signed. After you get Enterprise Library recompiled, you need to change the referenes in your existing projects, to use the new version of the dlls. Then of course you are still not done. Enterprise Library requires even more permissions than normal. Edit your manifest file, and add the following.

<IPermission class="AspNetHostingPermission" version="1" Level="Medium" />
<IPermission class="DnsPermission" version="1" Unrestricted="true" />
<IPermission class="EventLogPermission" version="1" Unrestricted="true">
  <Machine name="localhost" access="Administer" />
</IPermission>
<IPermission class="EnvironmentPermission" version="1" Unrestricted="true" />
<IPermission class="FileIOPermission" version="1" 
Read="$AppDir$;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config;"			   Write="$AppDir$"			   Append="$AppDir$"   
PathDiscovery="$AppDir$;C:\WINDOWS\Microsoft.NET\Framework\v
2.0.50727\CONFIG\machine.config"	/>
<IPermission class="IsolatedStorageFilePermission" version="1" Allowed="AssemblyIsolationByUser" 
UserQuota="9223372036854775807" />
<IPermission class="PrintingPermission" version="1" Level="DefaultPrinting" />
<IPermission class="PerformanceCounterPermission" version="1">
  <Machine name="localhost">
    <Category name="Enterprise Library Caching Counters" access="Write"/>
    <Category name="Enterprise Library Cryptography Counters" access="Write"/>
    <Category name="Enterprise Library Data Counters" access="Write"/>
    <Category name="Enterprise Library Exception Handling Counters" access="Write"/>
    <Category name="Enterprise Library Logging Counters" access="Write"/>
    <Category name="Enterprise Library Security Counters" access="Write"/>
  </Machine>
</IPermission>
<IPermission class="ReflectionPermission" version="1" Unrestricted="true"/>
<IPermission class="SecurityPermission" version="1"			   
Flags="SerializationFormatter, UnmanagedCode, Infrastructure, Assertion, Execution, ControlThread, ControlPrincipal, 
RemotingConfiguration, ControlAppDomain,ControlDomainPolicy"  />
<IPermission class="SharePointPermission" version="1" ObjectModel="True" />
<IPermission class="SmtpPermission" version="1" Access="Connect" />
<IPermission class="SqlClientPermission" version="1" Unrestricted="true"/>
<IPermission class="WebPartPermission" version="1" Connections="True" />
<IPermission class="WebPermission" version="1">
  <ConnectAccess>
    <URI uri="$OriginHost$"/>
  </ConnectAccess>
</IPermission>

Unfortunately, I do not have a version of the above that specified the full assembly path to each permission on the IPermission element, so that makes it necessary to make sure you have the following lines in the SecurityClasses element.

<SecurityClass Name="AllMembershipCondition" 
Description="System.Security.Policy.AllMembershipCondition, 
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="AspNetHostingPermission" Description="System.Web.AspNetHostingPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="DnsPermission" Description="System.Net.DnsPermission, System, Version=2.0.0.0, Culture=neutral, 
PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="EnvironmentPermission" 
Description="System.Security.Permissions.EnvironmentPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="EventLogPermission" 
Description="System.Diagnostics.EventLogPermission, System, 
Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<SecurityClass Name="FileIOPermission" 
Description="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="FirstMatchCodeGroup" 
Description="System.Security.Policy.FirstMatchCodeGroup, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="IsolatedStorageFilePermission" 
Description="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="NamedPermissionSet" 
Description="System.Security.NamedPermissionSet"/>
<SecurityClass Name="PrintingPermission" 
Description="System.Drawing.Printing.PrintingPermission, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
<SecurityClass Name="SecurityPermission" 
Description="System.Security.Permissions.SecurityPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="SharePointPermission" 
Description="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"/>
<SecurityClass Name="SmtpPermission" 
Description="System.Net.Mail.SmtpPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="SqlClientPermission" 
Description="System.Data.SqlClient.SqlClientPermission, System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="StrongNameMembershipCondition" 
Description="System.Security.Policy.StrongNameMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="UIPermission" 
Description="System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="UnionCodeGroup" 
Description="System.Security.Policy.UnionCodeGroup, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="UrlMembershipCondition" 
Description="System.Security.Policy.UrlMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="WebPermission" 
Description="System.Net.WebPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
<SecurityClass Name="WebPartPermission" 
Description="Microsoft.SharePoint.Security.WebPartPermission, Microsoft.SharePoint.Security, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"/>
<SecurityClass Name="ZoneMembershipCondition" 
Description="System.Security.Policy.ZoneMembershipCondition, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>

I spent a lot of time trying to figure this out today. Hopefully, this will help one of you if you need to use the Enterprise Library in SharePoint.

Read the complete post at http://www.dotnettipoftheday.com/blog.aspx?id=384