冯 海

一个程序新人菜鸟的日记,希望大家多多关照。QQ:32316131

ASP.NET Identity教程二:(用户管理)

由于我们这里使用的是 ASP.NET Identity 来管理用户,所以 User 数据实体是继承了 IdentityUser 的,我们只需要在派生类中编写需要扩展的属性即可。而在表现层,也就是 Web 应用程序这一层,我们只需要编写 ViewModel 即可,ViewModel 只在视图和控制中使用。最终在提交到服务器时,还是需要转换为数据实体 Model 的。
在“Yidosoft.Identity”项目中添加一个名称为“ViewModels”的文件夹,将所有的ViewModel 都放在该文件夹中。

 

1.  注册用户

注册用户是指将用户的信息添加到数据库中,是有用户在网站上自行完成的

1.1. 编写 AddUserViewModel

在“ViewModels”文件夹中添加一个名称为“AddUserViewModel”的类,然后编写如
下代码:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;

namespace jsdhh2.ViewModels
{
	public class AddUserViewModel
	{

		#region 扩展

		[Display(Name = "用户名")]
		public string UserName { get; set; }


		[Display(Name = "电话(手机/固话)")]
		[Phone]
		public string PhoneNumber { get; set; }
		#endregion
		
		[Required]
		[EmailAddress]
		[Display(Name = "电子邮件")]
		public string Email { get; set; }

		[Required]
		[StringLength(100, ErrorMessage = "{0} 必须至少包含 {2} 个字符。", MinimumLength = 6)]
		[DataType(DataType.Password)]
		[Display(Name = "密码")]
		public string Password { get; set; }

		[DataType(DataType.Password)]
		[Display(Name = "确认密码")]
		[Compare("Password", ErrorMessage = "密码和确认密码不匹配。")]
		public string ConfirmPassword { get; set; }


	}

