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

时间:2011-01-10 10:15:14

标签: c# asp.net-mvc routelink

我编写了以下代码,用于在C#MVC应用程序中重置用户密码(使用aspnet成员资格api),并在示例教程应用程序(MVC Music Store)上成功测试。如果您希望首先阅读问题描述,请跳到最后。

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/example1@gmail.com,但是,

单击RouteLink时会发生什么错误,表示无法找到视图changeUserPassword,并且URL如下所示:

http://localhost:83/ControlPanel/changeUserPassword/example1%40gmail.com - 看看“@”符号是如何弄乱的?

我也通过代码进行了调试,在我的GET changeUserPassword中,用户名正确填充:example1@gmail.com,所以我认为这只是弄乱它的URL?

如果我手动输入URL,则显示changeUserPassword视图,但密码重置功能不起作用。在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

2 个答案:

答案 0 :(得分:0)

你是否意识到%40是@ -symbol的URL编码版本?您网址中的数据没有搞砸,它是URL编码的。这是必需的,因为您的数据包含在URL中具有含义的符号,因此必须以不破坏URL的方式对其进行编码。

您可以在此尝试URL编码/解码: http://meyerweb.com/eric/tools/dencoder/

答案 1 :(得分:0)

最好使用System.Web.HttpContext.Current.Server.UrlDecode(url1)。 无论Url是否编码,它都会返回一个原始网址,例如“http:// localhost:83/ControlPanel/changeUserPassword/example1@gmail.com”,您可以从中获取userName。

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 }
            );