在上一篇博客中实现了用户的注销和登录,其实代码里落了点东西,就是用户登录要更新最后一次登录时间和登录IP,这次补上。今天做修改资料和修改密码,TryUpdateModel是新用到的东西。
目录:
ASP.NET MVC5 网站开发实践 - 概述
ASP.NET MVC5 网站开发实践(一) - 项目框架
ASP.NET MVC5 网站开发实践(一) - 框架(续) 模型、数据存储、业务逻辑
ASP.NET MVC5 网站开发实践(二) - 用户部分(1)用户注册
ASP.NET MVC5 网站开发实践(二) - 用户部分(2)用户登录、注销
现完善昨天的登录代码:
一、用户导航菜单
这个就是侧栏的导航,以后所有控制器中action名都为Menu。目标效果如下:
先UserController添加Menu action。直接返回分布视图。右键添加视图
<div class="panel panel-primary"><div class="panel-heading"><h3>我的资料</h3></div><div class="panel-body"><ul class="nav nav-pills nav-stacked"><li> <a href="@Url.Action("Details")"><span class="glyphicon glyphicon-user"> 修改资料</span></a></li><li> <a href="@Url.Action("ChangePassword")"><span class="glyphicon glyphicon-log-out"> 修改密码</span></a></li><li> <a href="@Url.Action("Logout")"><span class="glyphicon glyphicon-log-out"> 退出登录</span></a></li></ul></div> </div>
二、显示用户资料
再在User控制器里添加显示用户资料的action Details。以后约定所有显示详细资料的动作名都为Details。在控制器中返回当前用户的资料
/// <summary>/// 显示资料/// </summary>/// <returns></returns>public ActionResult Details(){return View(userService.Find(User.Identity.Name));}
右键添加视图
@model Ninesky.Models.User@{ViewBag.Title = "我的资料"; }<div class="row"><div class="col-md-3 col-sm-4">@Html.Action("Menu")</div><div class="col-md-9 col-sm-8"><ol class="breadcrumb"><li><span class="glyphicon glyphicon-home"><a> 会员中心</a></span></li><li><a> 个人中心</a></li><li>修改资料</li></ol>@using (Html.BeginForm("Modify","User")){@Html.AntiForgeryToken()<div class="form-horizontal"><h4>用户资料</h4><hr />@Html.ValidationSummary(true)@Html.HiddenFor(model => model.UserID)<div class="form-group">@Html.LabelFor(model => model.UserName, new { @class = "control-label col-md-2" })<div class="col-md-10">@Html.DisplayFor(model => model.UserName)</div></div><div class="form-group">@Html.LabelFor(model => model.DisplayName, new { @class = "control-label col-md-2" })<div class="col-md-10">@Html.EditorFor(model => model.DisplayName)@Html.ValidationMessageFor(model => model.DisplayName)</div></div><div class="form-group"><label class = "control-label col-md-2">用户组</label><div class="col-md-10">@foreach (var _relation in Model.UserRoleRelations){ <span>@_relation.Role.Name</span><br />}</div></div><div class="form-group">@Html.LabelFor(model => model.Email, new { @class = "control-label col-md-2" })<div class="col-md-10">@Html.EditorFor(model => model.Email)@Html.ValidationMessageFor(model => model.Email)</div></div><div class="form-group"><div class="col-md-offset-2 col-md-10"><input type="submit" value="修改" class="btn btn-default" /></div></div></div>}</div> </div> @section Scripts {@Scripts.Render("~/bundles/jqueryval") }
三、修改用户资料
显示用户资料后点击修改直接向后台提交数据,这里把接受并更新数据库的动作名也是Details。在这个方法里不能直接用User做方法参数,因为我只想跟新显示名和邮箱,我如果设置User类型的参数,如果用户向服务器提交的参数中含有UserName,可能用户名都会改掉,这里使用TryUpdateModel来部分更新模型。
/// <summary>/// 修改资料/// </summary>/// <returns></returns> [ValidateAntiForgeryToken][HttpPost]public ActionResult Modify(){var _user = userService.Find(User.Identity.Name);if (_user == null) ModelState.AddModelError("", "用户不存在");else{if (TryUpdateModel(_user, new string[] { "DisplayName", "Email" })){if (ModelState.IsValid){if (userService.Update(_user)) ModelState.AddModelError("", "修改成功!");else ModelState.AddModelError("", "无需要修改的资料");}}else ModelState.AddModelError("", "更新模型数据失败");}return View("Details", _user);}
四、修改密码
先建立一个视图模型ChangePasswordViewModel
using System.ComponentModel.DataAnnotations;namespace Ninesky.Web.Areas.Member.Models {/// <summary>/// 修改密码视图模型/// <remarks>创建:2014.02.19</remarks>/// </summary>public class ChangePasswordViewModel{/// <summary>/// 原密码/// </summary>[Required(ErrorMessage = "必填")][Display(Name = "密码")][StringLength(20, MinimumLength = 6, ErrorMessage = "{2}到{1}个字符")][DataType(DataType.Password)]public string OriginalPassword { get; set; }/// <summary>/// 新密码/// </summary>[Required(ErrorMessage = "必填")][Display(Name = "新密码")][StringLength(20, MinimumLength = 6, ErrorMessage = "{2}到{1}个字符")][DataType(DataType.Password)]public string Password { get; set; }/// <summary>/// 确认密码/// </summary>[Required(ErrorMessage = "必填")][Compare("Password", ErrorMessage = "两次输入的密码不一致")][Display(Name = "确认密码")][DataType(DataType.Password)]public string ConfirmPassword { get; set; }} }
然后在UserController中添加动作public ActionResult ChangePassword() 直接返一个视图。右键添加ChangePasswordViewModel类型的视图
@model Ninesky.Web.Areas.Member.Models.ChangePasswordViewModel@{ViewBag.Title = "修改密码"; } <div class="row"><div class="col-md-3 col-sm-4">@Html.Action("Menu")</div><div class="col-md-9 col-sm-8"><ol class="breadcrumb"><li><span class="glyphicon glyphicon-home"><a> 会员中心</a></span></li><li><a> 个人中心</a></li><li>修改密码</li></ol>@using (Html.BeginForm()){@Html.AntiForgeryToken()<div class="form-horizontal"><h4>修改密码</h4><hr />@Html.ValidationSummary(true)<div class="form-group">@Html.LabelFor(model => model.OriginalPassword, new { @class = "control-label col-md-2" })<div class="col-md-10">@Html.EditorFor(model => model.OriginalPassword)@Html.ValidationMessageFor(model => model.OriginalPassword)</div></div><div class="form-group">@Html.LabelFor(model => model.Password, new { @class = "control-label col-md-2" })<div class="col-md-10">@Html.EditorFor(model => model.Password)@Html.ValidationMessageFor(model => model.Password)</div></div><div class="form-group">@Html.LabelFor(model => model.ConfirmPassword, new { @class = "control-label col-md-2" })<div class="col-md-10">@Html.EditorFor(model => model.ConfirmPassword)@Html.ValidationMessageFor(model => model.ConfirmPassword)</div></div><div class="form-group"><div class="col-md-offset-2 col-md-10"><input type="submit" value="修改" class="btn btn-default" /></div></div></div>}@section Scripts {@Scripts.Render("~/bundles/jqueryval")}</div> </div>
在添加一个接受处理动作,代码也很简单
[ValidateAntiForgeryToken][HttpPost]public ActionResult ChangePassword(ChangePasswordViewModel passwordViewModel){if(ModelState.IsValid){var _user = userService.Find(User.Identity.Name);if (_user.Password == Common.Security.Sha256(passwordViewModel.OriginalPassword)){_user.Password = Common.Security.Sha256(passwordViewModel.Password);if (userService.Update(_user)) ModelState.AddModelError("", "修改密码成功");else ModelState.AddModelError("", "修改密码失败");}else ModelState.AddModelError("", "原密码错误");}return View(passwordViewModel);}
五、在首页显示登录、注册链接
在Web的Shared文件件添加LoginPartial.cshtml视图文件,在用户未登录时显示登录和注册链接,登录后显示用户名。
@using Microsoft.AspNet.Identity @if (Request.IsAuthenticated) {using (Html.BeginForm("Logout", "User", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })){@Html.AntiForgeryToken()<ul class="nav navbar-nav navbar-right"><li>@Html.ActionLink("你好 " + User.Identity.GetUserName() + "!", "Manage", "Account", routeValues: null, htmlAttributes: new { title = "管理" })</li><li><a href="javascript:document.getElementById('logoutForm').submit()">注销</a></li></ul>} } else {<ul class="nav navbar-nav navbar-right"><li>@Html.ActionLink("注册", "Register", "User", routeValues: new { Area = "Member" }, htmlAttributes: new { id = "registerLink" })</li><li>@Html.ActionLink("登录", "Login", "User", routeValues: new {Area="Member"}, htmlAttributes: new { id = "loginLink" })</li></ul> }
效果如下:
登录前
登陆后
ok.现在我们可以给给member区域的UserController控制器和Homecontroller加上[Authorize]特性。并为Usercontroller的注册 登录 验证码action 加上[AllowAnonymous]特性。
六、总结
修改资料部分用到了部分更新模型方法TryUpdateModel。
到此member区域的用户部分暂时结束。下次开始内容部分。
===================
代码 Ninesky二.3.rar http://pan.baidu.com/s/1pJ6TBmV