C# MVC:用户密码重置控制器:电子邮件地址作为用户名的问题
我编写了下面的代码,用于在 C# MVC 应用程序中重置用户密码(正在使用 aspnet 会员 api),并在示例教程应用程序(MVC 音乐商店)上成功进行了测试。如果您想先阅读问题描述,请跳到最后。
InactiveUsers 视图(部分视图)
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.Web.Security.MembershipUserCollection>" %>
<table class="normal" style="width: 100%; background-color: White;">
<tr>
<th>User Name</th>
<th>Last Activity date</th>
<th>Locked Out</th>
</tr>
<%foreach (MembershipUser user in Model){ %>
<tr>
<td><%: Html.RouteLink(user.UserName, "AdminPassword", new { username = user.UserName }) %></td>
<td><%: user.LastActivityDate %></td>
<td><%: user.IsLockedOut %></td>
</tr>
<% }%>
</table>
InactiveUsers 控制器
public ActionResult InactiveUsers()
{
var users = Membership.GetAllUsers();
return View(users);
}
changeUserPassword GET 和 POST 控制器
public ActionResult changeUserPassword(string username)
{
ViewData["username"] = username;
return View();
}
[HttpPost]
public ActionResult changeUserPassword(ChangePasswordModel model, FormCollection values)
{
string username = values["username"];
string password = values["password"];
string confirmPassword = values["confirmPassword"];
MembershipUser mu = Membership.GetUser(username);
if (password == confirmPassword)
{
if (mu.ChangePassword(mu.ResetPassword(), password))
{
return RedirectToAction("Index", "ControlPanel");
}
else
{
ModelState.AddModelError("", "The current password does not meet requirements");
}
}
return View();
}
我还修改了 Global.asax.cs 文件以适应我的路线InactiveUsers 部分:
// Added in 10/01/11
RouteTable.Routes.MapRoute(
"AdminPassword", // routename
"ControlPanel/changeUserPassword/{username}",
new { controller = "ControlPanel", action = "changeUserPassword", username = UrlParameter.Optional }
);
// END
现在,当我在 MVC 音乐商店上进行测试时,我的所有用户名都只是单词,例如管理员、用户等。但是现在我将此代码应用于我的工作场所的情况,但效果并不完全一样计划。我工作场所使用的用户名实际上是电子邮件地址,我认为这就是导致问题的原因。
当我单击部分 InactiveUsers 视图中的 RouteLink 时,它应该将我带到重置密码页面,其 URL 如下所示:
http://localhost:83/ControlPanel/changeUserPassword/[电子邮件受保护],但是,
当我单击 RouteLink 时发生的情况是抛出一个错误,指出找不到视图 changeUserPassword,并且 URL 如下所示:
http://localhost:83/ControlPanel/changeUserPassword/example1%40gmail.com - 看看“@”符号是如何混乱的?
我还通过代码进行了调试,并且在我的 GET changeUserPassword 中,用户名正确填充: [email protected],所以我认为只是 URL 搞砸了?
如果我手动输入 URL,则会显示更改用户密码视图,但密码重置功能不起作用。 if (mu.ChangePassword(mu.ResetPassword(), password)) 行会引发“对象引用未设置到对象实例”异常。
我想如果我能解决第一个问题(URL“@”符号问题),它可能会帮助我解决第二个问题。
如有任何帮助,我们将不胜感激:)
堆栈跟踪 - 按要求
源错误:
在执行当前 Web 请求期间生成未处理的异常。有关异常来源和位置的信息可以使用下面的异常堆栈跟踪来识别。
堆栈跟踪:
[InvalidOperationException: The view 'changeUserPassword' or its master was not found. The following locations were searched:
~/Views/ControlPanel/changeUserPassword.aspx
~/Views/ControlPanel/changeUserPassword.ascx
~/Views/Shared/changeUserPassword.aspx
~/Views/Shared/changeUserPassword.ascx]
System.Web.Mvc.ViewResult.FindView(ControllerContext context) +495
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +208
System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +39
System.Web.Mvc.<>c__DisplayClass14.<InvokeActionResultWithFilters>b__11() +60
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +391
System.Web.Mvc.<>c__DisplayClass16.<InvokeActionResultWithFilters>b__13() +61
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +285
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +830
System.Web.Mvc.Controller.ExecuteCore() +136
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +111
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +39
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__4() +65
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +44
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +42
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +141
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +54
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +52
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8841105
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
I have written the code below for resetting users passwords (am using the aspnet membership api) in an C# MVC application, and tested successfully on a sample tutorial application (MVC Music Store). Skip to the end if you wish to read problem description first.
InactiveUsers View (Partial View)
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.Web.Security.MembershipUserCollection>" %>
<table class="normal" style="width: 100%; background-color: White;">
<tr>
<th>User Name</th>
<th>Last Activity date</th>
<th>Locked Out</th>
</tr>
<%foreach (MembershipUser user in Model){ %>
<tr>
<td><%: Html.RouteLink(user.UserName, "AdminPassword", new { username = user.UserName }) %></td>
<td><%: user.LastActivityDate %></td>
<td><%: user.IsLockedOut %></td>
</tr>
<% }%>
</table>
InactiveUsers Controller
public ActionResult InactiveUsers()
{
var users = Membership.GetAllUsers();
return View(users);
}
changeUserPassword GET and POST Controllers
public ActionResult changeUserPassword(string username)
{
ViewData["username"] = username;
return View();
}
[HttpPost]
public ActionResult changeUserPassword(ChangePasswordModel model, FormCollection values)
{
string username = values["username"];
string password = values["password"];
string confirmPassword = values["confirmPassword"];
MembershipUser mu = Membership.GetUser(username);
if (password == confirmPassword)
{
if (mu.ChangePassword(mu.ResetPassword(), password))
{
return RedirectToAction("Index", "ControlPanel");
}
else
{
ModelState.AddModelError("", "The current password does not meet requirements");
}
}
return View();
}
I also modified the Global.asax.cs file to cater for my route in the InactiveUsers partial:
// Added in 10/01/11
RouteTable.Routes.MapRoute(
"AdminPassword", // routename
"ControlPanel/changeUserPassword/{username}",
new { controller = "ControlPanel", action = "changeUserPassword", username = UrlParameter.Optional }
);
// END
Now, when I tested on the MVC Music Store, all of my usernames were just words, e.g. Administrator, User, etc. However now I am applying this code to a situation in my workplace and it's not working out quite as planned. The usernames used in my workplace are actually email addresses and I think this is what is causing the problem.
When I click on the RouteLink in the partial InactiveUsers view, it should bring me to the reset password page with a url that looks like this:
http://localhost:83/ControlPanel/changeUserPassword/[email protected], HOWEVER,
what happens when I click on the RouteLink is an error is thrown to say that the view changeUserPassword cannot be found, and the URL looks like this:
http://localhost:83/ControlPanel/changeUserPassword/example1%40gmail.com - See how the '@' symbol gets messed up?
I've also debugged through the code, and in my GET changeUserPassword, the username is populating correctly: [email protected], so I'm thinking it's just the URL that's messing it up?
If I type in the URL manually, the changeUserPassword view displays, however the password reset function does not work. An 'Object reference not set to an instance of an object' exception is thrown at the if (mu.ChangePassword(mu.ResetPassword(), password)) line.
I think if I could solve the first issue (URL '@' symbol problem) it might help me along with my second issue.
Any help would be appreciated :)
Stack Trace - as requested
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: The view 'changeUserPassword' or its master was not found. The following locations were searched:
~/Views/ControlPanel/changeUserPassword.aspx
~/Views/ControlPanel/changeUserPassword.ascx
~/Views/Shared/changeUserPassword.aspx
~/Views/Shared/changeUserPassword.ascx]
System.Web.Mvc.ViewResult.FindView(ControllerContext context) +495
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +208
System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +39
System.Web.Mvc.<>c__DisplayClass14.<InvokeActionResultWithFilters>b__11() +60
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +391
System.Web.Mvc.<>c__DisplayClass16.<InvokeActionResultWithFilters>b__13() +61
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +285
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +830
System.Web.Mvc.Controller.ExecuteCore() +136
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +111
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +39
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__4() +65
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +44
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +42
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +141
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +54
System.Web.Mvc.Async.AsyncResultWrapper.End(IAsyncResult asyncResult, Object tag) +40
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +52
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +38
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8841105
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否意识到 %40 是 @ 符号的 URL 编码版本? URL 中的数据并没有混乱,而是经过 URL 编码的。这是必需的,因为您的数据包含在 URL 中具有含义的符号,因此必须以不会破坏 URL 的方式对其进行编码。
你可以在这里尝试 URL 编码/解码:
http://meyerweb.com/eric/tools/dencoder/
Do you realize that %40 is the URL encoded version of the @-symbol? The data in your URL is not messed up, it's URL encoded. This is needed because your data contains a symbol that has a meaning in URL's, so it must be encoded in a way that doesn't break the URL.
You can try URL encoding/decoding it out here:
http://meyerweb.com/eric/tools/dencoder/
最好使用 System.Web.HttpContext.Current.Server.UrlDecode(url1) 。
无论 Url 是否经过编码,它都会返回一个原始 url,如“http://localhost:83/ControlPanel/changeUserPassword/[email protected]",您可以从中获取用户名。
Better to use
System.Web.HttpContext.Current.Server.UrlDecode(url1)
.whether the Url is encoded or not it returns a raw url like "http://localhost:83/ControlPanel/changeUserPassword/[email protected]" and you can get userName from it.