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

25

除了已经在AccountController.cs文件中生成的内容之外,我无法让WebSecurity对象在任何地方工作。 Account控制器在顶部设置了 [InitializeSimpleMembership] 属性。例如,登录函数不会抱怨调用 WebSecurity.Login(...)。我向AccountController添加了一个子操作:

[ChildActionOnly]
        [AllowAnonymous]
        public ActionResult NavBar()
        {
            NavBarViewModel viewModel = new NavBarViewModel();
            viewModel.LinkItems = new List<NavBarLinkItem>();

            if (Request.IsAuthenticated)
            {
                SimpleRoleProvider roleProvider = new SimpleRoleProvider();
                if (roleProvider.IsUserInRole(User.Identity.Name, "User"))
                {
                    viewModel.LinkItems.Add(new NavBarLinkItem() 
                    { Title = "Create Project", Action = "Create", Controller = "Project" });

                }

            }

            viewModel.LinkItems.Add(new NavBarLinkItem() { Title="Help", Action="Index", Controller="Help" });

            return PartialView("_NavBar", viewModel);
        }

代码不做修改时,在 "if (roleProvider.IsUserInRole(User.Identity.Name, "User"))" 行会崩溃,并显示相应的错误信息。所以我进入InitialzeSimpleMembershipAttribute.cs文件,将此行复制/粘贴到函数顶部:

WebSecurity.InitializeDatabaseConnection("DefaultConnection", "UserProfile", "UserId", "UserName", autoCreateTables: true);

...然后收到一个错误信息,指出WebSecurity.InitializeDatabaseConnection应该只被调用一次。这是有道理的,因为控制器定义的顶部应该已经调用了这个函数(而且它似乎做得很好)。为了安全起见,我将上面的调用更改为:

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

...并获取原始错误消息,提示应该在blah blah blah之前调用WebSecurity.InitializeDatabaseConnection。非常感谢您对这种疯狂现象的任何见解。

5个回答

49

这里有一份更好的解释:http://odetocode.com/blogs/scott/archive/2012/09/24/perils-of-the-mvc4-accountcontroller.aspx

你只需要做以下几件事情:

  1. AccountController 顶部删除 [InitializeSimpleMembership]
  2. 将 /Filters/InitializeSimpleMembershipAttribute.cs(第39行)中的 WebSecurity.InitializeDatabaseConnection(...) 调用复制到 /AppStart/AuthConfig.cs
  3. 可以自由地将 InitializeSimpleMembershipAttribute.cs 从项目中删除

你不一定要将 InitializeDatabaseConnection() 调用添加到 AuthConfig.RegisterAuth() 中,但这似乎是一个合理的位置,并且可以保持 Global.asax 的清洁。

实质上,你所做的就是从原始属性中提取初始化调用,并在 Application_Start 上显式地调用它。属性中的其他内容仅是条件检查,以防你不使用(或不需要)SimpleMembership。


我只需要在我的控制器顶部放置[InitializeSimpleMembership]属性,现在它可以工作了。 - jwatts1980
很好的解释,兄弟。 - sensei
但这样做会有什么后果呢?我想这样做是有原因的。 - Paul C

9

在我需要访问WebSecurity的控制器顶部添加[InitializeSimpleMembership](如在AccountController中提到和找到的)为我解决了问题。但不确定这是否是预期的实现方法...

[InitializeSimpleMembership]
public class DataController : Controller
{ ... }

5
我在网络上找到了这个链接:http://forums.asp.net/t/1718361.aspx/1。基本上,不要使用SimpleRoleProvider类型。有一个可用的Roles对象,可以像这样简单地调用:
if (Request.IsAuthenticated)
{
  if( Roles.IsUserInRole(User.Identity.Name, "User"))
  {
    viewModel.LinkItems.Add(new NavBarLinkItem() 
    { Title = "Create Project", Action = "Create", Controller = "Campaign" });
  }
}

1
这并不像它应该的那样清晰。我看了链接,但它与我正在做的事情无关(我想?)因为我不想创建一个角色。 我有你遇到的同样问题,我得到了一个“不能调用两次”的消息,但是当我把“第二个”拿出来时,我得到了“你必须调用…”的消息。导致“你必须调用…”消息崩溃的是: if (OAuthWebSecurity.Login(result.Provider, result.ProviderUserId, createPersistentCookie: false))有什么想法吗? - Michael Blackburn

1

首先,您需要在web.config中设置您的角色和成员提供程序:

<authentication mode="Forms">
  <forms loginUrl="/Account/Login" slidingExpiration="true" timeout="60" />
</authentication>
<membership defaultProvider="p1">
  <providers>
    <add name="p1" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData"/>
  </providers>
</membership>
<roleManager enabled="true" defaultProvider="p1">
  <providers>
    <add name="p1" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
  </providers>
</roleManager>

当您创建SimpleRoleProvider的新实例时,请使用非空构造函数,并将web.config中设置为默认RoleProvider的参数提供给它:
SimpleRoleProvider srp = new SimpleRoleProvider(Roles.Provider);

解决方案在SimpleMembershipProvider的情况下是相同的:
SimpleMembershipProvider msp = new SimpleMembershipProvider(Membership.Provider);

1
在我的情况下,我需要在IIS身份验证设置中禁用匿名身份验证。

然后我需要启用表单和Windows身份验证。这当然取决于您的应用程序所需的身份验证方式。

一旦我这样做,错误就消失了,应用程序按预期工作。


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