I have a basic ASP.NET MVC 4 site which I am hosting on Azure websites. The authentication is forms authentication and has not been customised from the default template. Eve
Here's a tutorial that you could follow to setup a SQL database when deploying your application on Windows Azure. You must setup the correct connection string in your web.config which by default is pointing to a local SQL Express database when you create a new ASP.NET MVC 4 application using the Internet template.
Your SQL Azure connection string will look something like this:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=tcp:#server#.database.windows.net,1433;Initial Catalog=#DBName#;User ID=UserName#@#server#;Password=#password#;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
Although this question has been answered, I thought I might quickly share my experiences with the same problem. My case is slightly different to Mark's.
So, I had the InitializeSimpleMembership
attribute on all my controllers (actually I had it on my base controller from which all my controllers inherit), however I was still experiencing the same problem. Now, in my base controller I was also overriding the Initialize
method in order to setup some context information for our application. Part of this context setup is to check if the current user is in a particular role, hence the IsUserInRole
method was being called from within this Initialize
method, all before any action method is being called.
Now if one takes a look at the InitializeSimpleMembership
class one notices that the initializing is actually done in the OnActionExecuting
method (i.e. InitializeSimpleMembership
inherits from ActionFilterAttribute
):
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
In my case, this membership initialization was happening too late...that is, I need the Simple Membership to be initialized before I make my call to IsUserInRole
in my base controller's overridden Initialize
method.
The solution for me was relatively simple: I removed the InitializeSimpleMembership
attribute entirely and put its logic straight into my base controller so that I could call it from my Initialize
method, something like this:
public class BaseController : Controller
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
try
{
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
}
catch (Exception ex)
{
throw new InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see http://go.microsoft.com/fwlink/?LinkId=256588", ex);
}
}
}
...
protected override void Initialize(RequestContext requestContext)
{
base.Initialize(requestContext);
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
SetupControllerContext(); // my function that calls 'IsUserInRole'
}
}
Now I imagine that one should probably refactor this and put it in the Application_Start()
method, as Mark suggested, but you get the idea :). I just wanted to explain my experience just in case anybody is doing something similar in their controller's overridden Initialize
method.
After trying dozens of different suggestions from various blog posts, I have found a solution. Adding the InitialiseSimpleMembership
attribute to my home controller resolves the problem.
[InitializeSimpleMembership]
public class HomeController : Controller
After making this change, I managed several successful publishes without issues. I suspect the reason is that the following line of code in the InitializeSimpleMembershipAttribute
constructor needs to run before any calls to User.IsInRole
are made:
WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
I guess the best thing to do would be to run InitializeSimpleMembership
in Application_Start
.