你调用的对象是空的。 - 应用程序启动时不存在角色

时间:2013-09-27 00:47:59

标签: c# asp.net-mvc-4 roleprovider

所以,我有一个MVC4应用程序,我正在使用默认的登录和注册系统。在主页上,我想根据用户的角色重定向或更改消息。这是我在控制器中得到的东西:

    public ActionResult Index()
    {
        if (Roles.GetRolesForUser().Contains("Admin"))
            ViewBag.Message = "Click on a link to get started.";
        else if (Roles.GetRolesForUser().Contains("Authorized"))
            ViewBag.Message = "Click on Organizations or Interfaces to get started.";
        else if (Roles.GetRolesForUser().Contains("Unauthorized"))
            ViewBag.Message = "An administrator must activate your account before you can use this tool.";
        else
            return RedirectToAction("Login", "Account");
        return View();
    }

通常情况下,这很好用,但是如果我在登录时重新启动应用程序,并且在进行代码更改后,我会收到错误“对象引用未设置为对象的实例”。而且它指的是Roles,它显然还不存在。

经过太多的搜索,我找到了somebody with the same problem。我在那里尝试了建议的解决方案,并替换了Roles.GetRolesForUser()的所有实例。包含HttpContext.User.IsInRole,但后来我收到此错误:“建立与SQL的连接时发生了与网络相关或特定于实例的错误服务器。找不到服务器或无法访问服务器。验证实例名称是否正确以及SQL Server是否配置为允许远程连接。(提供程序:SQL网络接口,错误:26 - 错误查找指定的服务器/实例)“< / p>

经过一番搜索,我发现this,它指向我here,它说我的尝试都不会起作用,因为我首先需要重定向。虽然,他显然在谈论其他事情,但看起来非常相似。

我尝试将Index重定向到Index2,它重定向到Index3,包含相同的代码,我得到了同样的错误。我尝试了可点击链接从Index到Index2到Index3,同样的错误。我尝试通过放置WebSecurity.Logout()来强制注销;在导致错误的代码行之前,我得到一个不同的错误:“在调用”WebSecurity“类的任何其他方法之前,必须调用”WebSecurity.InitializeDatabaseConnection“方法。此调用应放在_AppStart中.cshtml文件位于您网站的根目录中。“但是内置的注销方法似乎没有调用它,它有不同的东西:

    @using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm" })) {
        @Html.AntiForgeryToken()
        <a href="javascript:document.getElementById('logoutForm').submit()">Log off</a>
    }

,单击时,立即调用WebSecurity.Logout();

这就是我知道怎么做的极限。我想每当我启动应用程序时都需要一种强制注销的方法,如果它被绑定到索引页面,它甚至可以,因为我可以在登录后避免索引页面。或者,如果有办法让它识别登录用户,那就更好了。

为了解决这个问题,起初我正在评论所有有问题的代码,重新启动它,单击注销,然后取消注释并重新启动。然后我发现在浏览器中删除cookie会修复它。我仍然不想每次都这样做。如果我找不到解决方案,我只是强迫用户点击一个注销链接,将他们带到登录页面。

2 个答案:

答案 0 :(得分:1)

代码可以抛出NullReferenceException,因为您没有检查Roles.GetRolesForUser的结果。

尝试:

string[] roles;

try
{
    roles = Roles.GetRolesForUser();
}
catch(HttpException)
{
    return RedirectToAction("Login", "Account");
}

if(roles == null) return RedirectToAction("Login", "Account");

if(roles.Contains("Admin")
{
    ViewBag.Message = "Click on a link to get started.";
}
else if (roles.Contains("Authorized"))
{
    ViewBag.Message = "Click on Organizations or Interfaces to get started.";
}
else if (roles.Contains("Unauthorized"))
{
    ViewBag.Message = "An administrator must activate your account before you can use this tool.";
}
else
{
    return RedirectToAction("Login", "Account");
}

return View();

如果您使用Roles.IsUserInRole,则代码可以简化为:

try
{
    if(Roles.IsUserInRole("Admin"))
    {
        ViewBag.Message = "Click on a link to get started.";
    }
    else if(Roles.IsUserInRole("Authorized"))
    {
        ViewBag.Message = "Click on Organizations or Interfaces to get started.";
    }
    else if (Roles.IsUserInRole("Unauthorized"))
    {
        ViewBag.Message = "An administrator must activate your account before you can use this tool.";
    }
    else
    {
        return RedirectToAction("Login", "Account");
    }
}
catch(ArgumentNullException)
{
    // No user is currently logged in
    return RedirectToAction("Login", "Account");
}
catch(HttpException)
{
    // There is no current logged on user. Role membership cannot be verified.
    return RedirectToAction("Login", "Account");
}

return View();

答案 1 :(得分:1)

好的,终于搞清楚了。 Romoku的回答是有帮助的,但我还没有足够的声誉投票:(

try / catch块可以正常工作,但它在尝试连接时仍会挂起一段时间,然后它会在“无法连接到SQL Server数据库”消息的情况下点击HttpException块。然后它会路由到Login页面,但对我来说奇怪的是,在登录页面上,它能够检测到谁登录,甚至更好,我在_Layout.cshtml文件中有类似的代码[@if(角色。 GetRolesForUser()。包含(“Admin”))]来过滤菜单选项,并在登录页面上正确运行。这真的很奇怪,因为我之前已经尝试重定向到Index2和Index3,没有运气。所以我想也许我只需要重定向到另一个控制器,然后我添加了一个“Tester”控制器,没有骰子。

原来,AccountController类上面有一个[InitializeSimpleMembership]属性,而我所要做的就是让原始代码按预期工作,将它添加到HomeController类之上,加上“using MyProject.Filters;”言。

更有趣的是,每当我收到相应的错误之前,我都在搜索“WebSecurity.InitializeDatabaseConnection”的解决方案,在Filters文件夹的“SimpleMembershipInitializer()”中找到该语句,然后在解决方案中搜索“SimpleMembershipInitializer”并且没有找到找不到任何其他命中。谁知道它隐藏在[InitializeSimpleMembership]属性中。