在调用“WebSecurity”类的任何其他方法之前,您必须先调用“WebSecurity.InitializeDatabaseConnection”方法。

23
每次我使用Visual Studio进行调试时,都会出现以下错误信息:

在调用“WebSecurity”类的任何其他方法之前,必须先调用“WebSecurity.InitializeDatabaseConnection”方法。此调用应放置在站点根目录下的_AppStart.cshtml文件中。

但是这种情况发生在每一次调试时,且当我将应用程序部署到生产环境时,也会不定期出现此错误。

我确实已经放置了正确的标签:

[Authorize(Roles = "admin")]
[InitializeSimpleMembership]
public class IndexController : Controller

给控制器,这是筛选器的方式。它就是不想工作。

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

namespace MeetingTaskManagement.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 http://go.microsoft.com/fwlink/?LinkId=256588", ex);
                }
            }
        }
    }
}

有人能帮我整理一下这个吗?


1
我想知道为什么默认的ASP.NET MVC Internet应用程序项目不会直接按照答案建议执行。 - jingtao
这个问题是否发生在ASP.NET MVC 5中? - Tassisto
不是的,因为MVC 5正在使用WIF。这样会更好。 - DarthVader
6个回答

67

从您的控制器中删除SimpleMemberShip属性并将其废弃。将以下内容添加到您的global.asax文件中。

    private static SimpleMembershipInitializer _initializer;
    private static object _initializerLock = new object();
    private static bool _isInitialized;

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();

        LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);
    }

    public class SimpleMembershipInitializer
    {
        public SimpleMembershipInitializer()
        {
            using (var context = new UsersContext())
                context.UserProfiles.Find(1);

            if (!WebSecurity.Initialized)
                WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);
        }
    }

11
我喜欢@Bastaspast说“trash it”的那部分。 - jingtao
“context.UserProfiles.Find(1);”这行代码应该做什么?在调试模式下检查时,它似乎返回了一个用户列表。但是这行代码会导致一个错误,要求我使用Code First Migration更新数据库。如果我删除这行代码,程序似乎可以正常工作。那我可以安全地删除这行代码吗? - mal
1
这行代码仅用于通过 CodeFirst 触发数据库的创建。当您确定数据库已经存在时,可以安全地删除此行。 - Bastaspast
我喜欢这个解决方案,但如果我们升级到ASP.NET MVC 5会怎样呢?丢弃一些东西会有帮助吗 :p - Tassisto
我去年12月将我的项目更新到MVC5,没有遇到任何问题。此致敬礼。 - Bastaspast
在应用程序中使用Area时出现了相同的错误:(如何解决? - Amirhossein Mehrvarzi

10
为了简化您的Global.asax,您可以像这样将初始化代码放入class AuthConfig中:
public static class AuthConfig
{
    private static SimpleMembershipInitializer _initializer;
    private static object _initializerLock = new object();
    private static bool _isInitialized;

    public static void RegisterAuth()
    {
        // Ensure ASP.NET Simple Membership is initialized only once per app start
        LazyInitializer.EnsureInitialized(ref _initializer, ref _isInitialized, ref _initializerLock);

        // To let users of this site log in using their accounts from other sites such as Microsoft, Facebook, and Twitter,
        // you must update this site. For more information visit http://go.microsoft.com/fwlink/?LinkID=252166

        //OAuthWebSecurity.RegisterMicrosoftClient(
        //    clientId: "",
        //    clientSecret: "");

        //OAuthWebSecurity.RegisterTwitterClient(
        //    consumerKey: "",
        //    consumerSecret: "");

        //OAuthWebSecurity.RegisterFacebookClient(
        //    appId: "",
        //    appSecret: "");

        //OAuthWebSecurity.RegisterGoogleClient();
    }

    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 http://go.microsoft.com/fwlink/?LinkId=256588", ex);
            }
        }
    }
}

这个很棒!我只想补充一点,我不得不添加几个引用:System.Data.Entity,System.Data.Entity.Infrastructure,System.Threading和WebMatrix.WebData。 - ourmandave

4

我只是将[InitializeSimpleMembership]从AccountController中删除,并将其放到了HomeController中。因为初始化是以懒惰的方式完成的...我只是想赶快解决它...然后它就起作用了!!!


1
我曾经在Membership提供程序和我的领域模型中使用了单一的上下文,这是一个聪明的做法。结果证明这是问题的根源;你不能在单一上下文中同时使用Membership提供程序和领域类。
你需要有两个上下文。

0
要求仅为调用WebSecurity数据库连接,您可以执行以下操作以使其正常工作:
var WebSecDBContx = new UsersContext();
var CreatedByUser = WebSecDBContx.UserProfiles.Find(UserID);
string CreatedByUserName = CreatedByUser.UserName;

0
为什么不在项目根目录中创建_AppStart.cshtml,并将初始化代码放置在其中,就像错误消息所述的那样。
@{WebMatrix.WebData.WebSecurity.InitializeDatabaseConnection("DefaultConnection", "TableName", "ColumnId", "ColumnName", autoCreateTables: false);}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接