VS2010 Assembly Load Error - asp.net

I am getting the following error when I try to build an ASP.NET 4 project in Visual Studio 2010: "Could not load file or assembly 'file:///C:\Dev\project\trunk\bin\Elmah.dll' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515)".
I have verified that the dll does, in fact, exist, and is getting copied to the bin folder correctly. I have also tried removing and then re-adding the reference to the project.
The build only fails when I switch the Solution Configuration to "Release". It does not fail when the Solution Configuration is set to "Debug".
The only difference between the two configurations (that I know of) is shown in the following Web.config transform, Web.Release.config:
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<connectionStrings>
<add name="SqlServer" connectionString="" providerName="System.Data.SqlClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
</connectionStrings>
<system.web>
<compilation xdt:Transform="RemoveAttributes(debug)" />
<customErrors mode="On" xdt:Transform="Replace">
<error statusCode="404" redirect="lost.htm" />
<error statusCode="500" redirect="uhoh.htm" />
</customErrors>
</system.web>
</configuration>
I have tried using Fusion Log Viewer to track down the assembly binding issue, but it looks like it is finding and loading the assembly correctly. Here is the log:
*** Assembly Binder Log Entry (6/8/2010 # 10:01:54 AM) ***
The operation was successful.
Bind result: hr = 0x0. The operation completed successfully.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll
Running under executable c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools\sgen.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: User = User
LOG: Where-ref bind. Location = C:\Dev\project\trunk\bin\Elmah.dll
LOG: Appbase = file:///c:/Program Files (x86)/Microsoft SDKs/Windows/v7.0A/bin/NETFX 4.0 Tools/
LOG: Initial PrivatePath = NULL
LOG: Dynamic Base = NULL
LOG: Cache Base = NULL
LOG: AppName = sgen.exe
Calling assembly : (Unknown).
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: No application configuration file found.
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Attempting download of new URL file:///C:/Dev/project/trunk/bin/Elmah.dll.
LOG: Assembly download was successful. Attempting setup of file: C:\Dev\project\trunk\bin\Elmah.dll
LOG: Entering run-from-source setup phase.
LOG: Assembly Name is: Elmah, Version=1.1.11517.0, Culture=neutral, PublicKeyToken=null
LOG: Re-apply policy for where-ref bind.
LOG: Where-ref bind Codebase does not match what is found in default context. Keep the result in LoadFrom context.
LOG: Binding succeeds. Returns assembly from C:\Dev\project\trunk\bin\Elmah.dll.
LOG: Assembly is loaded in LoadFrom load context.
I feel like there is a fundamental lack of understanding on my part as to what exactly is going on here. Any explanation/help is much appreciated!

Could be too late, I've experienced this issue. In my case, I fixed following this instructions I found in a comment (Thanks Thomas!) in this post
In the 'Developer IT' comment talks about do the same in the app.config. Actually must be in other place. Follow the instructions behind.
An even better solution is to "fix" Microsoft's sgen distribution. First find sgen (for example, on my system for .Net 4.0 it is in "C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\NETFX 4.0 Tools".) Next, create the file sgen.exe.config with the contents:
<configuration>
<runtime>
<loadFromRemoteSources enabled="true" />
</runtime>
</configuration>
The point is, adding loadFromRemoteResources set to true in the sgen app config file allows sgen to properly load files from ClearCase volumes. I know. I've run into the same problem and this is how I fixed it.
Note that at some point Microsoft may create the app config file, so if you do this, first check that the file doesn't already exist, and if it does, check if it still needs the setting.

I realise this is a slightly late reply, but I've just experienced and fixed the exact same issue with Elmah in release mode (and as with the OP, debug mode was working fine).
I fixed my issue by modifying the properties for Elmah.dll in Windows Explorer - from the general tab, I had to click Unblock to convince explorer that the file was indeed safe. After that, release mode publishes worked fine.

According to blogs here and here, the cause might be related to an untrusted assembly. If this were the case, I can't imagine why it would work in one configuration and not the other, but it's at least something to look at.

Problem may have multiple causes.
Appears to be exposed when loading mixed-mode assemblies (compiled in "ANY_CPU" and "X86" mode.)
I revised the compile option for my main program to "X86" to match the assumed mode of the component DLLs. The problem went away.
It may have something to do with the order in which the dll files are loaded.

Related

Wrong version of .NET assembly getting copied to Web Forms bin directory

I'm working on an ASP.NET Web Forms web site and frequently get run-time exceptions like the following:
Could not load file or assembly 'Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
=== Pre-bind state information ===
LOG: DisplayName = Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
(Fully-specified)
LOG: Appbase = file:///C:/Code/MyProject/
LOG: Initial PrivatePath = C:\Code\MyProject\bin
Calling assembly : System.Net.Http.Formatting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Code\MyProject\web.config
LOG: Using host configuration file: \\foo\bar\Profile.v2\simonm\Documents\IISExpress\config\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Redirect found in application configuration file: 4.5.0.0 redirected to 11.0.0.0.
LOG: Post-policy reference: Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
LOG: Attempting download of new URL file:///C:/Users/simonm/AppData/Local/Temp/Temporary ASP.NET Files/vs/8d6ca9e7/1d38a78a/Newtonsoft.Json.DLL.
LOG: Attempting download of new URL file:///C:/Users/simonm/AppData/Local/Temp/Temporary ASP.NET Files/vs/8d6ca9e7/1d38a78a/Newtonsoft.Json/Newtonsoft.Json.DLL.
LOG: Attempting download of new URL file:///C:/Code/MyProject/bin/Newtonsoft.Json.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Major Version
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
They're invariably because the "wrong" version of an assembly (it always seems to be Newtonsoft.Json) gets copied to the Bin directory despite the fact that the packages.config in the root of the site has:
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net45" />
and the web.config contains:
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
Can somebody please explain what dictates which assembly gets copied to the Bin directory, why this keeps happening and how to prevent it from happening in the future?
I guess, that some of your used frameworks/libraries are using different versions of Newtonsoft.Json. First, check your frameworks/libraries if they are requiring different versions of the Newtonsoft.Json library.
When you detected which is the (minimum) required version of Newtonsoft.Json try to reinstall this version through Nuget.
This seems to be cause by a number of factors, but ultimately boils down to having a .refresh file in the Bin directory that points to a different version of the assembly than the one referenced in the web.config.
It looks like these .refresh files get added when you (either manually or automatically due to e.g. Update-Package) add a reference to an ASP.NET project. If you look at the contents of a .refresh file, it's just the path to a .dll file. When you build, MSBuild (I assume) checks whether the Foo.dll in your Bin directory matches the one referenced by Foo.dll.refresh and, if they don't, copies the one referenced by the .refresh file into your Bin.
I think this combined with switching branches in Git to one that has a reference to a different version referenced in the web.config combined with the .refresh files not being in version control is what causes these problems.

ASP.Net Razor App - OAuth somehow got into app, can't get it out

Sounds strange, I know... and I've poured over every post I could find relating to this :( However, my website worked just fine and then all of the sudden it is failing on:
Could not load file or assembly 'DotNetOpenAuth.Core, Version 4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246' or one of its dependencies. The located assembly's manifest definition does not match the asembly reference. (Exception from HResult: 0x80131040).
I don't see any references to it at all in the project and it has never used authentication ever. What is the lowest level I can get to in order to find out where it is trying to call this assembly and remove it?
It's frustrating as heck... I know it is because I'm not an every-day programmer - so maybe its easy to find, but I have looked over hundreds of posts here and elsewhere trying to resolve and nothing has worked so far :(
I also grabbed an unused reference tool called ResolveUR to try to do it... still same result :(
FYI - I'm using Visual Studio 2013 for this one because Installshield LE is part of it and that was how the application was initially deployed.
Thanks in advance!
** ADDED error I get from page **
=== Pre-bind state information ===
LOG: DisplayName = DotNetOpenAuth.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246
(Fully-specified)
LOG: Appbase = file:///C:/inetpub/wwwroot/MedsAdmin/
LOG: Initial PrivatePath = C:\inetpub\wwwroot\MedsAdmin\bin
Calling assembly : Microsoft.Web.WebPages.OAuth, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file: C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: DotNetOpenAuth.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=2780ccd10d57b246
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/Temporary ASP.NET Files/medsadmin/4efeacc2/d291dc53/DotNetOpenAuth.Core.DLL.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework/v4.0.30319/Temporary ASP.NET Files/medsadmin/4efeacc2/d291dc53/DotNetOpenAuth.Core/DotNetOpenAuth.Core.DLL.
LOG: Attempting download of new URL file:///C:/inetpub/wwwroot/MedsAdmin/bin/DotNetOpenAuth.Core.DLL.
WRN: Comparing the assembly name resulted in the mismatch: Minor Version
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
* EDIT: Replaced Old Web.Config *
Somehow my web.config file got written over - so that is the reason for the OpenAuth issue.
NOW: It seems to be trying to load MySQLMembershipProvider from my machine.config file (which fails). Why is it doing this?

Wix setup failing with error 1603

I have written a .NET 4 desktop application and when trying to run the Setup.exe I am getting the following error in the log file.
I am using Visual Studio 2012 with Wix 3.7.
MSI (s) (E8:1C) [16:51:54:890]: Invoking remote custom action. DLL: C:\windows\Installer\MSIFECD.tmp, Entrypoint: EncryptConfig
SFXCA: Extracting custom action to temporary directory: C:\windows\Installer\MSIFECD.tmp-\
SFXCA: Binding to CLR version v4.0.30319
Calling custom action SecureConfig!SecureConfig.CustomActions.EncryptConfig
EncryptConfig: Begin
An error occurred creating the configuration section handler for security: Could not load file or assembly 'Order.Configuration.Net' or one of its dependencies. The system cannot find the file specified. (C:\Program Files (x86)\Orbit Order System\Orbit Order System.exe.config line 6)
CustomAction EncryptConfigurationFile returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
Action ended 16:51:55: InstallFinalize. Return value 3.
I can confirm that `Order.Configuration.Net.dll' exists in the target folder as does the application config file.
This is the app.config file:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="backup"
type="OrderConfiguration.BackupConfig, Order.Configuration.Net"/>
<section name="general"
type="OrderConfiguration.GeneralConfig, Order.Configuration.Net"/>
<section name="security"
type="OrderConfiguration.SecurityConfig, Order.Configuration.Net"/>
<-- ** THIS IS LINE 6 **
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<backup configSource="config\backup.config"/>
<general configSource="config\general.config"/>
<security configSource="config\security.config"/>
<connectionStrings>
<clear/>
<add name="OrderDb"
connectionString="Data Source=(local);Initial Catalog=OrbitOrder;
User Id=User;Password=Pass;MultipleActiveResultSets=true;"/>
</connectionStrings>
</configuration>
I also confirm that config\security.config exists in the target folder.
I have spent three hours trying to figure out what the error means as all files actually exist in the target folder. I actually copied the WIX set up from a prior solution that I worked on a year ago and that one works fine without any issues.
The custom action that is failing is trying to encrypt the security configuration section.
I am at a loss to explain why MSI is throwing a 1603 error when there doesn't appear to be anything amiss.
I managed to resolve this after adding the following code to the Wix custom action:
AppDomain.CurrentDomain.AssemblyResolve += ( sender, args ) =>
{
return Assembly.LoadFrom( string.Format( #"{0}Order.Configuration.Net.dll", installFolder ) );
};
This basically says to load the assembly when it encounters a reference that needs resolving.
As per the log, the error is returned by the custom action written by you, so please debug the custom action dll during installation. Easiest method of debugging custom action is to add a message box in the code (begin of custom action) and attach to process in visual studio when the message box is displayed. other way is to use MsiBreak environment variable as described in http://msdn.microsoft.com/en-us/library/aa368264%28v=vs.85%29.aspx

Newtonsoft.Json.dll issue when using multiple projects

I am seeing some really odd behavior that I have not been able to correct related to references for Newtonsoft.Json.dll. I have a sample solution set up with the following projects:
JsonProblem.Core
JsonProblem.CauseProblem (references JsonProblem.Core)
JsonProblem.Web (references JsonProblem.Core and JsonProblem.CauseProblem)
In JsonProblem.Core and JsonProblem.Web I have added the "Microsoft ASP.NET Web API 2.2" NuGet package. In JsonProblem.Core I have created a web api. If I build JsonProblem.Core and run a page from JsonProblem.Web everything works as expected.
Now if I build JsonProblem.CauseProblem and try to view a page in JsonProblem.Web, I get the following error.
Could not load file or assembly 'Newtonsoft.Json' or one of its
dependencies. The located assembly's manifest definition does not
match the assembly reference. (Exception from HRESULT: 0x80131040)
If I rebuild JsonProblem.Core the error goes away. And again if I build JsonProblem.CauseProblem without building JsonProblem.Core afterward (even though JsonProblem.CauseProblem depends on JsonProblem.Core) I get the error. Somehow the build of JsonProblem.CauseProblem is causing version 4.5.11 of Newtonsoft.Json to get copied to the JsonProblem.Web bin directory, overwriting version 6.0.3. I'm pretty sure I have binding redirects setup correctly, as I have the following in the JsonProblem.Web web.config and in the app.config files for JsonProblem.Core and JsonProblem.CauseProblem:
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
So I am at a loss as to the cause of this strange behavior. I have reproduced it in 2 projects. It seems that the binding redirects are ignored when I build JsonProblem.CauseProblem. I can work around it, but I'm concerned that whatever bug or feature is causing this behavior may be altering other references in the background that might cause problems down the line.
EDIT - as tizzy suggested I used the fuslogvw tool. Here is what was generated in the log. I'm not sure how to interpret this, however, because the log does not tell me what happens at build time to overwrite the version of Newtonsoft.Json.dll in my the app's website directory.
The operation failed.
Bind result: hr = 0x80131040. No description available.
Assembly manager loaded from: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable C:\Program Files\IIS Express\iisexpress.exe
--- A detailed error log follows.
=== Pre-bind state information ===
LOG: DisplayName = Newtonsoft.Json
(Partial)
WRN: Partial binding information was supplied for an assembly:
WRN: Assembly Name: Newtonsoft.Json | Domain ID: 5
WRN: A partial bind occurs when only part of the assembly display name is provided.
WRN: This might result in the binder loading an incorrect assembly.
WRN: It is recommended to provide a fully specified textual identity for the assembly,
WRN: that consists of the simple name, version, culture, and public key token.
WRN: See whitepaper http://go.microsoft.com/fwlink/?LinkId=109270 for more information and common solutions to this issue.
LOG: Appbase = file:///C:/Users/John/Desktop/JsonProblem/JsonProblem.Web/
LOG: Initial PrivatePath = C:\Users\John\Desktop\JsonProblem\JsonProblem.Web\bin
LOG: Dynamic Base = C:\Users\John\AppData\Local\Temp\Temporary ASP.NET Files\vs\3661babd
LOG: Cache Base = C:\Users\John\AppData\Local\Temp\Temporary ASP.NET Files\vs\3661babd
LOG: AppName = 3b3fd45
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Users\John\Desktop\JsonProblem\JsonProblem.Web\web.config
LOG: Using host configuration file: C:\Users\John\Documents\IISExpress\config\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind).
LOG: Attempting download of new URL file:///C:/Users/John/AppData/Local/Temp/Temporary ASP.NET Files/vs/3661babd/3b3fd45/Newtonsoft.Json.DLL.
LOG: Attempting download of new URL file:///C:/Users/John/AppData/Local/Temp/Temporary ASP.NET Files/vs/3661babd/3b3fd45/Newtonsoft.Json/Newtonsoft.Json.DLL.
LOG: Attempting download of new URL file:///C:/Users/John/Desktop/JsonProblem/JsonProblem.Web/bin/Newtonsoft.Json.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Users\John\Desktop\JsonProblem\JsonProblem.Web\bin\Newtonsoft.Json.dll
LOG: Entering download cache setup phase.
LOG: Assembly Name is: Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
LOG: A partially-specified assembly bind succeeded from the application directory. Need to re-apply policy.
LOG: Using application configuration file: C:\Users\John\Desktop\JsonProblem\JsonProblem.Web\web.config
LOG: Using host configuration file: C:\Users\John\Documents\IISExpress\config\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Redirect found in application configuration file: 4.5.0.0 redirected to 6.0.0.0.
LOG: Post-policy reference: Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
LOG: GAC Lookup was unsuccessful.
LOG: The post-policy assembly reference requires probing again.
LOG: Attempting download of new URL file:///C:/Users/John/AppData/Local/Temp/Temporary ASP.NET Files/vs/3661babd/3b3fd45/Newtonsoft.Json.DLL.
LOG: Attempting download of new URL file:///C:/Users/John/AppData/Local/Temp/Temporary ASP.NET Files/vs/3661babd/3b3fd45/Newtonsoft.Json/Newtonsoft.Json.DLL.
LOG: Attempting download of new URL file:///C:/Users/John/Desktop/JsonProblem/JsonProblem.Web/bin/Newtonsoft.Json.DLL.
LOG: Assembly download was successful. Attempting setup of file: C:\Users\John\Desktop\JsonProblem\JsonProblem.Web\bin\Newtonsoft.Json.dll
LOG: Entering download cache setup phase.
LOG: Assembly Name is: Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed
WRN: Comparing the assembly name resulted in the mismatch: Major Version
ERR: The assembly reference did not match the assembly definition found.
ERR: Setup failed with hr = 0x80131040.
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
I had the exact same behavior as the above problem description, except that when I rebuilt my class library (i.e. JsonProblem.Core), it would pull in Newtonsoft.dll 4.5.11, even though this class library had no direct reference or Nuget package that indicated a reference to NewtonSoft.
In what could be considered a Visual Studio 2015 bug, the class library rebuild copies the invisibly referenced DLLs into referencing project bin folders (not currently being built), overwriting the DLLs in referencing projects, breaking them.
IOW, for example, build project Y (referencing JsonProblem.Core), apparent success. Build project X (ref to JsonProblem.Core) which breaks project Y. Build Project Y and now this breaks Project X. Infinite loop: while( sane ) { build(); }
In my case, the only 3rd party libraries that I was referencing in this library were Gibraltar.Agent and Gibraltar.Agent.Web.Mvc (which reported no dependency on NewtonSoft. Right clicking on these in project References and selecting "Find Code Dependent on this module" revealed that I didn't need to reference the 2nd one.
I uninstalled Gibraltar.Agent.Web.Mvc in Nuget, and all problems went away. Two days of DLL Hell heartache have ended.
You may be dealing with a handful of different scenarios here. My advice to you would be to use the fuslogvw tool to show you which dll it's trying to load, and where it's looking for it. It is possible that there is another dependency problem that is being masked here, since your assembly binding redirect looks correct on the surface. The fuslogvw tool will just allow you to see the assembly binding behavior, and what's happening. It's great to have for assembly binding issues.

Why can't I encrypt web.config/appSettings using a custom configProtectionProvider on Azure (Windows Server 2012)?

I have an MVC application which is deployed to a Windows Azure hosted service running on a Windows Server 2012 virtual machine. In the web.config file, I have 3 sections encrypted using the PKCS12ProtectedConfigurationProvider: connectionStrings, dataCacheClients, and system.net/mailSettings/smtp. Here is what the relevant sections look like:
<configuration>
...
<configProtectedData>
<providers>
<add name="CustomProvider" thumbprint="[this is secret]"
type="Pkcs12ProtectedConfigurationProvider.Pkcs12ProtectedConfigurationProvider, PKCS12ProtectedConfigurationProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34da007ac91f901d" />
</providers>
</configProtectedData>
...
<connectionStrings configProtectionProvider="CustomProvider">
<EncryptedData ... ommitted for brevity
</connectionStrings>
...
<system.net>
<mailSettings>
<smtp configProtectionProvider="CustomProvider">
<EncryptedData ommitted for brevity
</smtp>
</mailSettings>
</system.net>
...
<dataCacheClients configProtectionProvider="CustomProvider">
<EncryptedData ommitted for brevity
</dataCacheClients>
...
</configuration>
All of the above works perfectly fine. When deployed to Azure, the connection strings, SMTP mail, and data cache all work. The PKCS12ProtectedConfiguration provider uses my custom certificate to decrypt the sections and all is well.
However I can't seem to use the same approach to encrypt web.config/appSettings. When I try deploying something like the following to Azure...
<configuration>
...
<appSettings configProtectionProvider="CustomProvider">
<EncryptedData ommitted for brevity
</appSettings>
...
</configuration>
...then I get the following exception:
Server Error in '/' Application.
Configuration Error
Description: An error occurred during the processing of a configuration file
required to service this request. Please review the specific error details
below and modify your configuration file appropriately.
Parser Error Message: An error occurred loading a configuration file: Could not
load file or assembly 'PKCS12ProtectedConfigurationProvider, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=34da007ac91f901d' or one of its dependencies.
The system cannot find the file specified.
Source Error:
Line 41: </EncryptedData>
Line 42: </connectionStrings>
Line 43: <appSettings configProtectionProvider="CustomProvider">
Line 44: <EncryptedData ...>
Line 45: <EncryptionMethod .../>
Source File: E:\sitesroot\0\web.config Line: 43
Assembly Load Trace: The following information can be helpful to determine why
the assembly 'PKCS12ProtectedConfigurationProvider, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=34da007ac91f901d' could not be loaded.
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value
[HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure
logging.
To turn this feature off, remove the registry value
[HKLM\Software\Microsoft\Fusion!EnableLog].
However I know the PKCS12ProtectedConfigurationProvider.dll is in the /bin folder because:
I remoted into the VM and saw it in both approot/bin and siteroot/bin
When I deploy with the appSettings unencrypted, the other 3 sections are successfully decrypted using this dll.
It's almost as if the assembly loader can't look for the PKCS12ProtectedConfigurationProvider.dll file until after it parses and loads the appSettings section. I have tried omitting the Version, Culture, and PublicKeyToken parts of the provider config section, but then the error just changes to this:
Parser Error Message: An error occurred loading a configuration file: Could not
load file or assembly 'PKCS12ProtectedConfigurationProvider' or one of its
dependencies. The system cannot find the file specified.
Is it possible to encrypt web.config/appSettings using a custom configProtectionProvider when deploying to a Windows Azure hosted service running on a Windows Server 2012 virtual machine? If so, what am I missing here?
Update:
After posting this I turned on the Fusion!EnableLog registry key and now I get this additional information in the exception:
Assembly Load Trace: The following information can be helpful to determine why
the assembly 'PKCS12ProtectedConfigurationProvider, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=34da007ac91f901d' could not be loaded.
=== Pre-bind state information ===
LOG: User = NT AUTHORITY\NETWORK SERVICE
LOG: DisplayName = PKCS12ProtectedConfigurationProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34da007ac91f901d
(Fully-specified)
LOG: Appbase = file:///d:/windows/system32/inetsrv/
LOG: Initial PrivatePath = NULL
Calling assembly : (Unknown).
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using host configuration file: D:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet.config
LOG: Using machine configuration file from D:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: PKCS12ProtectedConfigurationProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=34da007ac91f901d
LOG: Attempting download of new URL file:///d:/windows/system32/inetsrv/PKCS12ProtectedConfigurationProvider.DLL.
LOG: Attempting download of new URL file:///d:/windows/system32/inetsrv/PKCS12ProtectedConfigurationProvider/PKCS12ProtectedConfigurationProvider.DLL.
LOG: Attempting download of new URL file:///d:/windows/system32/inetsrv/PKCS12ProtectedConfigurationProvider.EXE.
LOG: Attempting download of new URL file:///d:/windows/system32/inetsrv/PKCS12ProtectedConfigurationProvider/PKCS12ProtectedConfigurationProvider.EXE.
So here's another question: Why is IIS looking in the inetsrv path for this assembly instead of looking for it in the app's /bin folder? I see in the log "No application configuration file found." Does this mean the assembly binder has to find a web.config with an unencrypted appSettings section in order to parse and load it?
Did you attempt installing the assembly in the GAC yet on role start?
Information on adding assemblies to the gac on start up http://blogs.infosupport.com/adding-assemblies-to-the-gac-in-windows-azure/
I was able to fix this error by installing the NuGet package: https://www.nuget.org/packages/Pkcs12ProtectedConfigurationProvider/
I'm guessing part of the install process is registering the .dll for you.

Resources