  在 ViewModel 中,可以使用数据验证和注解来保证数据的正确性。 

1.2. 编写 Add 方法

在 UserController 控制器中添加一个带有 HttpGet 特性的 Add()方法,用于呈现添加用户的表单信息视图。再添加一个带有 HttpPost 特性的 Add()方法,用于提交
用户信息到数据库中。完整的代码如下:

 

[HttpPost]
		[AllowAnonymous]
		[ValidateAntiForgeryToken]
		public async Task<ActionResult> Add(AddUserViewModel addUserModel)
		{
			if (ModelState.IsValid)
			{
				var _creatTime = DateTime.Now;  //注册时间
				var _headerPic = "/Content/noheaderpic.png";   //默认的显示一个头像
				var user = new User { UserName = addUserModel.UserName, Email = addUserModel.Email, PhoneNumber = addUserModel.PhoneNumber, CreateTime =_creatTime, HeaderPic = _headerPic };
				var result = await UserManager.CreateAsync(user, addUserModel.Password);
				if (result.Succeeded)
				{
					//登录
					await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

					// 发送包含此链接的电子邮件
					string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
					var callbackUrl = Url.Action("ConfirmEmail", "User", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
					await UserManager.SendEmailAsync(user.Id, "确认你的帐户", "请通过单击 <a href=\"" + callbackUrl + "\">这里</a>来确认你的帐户");

					//return RedirectToAction("List", "User");
					return RedirectToAction("Index", "Home");
				}
				AddErrors(result);
			}
			return View(addUserModel);
		}

  

 在这里的两个 Add()方法上都添加了 AllowAnonymous 特性,表示可以被匿名访问。ValidateAntiForgeryToken 特性用于阻止 CSRF 攻击。

在这里我们使用了 CreateAsync()异步方法来向数据库添加用户信息,在UserManager 中,定义了许多的异步操作的方法,异步方法都是以 Async 结尾的。

 .3. 编写 Add 视图

在”项目的“Views”“User”中添加一个名称为“Add”的视图,如图

中修改视图名称为“Add”,点击“添加”按钮。如图

 

第一次为空的 MVC 项目添加视图时,VS2015 会自动添加一些其它的文件。如:bootstrap.css、Site.css、Jquery 文件及一些公共视图,还有就是“_Layout.cshtml”
视图的基本样式。
这里使用 Bootstrap 为 Add.cshtml 视图布局页面。在 add.cshtml 视图中编写如下代码: 

@model jsdhh2.ViewModels.AddUserViewModel
@{
	ViewBag.Title = "Add";
}

@using (Html.BeginForm("Add", "User", FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
{
	@Html.AntiForgeryToken()
	<h4>添加用户。</h4>
	<hr />
	@Html.ValidationSummary("", new { @class = "text-danger" })

	<div class="form-group">
		@Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
		<div class="col-md-10">
			@Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
		</div>
	</div>
	<div class="form-group">
		@Html.LabelFor(m => m.PhoneNumber, new { @class = "col-md-2 control-label" })
		<div class="col-md-10">
			@Html.TextBoxFor(m => m.PhoneNumber, new { @class = "form-control" })
		</div>
	</div>



	<div class="form-group">
		@Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" })
		<div class="col-md-10">
			@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })
		</div>
	</div>
	
	<div class="form-group">
		@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
		<div class="col-md-10">
			@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
		</div>
	</div>
	<div class="form-group">
		@Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" })
		<div class="col-md-10">
			@Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" })
		</div>
	</div>
	<div class="form-group">
		<div class="col-md-offset-2 col-md-10">
			<input type="submit" class="btn btn-default" value="保存" />
		</div>
	</div>
}

  

在此视图中使用了Bootstrap的class来布局表单样式。并使用ValidationSummary()方法来执行验证。

4. 测试运行结果

add.cshtml 视图编写完成之后,就可以在 Visual Studio 2015 中按下 F5 键来运行一下。打开 add.cshtml 视图,如图 7-5 所示:中可以按 F5,也可以点击调试按钮。如图 7-6 所示:

此时的图 7-6 使用的是带 HttpGet 特性的 Add()方法返回的视图页面。
现在点击一下图 7-6 的“保存”按钮,浏览器不会刷新,会执行客户端验证。如图

 

凡是在 ViewModel 里使用了[Required]特性,都会在没有输入任何值的情况下出
现 7-7 的非空验证。
在点击“保存”按钮时,注意浏览器的刷新情况,如果没有刷新,则就执行了客户
端验证,如果刷新了,则会执行服务器端验证。
现在在图 7-7 的表单中输入内容。如图 7-8 所示:

输入完成后,点击“保存”按钮。注意:由于这是第一次使用 Entity Framework 提交数据到数据库,所以会检查相关的数据库、表是否已经创建,如果未创建,则
就会立即创建并执行操作。
当点击“保存”按钮后,就会执行带 HttpPost 特性的 Add()方法中的代码。图 7-8 的表单数据保存成功后会转到首页(Home/Index),这也是默认路由指定的
默认路径。如图 7-9 所示:

但是也表明了我们的执行操作成功了。打开数据库查看一下,如图 7-10 所示:

在图 7-10 中可以看到,“YDIdentityDb”数据库已经创建成功了,并且还为 ASP.NETIdentity 创建相应的表结构。

与用户相关的信息是存在“AspNetUsers”表中的,打开该表可以看到我们新添加的用户信息。这也证明我们在上面所做的操作已经执行成功了。

从这些操作中可以看到,我们使用了 Entity Framework 操作持久化数据非常方便,不仅不需要编写 SQL 语句,就连数据库和表结构都不需要我们创建。另外在ASP.NET Identity 中,对用户属性的扩展是那么的方便,这在 ASP.NET Membership中,这么扩展用户属性是做不到的。

2.   用户列表

管理用户都是从用户列表开始的,在用户列表中可以查看用户信息、编辑用户信息和删除用户信息。当然也可以放个添加用户的链接用于新增用户。用户列表就
是管理用户的入口。
在用户列表视图中,我们不使用 ViewModel,直接使用 User 类即可,因为UserManager 提供了获取所有用户的方法,直接调用即可。

.2.1. 编写 List 方法

在 UserController 控制器中添加一个带有 HttpGet 特性的 List()方法,用于以列表的形式显示所有的用户。完整的代码如下:

 

		[HttpGet]
		public ActionResult List()
		{
			var users = UserManager.Users.ToList();
			return View(users);
		}
 		  

2.2. 编写 List 视图

项目的“Views”“User”文件夹中添加一个名称为“List”的视图。

@model IEnumerable<jsdhh2.Models.User>
@{
	ViewBag.Title = "List";
}


<div class="wrapper wrapper-content">
	<div class="ibox float-e-margins">
		<div class="ibox-title">
			<h2>用户管理</h2>
			<div class="ibox-tools">
				<a class="collapse-link">
					<i class="fa fa-chevron-up"></i>
				</a>
			</div>
		</div>

		<div class="ibox-content">
			<div class="form-group">
				<a class="btn btn-primary" href="/User/Add">添加</a>
				 <button id="btnEdit" type="button" class="btn btn-info " onclick="editModel()"><i class="fa fa-pencil"></i> 编辑</button>
				<button id="btnDel" type="button" class="btn btn-danger " onclick="delData()">
					<i class="fa fa-remove"></i>  <span class="bold">删除</span>
				</button>
				<button id="btnSetRole" type="button" class="btn btn-info "><i class="fa fa-user"></i> 角色授权</button>
				<button id="btnResetPwd" class="btn btn-warning"><i class="fa fa-undo"></i> 重置密码</button>
			</div>
			<div class="form-group">
				<div class="input-group">
					<input id="txtSearchKey" type="text" class="input form-control" placeholder="搜索关键字" />
					<span class="input-group-btn">
						<button id="btnSearch" class="btn btn btn-primary" type="button"> <i class="fa fa-search"></i> 搜索</button>
					</span>
				</div>
			</div>

			<div class="jqGrid_wrapper">
				<table id="table_list"></table>
				<div id="pager_list"></div>
			</div>
		</div>
	</div>
</div>

 
<table class="table">
	<thead>
		<tr>
			<th>用户名</th>
			<th>电子邮件</th>
			<th>QQ号码</th>
			<th>微信号码</th>
		</tr>
	</thead>
	<tbody>
		@foreach (var user in Model)
			{
			<tr>
				<td>@Html.DisplayFor(m => user.UserName)</td>
				<td>@Html.DisplayFor(m => user.Email)</td>
				<td>@Html.DisplayFor(m => user.QQ)</td>
				<td>@Html.DisplayFor(m => user.PhoneNumber)</td>
				<td>@Html.DisplayFor(m => user.CreateTime) </td>
				<td>
					@Html.ActionLink("编辑", "Edit", new { id = user.Id },new { @class= "btn btn-info" })
					@Html.ActionLink("删除", "Del", new { id = user.Id }, new { @class = "btn btn-danger" })
				</td>
			</tr>
			}
	</tbody>
</table>

 

  

 

  显示效果为

 

 

这里使用了表格 table 以列表的形式的显示用户基本信息,使用了 Bootstrap 中的class=”table”来布局样式。在<table>标记上面还添加了一个链接,用于转到添加用户的页面:

<a class="btn btn-primary" href="/User/Add">添加</a>

这样可以在用户列表中直接点击“添加用户”链接转到添加用户的页面。那么此时,我们就可以在“Add()”方法中,将添加用户成功后转到的页面修改为 List 页面。打开“UserController”,修改带有 HttpPost 的 Add()方法。如下代码:

   

 [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public async Task<ActionResult> Add(AddUserViewModel addUserModel)
        {
            if (ModelState.IsValid)
            {
                var user = new User { UserName = addUserModel.Email, Email = addUserModel.Email, QQNumber = addUserModel.QQNumber, WechatNumber = addUserModel.WechatNumber };
                var result = await UserManager.CreateAsync(user, addUserModel.Password);
                if (result.Succeeded)
                {
                    //登录
                    await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);

                    // 发送包含此链接的电子邮件
                    string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                    var callbackUrl = Url.Action("ConfirmEmail", "User", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
                    await UserManager.SendEmailAsync(user.Id, "确认你的帐户", "请通过单击 <a href=\"" + callbackUrl + "\">这里</a>来确认你的帐户");

                    return RedirectToAction("List", "User");
                    //eturn RedirectToAction("Index", "Home");
                }
                AddErrors(result);
            }
            return View(addUserModel);

  

现在新建一个用户,自动就跑到所有用户列表了。

3.增加详细页面显示

先在List视图中增加详细信息按钮

	<td>
					@Html.ActionLink("详情", "DetailsList", new { id = user.Id }, new { @class = "btn btn-info" })
					@Html.ActionLink("编辑", "Edit", new { id = user.Id },new { @class= "btn btn-info" })
					@Html.ActionLink("删除", "Del", new { id = user.Id }, new { @class = "btn btn-danger" })
				</td>

  

在UserControoer中增加DetailsList方法

[HttpGet]
public ActionResult DetailsList(string id)
{
if (string.IsNullOrWhiteSpace(id))
{
return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest);
}
User user = UserManager.FindById(id);

return View(user);
}

 

  然后增加一个DetailsList视图

@model  jsdhh2.Models.User 
@{
	ViewBag.Title = "List";
}


<div class="wrapper wrapper-content">
	<div class="ibox float-e-margins">
		<div class="ibox-title">
			<h2>详细信息</h2>
			<div class="ibox-tools">
				<a class="collapse-link">
					<i class="fa fa-chevron-up"></i>
				</a>
			</div>
		</div>

		<div class="ibox-content">
			<div class="form-group">
				<a class="btn btn-primary" href="/User/List">返回</a>
				
			</div>

		 
		</div>
	</div>
</div>
<div>

	<hr />
 

	<dl class="dl-horizontal">
		<dt>
			 
		</dt>
		<dd>
			<img src="@Model.HeaderPic" width="80" height="80" />
		</dd>
		    <dt>
			@Html.DisplayNameFor(model => model.UserName)
			</dt><dd>
					@Html.DisplayFor(model => model.UserName)
			</dd>
				<dt>
				@Html.DisplayNameFor(model => model.RealName)
				</dt><dd>
					@Html.DisplayFor(model => model.RealName)
				</dd>
				<dt>
				@Html.DisplayNameFor(model => model.Email)
				</dt><dd>
					@Html.DisplayFor(model => model.Email)
				</dd>
				<dt>
				@Html.DisplayNameFor(model => model.QQ)
				</dt><dd>
					@Html.DisplayFor(model => model.QQ)
				</dd>
				<dt>
				@Html.DisplayNameFor(model => model.PhoneNumber)
				</dt><dd>
					@Html.DisplayFor(model => model.PhoneNumber)
				</dd>

				<dt>
				@Html.DisplayNameFor(model => model.Address)
				</dt><dd>
					@Html.DisplayFor(model => model.Address)
				</dd>
				<dt>
				@Html.DisplayNameFor(model => model.Gender)
				</dt><dd>
					@Html.DisplayFor(model => model.Gender)
				</dd>
				<dt>
				@Html.DisplayNameFor(model => model.SpouseId)
				</dt><dd>
					@Html.DisplayFor(model => model.SpouseId)
				</dd>
				<dt>
				@Html.DisplayNameFor(model => model.Address)
				</dt><dd>
					@Html.DisplayFor(model => model.Address)
				</dd>
				<dt>
				@Html.DisplayNameFor(model => model.DepartmentId)
				</dt><dd>
					@Html.DisplayFor(model => model.DepartmentId)
				</dd>
		 
				<dt>
				@Html.DisplayNameFor(model => model.BirthDate)
				</dt><dd>
					@Html.DisplayFor(model => model.BirthDate)
				</dd>
			 
				<dt>
				@Html.DisplayNameFor(model => model.TheHour)
				</dt><dd>
					@Html.DisplayFor(model => model.TheHour)
				</dd>
		<dt>
			@Html.DisplayNameFor(model => model.DetailedTime)
		</dt>
		<dd>
			@Html.DisplayFor(model => model.DetailedTime)
		</dd>





</div>

  显示效果为

 

 

4.

 

posted @ 2017-05-13 17:45  秋天来了哟  阅读(549)  评论(0编辑  收藏  举报
认识就是缘份,愿天下人都快乐!
QQ: 32316131
Email: 32316131@qq.com