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.

 

 

 

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>

 

How to use CDN links in your ASP.NET MVC application to serve static content from a cookieless domain

Here’s one way you can use CDN links in your ASP.NET MVC application.

Problem:
When you develop your ASP.NET MVC application and use a link to a static content, such as css, jpg’s etc, you may want to server these from a CDN or at least a domain that doesn’t server cookies with the request. For those of you who have been using the Google Page Speed add-in for FireFox, you know what I’m talking about:

Untitled1

So the question is, how do you get your markup that normally may look something like this:


to look something like this on your production server:


When you are developing using the local web server (Cassini), you don’t want the CDN links in your code, but after you have published the page to prod, you want it to use the CDN link. One way to make this work is to make an extension helper method that creates the correct link based on if you run in dev or prod. Here is my suggestion:

public static MvcHtmlString CDNLink(this HtmlHelper html,
string tagName,
string contentTag,
string contentUrl,
object htmlAttributes)
{
var contentLink = new TagBuilder(tagName);
var contentServerUrl = ConfigurationManager.AppSettings["ContentServerUrl"];
contentServerUrl = string.IsNullOrEmpty(contentServerUrl) ? "{0}" : contentServerUrl;
contentLink.MergeAttribute(contentTag, string.Format(contentServerUrl, contentUrl));
contentLink.MergeAttributes((IDictionary<string, string="">)htmlAttributes, true);
return MvcHtmlString.Create(contentLink.ToString());
}

 

It is pretty straightforward to use:

<%=html.cdnlink("link", new="" string="">
{
{"rel", "stylesheet"},
{"type","text/css"}
}) %>

<%=html.cdnlink(“link”, new=”” string=””>

<%=html.cdnlink(“link”, new=”” string=””>

Pass the tag name (“link”), the content attribute (“href”), the actual content link (“file.css”) and optional HTML attributes. In your web.config file, add an application settings for the content server url like this in dev


And in prod, use something like this:

There you go, hope you will find it useful.