0

所以,我有一个 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.GetRolesForUser().Contains 的所有实例替换为 HttpContext.User.IsInRole,但随后出现此错误:“建立与 SQL 的连接时发生与网络相关或特定于实例的错误服务器。未找到或无法访问服务器。验证实例名称是否正确以及 SQL Server 是否配置为允许远程连接。(提供程序:SQL 网络接口,错误:26 - 错误定位服务器/指定实例)“

经过一番搜索后,我找到了这个,它指向我这里,它说我的尝试都不会奏效,因为我需要先重定向。虽然,他显然在谈论其他事情,但看起来很相似。

我尝试让 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 可以修复它。我仍然不想每次都这样做。如果我无法找到解决方案,我将强制用户单击将他们带到登录页面的注销链接。

4

2 回答 2

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();
于 2013-09-27T01:03:50.590 回答
1

好的,终于弄明白了。Romoku 的回答很有帮助,但我还没有足够的声誉来投票:(

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

原来 AccountController 类在它上面有一个 [InitializeSimpleMembership] 属性,我要做的就是使原始代码按预期工作是在 HomeController 类上方添加它,加上“使用 MyProject.Filters;” 陈述。

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

于 2013-09-27T15:48:49.923 回答