C# MVC:用户密码重置控制器:电子邮件地址作为用户名的问题

发布于 2024-10-11 05:03:52 字数 6175 浏览 1 评论 0原文

我编写了下面的代码,用于在 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

海未深 2024-10-18 05:03:53

您是否意识到 %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/

朮生 2024-10-18 05:03:53

最好使用 System.Web.HttpContext.Current.Server.UrlDecode(url1) 。
无论 Url 是否经过编码,它都会返回一个原始 url,如“http://localhost:83/ControlPanel/changeUserPassword/[email protected]",您可以从中获取用户名。

string userName = System.Web.HttpContext.Current.Server.UrlDecode(userName);
RouteTable.Routes.MapRoute(
            "AdminPassword", // routename 
            "ControlPanel/changeUserPassword/" + userName,
            new { controller = "ControlPanel", action = "changeUserPassword", username = UrlParameter.Optional }
            ); 

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.

string userName = System.Web.HttpContext.Current.Server.UrlDecode(userName);
RouteTable.Routes.MapRoute(
            "AdminPassword", // routename 
            "ControlPanel/changeUserPassword/" + userName,
            new { controller = "ControlPanel", action = "changeUserPassword", username = UrlParameter.Optional }
            ); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文