Udostępnij za pośrednictwem


InitializeSimpleMembership Attribute and SimpleMembership Exceptions

The InitializeSimpleMembership Attribute ensures that before any membership (login/register) related functionality is run, that the membership database has been created. If the database is not yet created, the code will automatically create one. If the simple membership initialization fails, the Web Application can continue to run requests that don’t require membership.

Simple membership initialization failure can occur for the following reasons.

  1. The most common reason is the connection string to SQL Server is not valid. For example, you might not have SQL Server available. This is a frequent cause of failure in Azure. The ASP.NET MVC 4 templates by default use SqlExpress when created with Visual Studio 2010 and LocalDB when using Visual Studio 2012. SqlExpress is not installed on Azure and LocalDB does not run on Azure.
  2. Multiple DBContext objects on the same database.

The following code shows the InitializeSimpleMembership Attribute code that is added to a new ASP.NET MVC application. The code is found in the Filters folder:

 using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Threading;
using System.Web.Mvc;
using WebMatrix.WebData;
using MvcV4.Models;

namespace MvcV4.Filters
{
    [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 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<UsersContext>(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("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 https://go.microsoft.com/fwlink/?LinkId=256588", ex);
                }
            }
        }
    }
}

Comments

  • Anonymous
    August 21, 2012
    Have you changed something with the connection strings? I can't see it documented anywhere, but with SQL Server the username parameter name seems to have been changed from "User Name" to "User".

  • Anonymous
    August 26, 2012
    I have the exception when using Azure (it works fine on my computer connecting to SQL Azure). What do we need to do when dealing with Azure?

  • Anonymous
    September 13, 2012
    So, what should we do? I am using SQL Server 2008 and I have connection string pointing to my application. I am not sure I'd like to use the default provider, I already have Operators (Users) table in my database and I want to use that table instead. What / where should I change? Thanks in advance

  • Anonymous
    September 17, 2012
    Thanks for your article But I have search all over the internet to resolve the situation below : How to Handle the initialization when Simplemebership and context share the same database and the same context ? I have a Database and I want to store the simplemembership information and my domain model tables too. But how to Initialize them at the same time and seeding them ? This seems to be impossible Thanks

  • Anonymous
    September 26, 2012
    Article post is as useless as they come.

  • Anonymous
    September 27, 2012
    The comment has been removed

  • Anonymous
    October 10, 2012
    Here is a great primer for learing about SimpleMembership: weblogs.asp.net/.../simplemembership-membership-providers-universal-providers-and-the-new-asp-net-4-5-web-forms-and-asp-net-mvc-4-templates.aspx

  • Anonymous
    October 14, 2012
    @Mirza  you need to have the correct values in the defaultconnection connection string. I copied mine into there

  • Anonymous
    October 26, 2012
    Hi, I just questioning why we need this filter here stackoverflow.com/.../why-initializesimplemembershipattribute-in-mvc-4-app Initially I think this filter only useful for controllers/actions that has Membership aware and provide something like lazy initialization but after sometimes, I quickly used this filter everywhere until I realize I don't need this filter but WebSecurity.InitializeDatabaseConnection required to be called in Application_Start. Lazy initialization is not really necessary because not only this way will make non-membership controllers/views loads faster but initialize in app start once also do the same. Sorry to say that, based on my point of view, using this filter is impractical because anyone definitely use Membership API anywhere like calling User.IsInRole in _Layout.cshtml to show menu for admin. WebSecurity.InitializeDatabaseConnection required to be called before using any of the Membership or Role API. The existence of LazyInitializer.EnsureInitialized in the filter makes move this code into Application_Start. I hope by moving the filter to Application_Start save other developers time. There is no reason not to initialize membership database in Application_Start unless you are designing non-membership application. Initialization for SimpleMembership is required even though you declare the SimpleMembershipProvider in the web.config to replace the default membership provider defined in machine.config. It is not worth by having this filter but later introduce a few problems It is too late to initialize database (and/or membership related objects) when the first request has been called.

  • Anonymous
    November 24, 2012
    Can someone please post a correct connection string example for using simple membership and sqlazure.

  • Anonymous
    January 07, 2013
    Why would multiple DbContext on one database cause errors?

  • Anonymous
    January 20, 2013
    The comment has been removed

  • Anonymous
    June 30, 2013
    You need to ACTUALLY explain scenario 2 where multiple DB Contexts cause an error.  Are you saying to change the attrbiute to use the same context as the rest of your application?  I can't get that working.

  • Anonymous
    July 13, 2013
    The comment has been removed

  • Anonymous
    July 24, 2013
    It's a little frustrating that this is the target of the error link go.microsoft.com/fwlink, but you don't actually address 'half' the causes of errors - WHY would having more than one DbContext cause problems, and HOW should we resolve those problems? In fact you don''t seem really to address the case where connecting to azure either.

  • Anonymous
    August 28, 2013
    I struggled with the same issue, and only just realized that if you look at the constructor of UsersContext it is initialized with a hardcoded connectionstring name of "DefaultConnection". If you have this connection string name in Web.Config (or Machine.Config) it will work. But if you don't have that name in Web.Config it may very well take the connection details from Machine.Config which will probably not point to the right server in a hosted environment.

  • Anonymous
    October 08, 2013
    If you're using SQL Server, be sure to have your connection string include providerName="System.Data.SqlClient" (That was a long hunt)

  • Anonymous
    November 05, 2013
    Point 2 is referring to the fact you cannot have two objects in the database with the same name. If you don't modify the SimpleMembership it will try and create a table named UserProfile. If you have the universal providers set up to use the same database it has a foreign key constraint on the Profiles table with the same name UserProfile. Renaming the foreign key constraint should stop the error. If you still get an error then try setting the SimpleMembership to use an empty database. You can then get scripts for everything it creates and run them on your main database to find where the conflict occurs.

  • Anonymous
    November 10, 2013
    The comment has been removed

  • Anonymous
    February 12, 2014
    What's wrong with Microsoft  ASP Team? Poor docu.

  • Anonymous
    March 24, 2014
    I have tried in SQLServer 2008, mentioned the connection string in web.config file Solution: <add name="DefaultConnection" connectionString="uid=****;pwd=*****;server=(local); database=aspnet-SampleMVC4Layout-20140325111706" providerName="System.Data.SqlClient" /> If Membership db does not exists, system automatically creates the db. Issue was identified in FiltersInitializeSimpleMembershipAttribute.cs WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

  • Anonymous
    June 03, 2014
    what is the actual meaning of UsersContext mvc.net

  • Anonymous
    July 07, 2014
    Add a connection string in web.config named "DefaultConnection" pointing to the correct datasource, that did the trick for me :o) <connectionStrings>    <add name="MvcAuction.Models.AuctionsDataContext" connectionString="Data Source=(LocalDb)v11.0;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|MvcAuction.Models.AuctionDataContext.mdf" providerName="System.Data.SqlClient" />    <add name="DefaultConnection" connectionString="Data Source=(LocalDb)v11.0;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|MvcAuction.Models.AuctionDataContext.mdf" providerName="System.Data.SqlClient" />  </connectionStrings>

  • Anonymous
    September 16, 2014
    here is the working connection string: <add name="DefaultConnection" connectionString="server=WKMJ84N9BSQLEXPRESS;Database=aspnet-MvcApplication1-20140916105626;Integrated Security=SSPI;" providerName="System.Data.SqlClient" /> replace WKMJ84N9B with you machine id

  • Anonymous
    September 26, 2014
    How can I change this class to connect with Azure? I tried with: "data source=:azuredbname.database.windows.net;initial catalog=mydb;persist security info=True;user id=username;password=pasword;MultipleActiveResultSets=True;App=EntityFramework;" The same in the web.config, but it still not work.

  • Anonymous
    November 03, 2014
    The comment has been removed

  • Anonymous
    December 16, 2014
    How can i use EF5 codefirst model to create oracle database? Thank you.

  • Anonymous
    March 30, 2015
    thanks suresh ganapa for provide right information.

  • Anonymous
    April 14, 2015
    Ahmed Salah your answer works for me i just wrote my server name and it works, thak you so much.

  • Anonymous
    April 19, 2015
    Needed the correct connection string. Needed to comment out a few things in the Filters folder > InitializeSimpleMembershipAttribute.vb I have a hosted account where I cannot make databases.  It has to use the only one there that I have access.  So I had to comment out the part that was trying to make a new database.  This is what I ended up with in InitializeSimpleMembershipAttribute.vb Private Class SimpleMembershipInitializer        Public Sub New()            'Database.SetInitializer(Of UsersContext)(Nothing)            Try                'Using context As New UsersContext()                '    If Not context.Database.Exists() Then                '        ' Create the SimpleMembership database without Entity Framework migration schema                '        CType(context, IObjectContextAdapter).ObjectContext.CreateDatabase()                '    End If                'End Using                WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables:=True)            Catch ex As Exception                Throw New InvalidOperationException("The ASP.NET Simple Membership database could not be initialized. For more information, please see go.microsoft.com/fwlink, ex)            End Try        End Sub    End Class Notice that most of it was commented out except for the initilzeDatabaseConnection part.

  • Anonymous
    October 12, 2015
    when i am clciking on login or register then error--exception has been thrown by target of invocation