I think my understanding on SimpleMembershipProvider is almost 60% and the rest is getting to know how it internally work.
You can quickly found some is
Inspired on Aaron's answer I've implemented a solution that keeps Global.asax clean and reuses the code that comes with the template.
Add one line to RegisterGlobalFilters method in RegisterApp_Satrt/FilterConfig.cs
filters.Add(new InitializeSimpleMembershipAttribute());
Add a default constructor to InitializeMembershipAttribute class that is found in Filters folder. The content of this constructor is going to be the same line that is in the override of OnActionExecuting method. (Here is how the constructor looks like)
public InitializeSimpleMembershipAttribute()
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}Comment out (or remove) the override of OnActionExecuting method.
And that's it. This solution is giving me two main benefits:
The flexibility to check things related to membership and roles immediately after FilterConfig.RegisterGlobalFilters(GlbalFilters.Filters) line gets executed on global.asax.
Ensures that WebSecurity database initialization is executed just once.
EDIT: The InitializeSimpleMembershipAttribute that I'm using.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class InitializeSimpleMembershipAttribute : ActionFilterAttribute
{
private static SimpleMembershipInitializer _initializer;
private static object _initializerLock = new object();
private static bool _isInitialized;
public InitializeSimpleMembershipAttribute()
{
// Ensure ASP.NET Simple Membership is initialized only once per app start
LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
}
//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);
//}
private class SimpleMembershipInitializer
{
public SimpleMembershipInitializer()
{
Database.SetInitializer(null);
try
{
using (var context = new UsersContext())
{
if (!context.Database.Exists())
{
// Create the SimpleMembership database without Entity Framework migration schema
((IObjectContextAdapter)context).ObjectContext.CreateDatabase();
}
}
WebSecurity.InitializeDatabaseConnection("Database_Connection_String_Name", "Users", "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);
}
}
}
}