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 [HKLMSoftwareMicrosoftFusion!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 [HKLMSoftwareMicrosoftFusion!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:WindowsMicrosoft.NETFramework64v4.0.30319clr.dll
[1988] Running under executable F:basex64WaIISHost.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:approotbin
[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:basex64WaIISHost.exe.Config
[1988] LOG: Using host configuration file:
[1988] LOG: Using machine configuration file from D:WindowsMicrosoft.NETFramework64v4.0.30319configmachine.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.

 

 

 

The Web role was started in a wrong port

So you have started to trying out the Windows Azure Toolkit for Windows Phone 7, and created your first sample application. Then , when you launch the admin page, you get this error:

Sorry, an error occurred while processing your request.
WP7CloudApp1.Web.Infrastructure.RoleInWrongPortException: The Web role was started in a wrong port. For this sample application to work correctly, please make sure that it is running in port 443. Please review the Troubleshooting section of the sample documentation for instructions on how to do this.

image

Interesting. You notice that in the address bar, Internet Explorer has for some reason browsed to port 444 instead of the expected port 443. Looking at the documentation on MSDN for Azure, in the paragraph Testing an HTTPS endpoint in the compute emulator, one can find this little tidbit: If a port that you specify is not available, in the case of an HTTPS endpoint 443, the compute emulator will increment the port number until it finds one that is free.

And the Compute Emulator confirms the fact that is started to listen on port 444 instead:

image

So what’s is keeping port 443 busy?

Netstat –a –b says nothing of interest really, other than the fact that something is indeed listening on port 443 (and port 80 also, BTW):

Active Connections

Proto  Local Address          Foreign Address        State
TCP    0.0.0.0:80             Magnus-PC:0            LISTENING
Can not obtain ownership information
TCP    0.0.0.0:135            Magnus-PC:0            LISTENING
RpcSs
[svchost.exe]
TCP    0.0.0.0:443            Magnus-PC:0            LISTENING
Can not obtain ownership information
So you start to close down the usual suspects, as IIs etc. but still something is listening on port 443.

It took me some time, but I finally figured it out…. SQL Server Reporting Services.

image

Maybe you are like me, when installing SQL Server, you opt in for all features, just in case… Well, this time it bit me hard.

Stopping the SQL Reporting Services Service, and restarting the Compute Emulator, my Windows Azure sample application for Phone 7 started to work again:

image