Azure Role does not start, Could not load file or assembly ‘System.Web.Mvc, Version=4.0.0.0

The sub title of this post is also; how to do pre-web.config assembly binding for Windows Azure.

So I upgraded my ASP.NET MVC 4 Web Application to MVC 5 and published to my Windows Azure Web Role/Worker Role.

What might a little unusual is that I have my web application and the worker role in the same project/role, since the workload is currently very little. In fact, I have a Web Role that spawn background tasks using classes that inherits from RoleEntryPoint.

After upgrade and publish, my worker role did not start. And even though I had enabled all the logging I could think of, the only error I got was that WaIISHost.exe has crashed with an Exception. No stack trace. Bummer.

 

So I had to remote desktop into one of the roles, firing up DebugView.exe and I deployed. This is what I got:

[3464] Microsoft.WindowsAzure.ServiceRuntime Critical: 201 :
[3464] Role entrypoint could not be created:
[3464] System.TypeLoadException: Unable to load the role entry point due to the following exceptions:
[3464] — System.IO.FileLoadException: Could not load file or assembly ‘System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
[3464] File name: ‘System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’
[3464]
[3464] WRN: Assembly binding logging is turned OFF.
[3464] To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
[3464] Note: There is some performance penalty associated with assembly bind failure logging.
[3464] To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
[3464]
[3464] —> System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
[3464] at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
[3464] at System.Reflection.RuntimeModule.GetTypes()
[3464] at System.Reflection.Assembly.GetTypes()
[3464] at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetRoleEntryPoint(Assembly entryPointAssembly)
[3464] — End of inner exception stack trace —
[3464] at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetRoleEntryPoint(Assembly entryPointAssembly)
[3464] at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.CreateRoleEntryPoint(RoleType roleTypeEnum)
[3464] at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.InitializeRoleInternal(RoleType roleTypeEnum)

Hmm.. thats odd, since when I upgraded to MVC 5, I also has these assembly bindings in my web.config:

<dependentAssembly>
<assemblyIdentity name=”System.Web.Mvc” publicKeyToken=”31BF3856AD364E35″ culture=”neutral”/>
<bindingRedirect oldVersion=”0.0.0.0-5.0.0.0″ newVersion=”5.0.0.0″/>
</dependentAssembly>

So let’s enable Fusion logging. It gave me a little bit more details:

[1988] Microsoft.WindowsAzure.ServiceRuntime Critical: 201 :
[1988] Role entrypoint could not be created:
[1988] System.TypeLoadException: Unable to load the role entry point due to the following exceptions:
[1988] — System.IO.FileLoadException: Could not load file or assembly ‘System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
[1988] File name: ‘System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’
[1988]
[1988] Assembly manager loaded from: D:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
[1988] Running under executable F:\base\x64\WaIISHost.exe
[1988] — A detailed error log follows.
[1988]
[1988] === Pre-bind state information ===
[1988] LOG: DisplayName = System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
[1988] (Fully-specified)
[1988] LOG: Appbase = file:///F:/approot/bin
[1988] LOG: Initial PrivatePath = F:\approot\bin
[1988] Calling assembly : Mvc.Mailer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
[1988] ===
[1988] LOG: This bind starts in default load context.
[1988] LOG: Using application configuration file: F:\base\x64\WaIISHost.exe.Config
[1988] LOG: Using host configuration file:
[1988] LOG: Using machine configuration file from D:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
[1988] LOG: Post-policy reference: System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
[1988] LOG: Attempting download of new URL file:///F:/approot/bin/System.Web.Mvc.DLL.
[1988] WRN: Comparing the assembly name resulted in the mismatch: Major Version
[1988] ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
[1988]
[1988] —> System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.
[1988] at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module)
[1988] at System.Reflection.RuntimeModule.GetTypes()
[1988] at System.Reflection.Assembly.GetTypes()
[1988] at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetRoleEntryPoint(Assembly entryPointAssembly)
[1988] — End of inner exception stack trace —
[1988] at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.GetRoleEntryPoint(Assembly entryPointAssembly)
[1988] at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.CreateRoleEntryPoint(RoleType roleTypeEnum)
[1988] at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.InitializeRoleInternal(RoleType roleTypeEnum)

Ok, so now I know which DLL tries to load the older MVC 4 assemblies, but why isn’t my binding taking care of that?

As it turns out, since I am using my combined codebase for the worker role, essentially my Application.Web.dll, the web.config is of course not used when the WaIISHost.exe is loading that assembly. So what I had to do is to create a Application.Web.dll.config in my project root, set it to Content and Copy Always(or Copy If Newer), and copy paste in all my Assemlby Binding elements.

Now, the AZure WAIIHost.exe picks it up correctly, and my role is started correctly.

 

 

 

To call this method, the “Membership.Provider” property must be an instance of “ExtendedMembershipProvider”.

Membership Provider property must be an instance of ExtendedMembershipProvider

Have you just created an ASP.NET MVC 4 internet project, decided to use the universal providers to utilize SQL Azure? So you have installed the NuGet package Microsoft ASP.NET Universal Providers and now your project bombs with:

To call this method, the “Membership.Provider” property must be an instance of “ExtendedMembershipProvider”.

You search for a solution, find Jon Galloway article SimpleMembership, Membership Providers, Universal Providers and the new ASP.NET 4.5 Web Forms and ASP.NET MVC 4 templates , where he states: “If you want to use the new AccountController, you’ll either need to use the SimpleMembershipProvider or another valid ExtendedMembershipProvider. This is pretty straightforward.”

Well, he fails to describe what you’ll need to do if you want continue to use the AccountController. Fear not, here’s what you’ll have do to.

Edit your web.config and replace:

<profile defaultProvider=DefaultProfileProvider>
<providers>
  <add name=DefaultProfileProvider” type=System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
connectionStringName=DefaultConnection
applicationName=/ />
  </providers>
</profile>
<membership defaultProvider=DefaultMembershipProvider>
  <providers>
    <add name=DefaultMembershipProvider
type=System.Web.Providers.DefaultMembershipProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 connectionStringName=DefaultConnection enablePasswordRetrieval=false” enablePasswordReset=true” requiresQuestionAndAnswer=false
requiresUniqueEmail=false” maxInvalidPasswordAttempts=5
minRequiredPasswordLength=6” minRequiredNonalphanumericCharacters=0
passwordAttemptWindow=10
applicationName=/ />
  </providers>
</membership>
<roleManager defaultProvider=DefaultRoleProvider>
  <providers>
    <add name=DefaultRoleProvider type=System.Web.Providers.DefaultRoleProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 connectionStringName=DefaultConnection applicationName=/ />
  </providers>
</roleManager>

With:

<profile defaultProvider=SimpleProfileProvider>
  <providers>
    <add name=SimpleProfileProvider type=WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData
        connectionStringName=DefaultConnection applicationName=/ />
</providers>
</profile>
<membership defaultProvider=SimpleMembershipProvider>
  <providers>
      <add name=SimpleMembershipProvider” type=WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData />
  </providers>
</membership>
<roleManager defaultProvider=SimpleRoleProvider>
  <providers>
    <add name=SimpleRoleProvider type=WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData/>
  </providers>
</roleManager>