对象引用未设置为对象的实例.- 应用程序启动时角色不存在
本文关键字:启动 应用程序 角色 不存在 实例 设置 对象 对象引用 | 更新日期: 2023-09-27 18:32:55
所以,我有一个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((的所有实例。包含 HttpContext.User.IsInRole,但后来我收到此错误:"与 SQL Server 建立连接时发生与网络相关或特定于实例的错误。找不到服务器或无法访问服务器。验证实例名称是否正确,以及 SQL Server 是否配置为允许远程连接。(提供程序:SQL 网络接口,错误:26 - 查找指定的服务器/实例时出错(">
经过一堆搜索,我找到了这个,它把我指向了这里,它说我的尝试都不起作用,因为我首先需要重定向。虽然,他显然在谈论别的东西,但它看起来很相似。
我尝试将索引重定向到 Index2,它重定向到 Index3,包含相同的代码,但遇到了相同的错误。我尝试了可单击的链接从索引到索引 2 再到索引 3,同样的错误。我尝试通过放置 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可以修复它。我仍然不想每次都这样做。如果我找不到解决方案,我只会强制用户单击将他们带到登录页面的注销链接。
代码可能会抛出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();
好的,终于想通了。Romoku的回答很有帮助,但我没有足够的声誉来投票:(
try/catch 块可以工作,但它在尝试连接时仍然挂起一段时间,然后它命中 HttpException 块,并显示消息"无法连接到 SQL Server 数据库"。然后它路由到登录页面,但对我来说奇怪的是,在登录页面上,它能够检测谁登录了,更好的是,我在 _Layout.cshtml 文件 [@if (Roles.GetRolesForUser(( 中也有类似的代码。包含("管理员"((]来过滤菜单选项,并在登录页面上正确运行这些选项。这真的很奇怪,因为我之前已经尝试过重定向到 Index2 和 Index3,但没有运气。所以我想也许我只需要重定向到不同的控制器,我添加了一个"测试器"控制器,没有骰子。
事实证明,AccountController 类在其上方有一个 [InitializeSimpleMembership] 属性,为了使原始代码按预期工作,我所要做的就是在 HomeController 类上方添加它,加上"using MyProject.Filters;"语句。
更有趣的是,每当我之前遇到相应的错误时,我都会搜索"WebSecurity.InitializeDatabaseConnection"的解决方案,在Filters文件夹中的"SimpleMemberInitializer(("中找到该语句,然后在解决方案中搜索"SimpleMemberInitializer",没有找到任何其他命中。谁知道它隐藏在[InitializeSimpleMember]属性中。