Yesterday Steve Marx and I covered the new Windows Azure Tools for Visual Studio 1.4 release on the Cloud Cover Show (will publish on Friday, 8/5). Since the tools shipped the same day as the show we literally only had an hour or so before the show to pull together a demonstration of some of the new capabilities. I think we did a reasonably good job, but I’d like to further clarify a few things in this post.
One of the items I demonstrated on the show was deploying the new MVC 3 template to Windows Azure.
It’s great having this template built into the tools. No longer do I have to hit Steve Marx’s website to lookup the requisite MVC 3 assemblies.
Immediately after creating the projects I confirmed that my assemblies were all added and set to Copy Local = True by default (one of the nice aspects of having the template baked into the tools) and published to Windows Azure. I was a bit surprised when suddenly I got the YSOD:
Naturally, I updated my web.config file with <customErrors mode="Off" /> and redeployed to Windows Azure.
In case you don’t want to click the image, the error is:
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)"
In retrospect, I should have expected this error as I received validation warnings within Visual Studio (one of the other nice updates in the 1.4 tools):
I was quite baffled as to why MVC 3 suddenly would require SQL Express (or any flavor of SQL for that matter), until Anders Hauge—a PM on the Visual Studio team—clued me in on the fact that they have shipped the ASP.NET Universal Providers within the MVC 3 template.
For information on these providers, see Introducing System.Web.Providers – ASP.NET Universal Providers for Session, Membership, Roles and User Profile on SQL Compact and SQL Azure by Scott Hanselman for a great introduction.
It turns out that, by default, the template uses the default session state provider in ASP.NET Universal Providers as the ASP.NET session state provider, which in turn uses SQL Express (by default) to store session state.
<sessionState mode="Custom" customProvider="DefaultSessionProvider"> <providers> <add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=18.104.22.168, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" /> </providers> </sessionState>
Okay, so what’s the best way to get this to work?
Well, in my haste on the Cloud Cover Show, I simply uninstalled the ASP.NET Universal Provider package, which removed the custom session state provider. Of course, once I deployed, I no longer saw the YSOD. This is probably not the best way to go about fixing this, as the ASP.NET Universal Providers are really worth using. For a good analysis of the options, take a look at Nathan’s discussion on various ways to resolve this in his post Windows Azure Tools 1.4 Released.
In retrospect, I wish I had simply created a SQL Azure database and used it instead. It’s pretty easy to do:
- In the Windows Azure Platform Management Portal, select Database and create a new database. I called mine UniversalProviders.
- Select the database and click the View … button to grab/copy your connection string. Note: you’ll need to remember your SQL login password.
- In your solution, update the ApplicationServies and DefaultConnection connection strings using your SQL Azure connection string. Note: you must set MultipleActiveResultSets=True in the connection string, so be sure to add it back if you’ve copied the SQL Azure connection string from the portal.
<connectionStrings> <add name="ApplicationServices" connectionString="Server=tcp:YOURDB.database.windows.net,1433;Database=UniversalProviders;User ID=YOURLOGIN@YOURDB;Password=YOURPWD;Trusted_Connection=False;Encrypt=True;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" /> <add name="DefaultConnection" connectionString="Server=tcp:YOURDB.database.windows.net,1433;Database=UniversalProviders;User ID=YOURLOGIN@YOURDB;Password=YOURPWD;Trusted_Connection=False;Encrypt=True;MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" /> </connectionStrings>
- Deploy to Windows Azure.
Now, when we run the applications, it works!
In fact, I recommend you use Database Manager from the portal …
… to open up the database and see that, in fact, you now have a dbo.Sessions table in the database.
What’s more, if you then click Log On and setup a user, you’ll see all the membership & roles work within the MVC application in Windows Azure!
Wrapping up, apologies for not digging into this in greater depth on the show – hopefully this post helps to clarify a few things.