冯 海

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

ASP.NET Identity教程一:(配置 ASP.NET Identity)-从这往后是我系列教程(mvc5+ef+adminlte)的开始。请顺着看。

ASP.NET Identity 提供了许多的 API接口供使用,但是都是以继承的方式来实现的。因此,在使用某个功能之前,需要继承该功能的基类。

1.  继承 IdentityUser

用户是 ASP.NET Identity 其它操作的基础,所以在使用 ASP.NET Identity 之前,首先要创建 User 类。在 ASP.NET Identity 中,用户的基本信息是很容易扩展的,也就是可以添加我们自己的用户属性,如 QQ、微信、爱好、职业等等。

IdentityUser类是定义在Microsoft.AspNet.Identity.EntityFramework名称空间下的:

namespace Microsoft.AspNet.Identity.EntityFramework
{
public class IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole,
IdentityUserClaim>, IUser, IUser<string>
{
public IdentityUser();
public IdentityUser(string userName);
}
}

 

从定义上看,IdentityUser 类是继承了泛型的 IdentityUser<>、IUser 和泛型的 IUser<>接口。而 IUser 接口又是继承了 IUser<string>泛型接口。如下代码:

namespace Microsoft.AspNet.Identity
{
//
// 摘要:
// Minimal interface for a user with id and username
//
// 类型参数:
ASP.NET Identity 的配置及在 MVC5 框架中的应用详细开发实战培训教程
22 / 136
一都 (Yidosoft.cn) 软件
// TKey:
public interface IUser<out TKey>
{
//
// 摘要:
// Unique key for the user
TKey Id { get; }
//
// 摘要:
// Unique username
string UserName { get; set; }
}
}

  

在泛型的 IUser 接口中,定义了 Id 和 UserName 属性,并且是唯一值。而更多的用户属性是定义在泛型的 IdentityUser 基类中的。如下代码:

namespace Microsoft.AspNet.Identity.EntityFramework
{
public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey>
where TLogin : IdentityUserLogin<TKey>
where TRole : IdentityUserRole<TKey>
where TClaim : IdentityUserClaim<TKey>
{
public IdentityUser();
public virtual int AccessFailedCount { get; set; }
public virtual ICollection<TClaim> Claims { get; }
public virtual string Email { get; set; }
public virtual bool EmailConfirmed { get; set; }
public virtual TKey Id { get; set; }
public virtual bool LockoutEnabled { get; set; }
public virtual DateTime? LockoutEndDateUtc { get; set; }
public virtual ICollection<TLogin> Logins { get; }
public virtual string PasswordHash { get; set; }
public virtual string PhoneNumber { get; set; }
public virtual bool PhoneNumberConfirmed { get; set; }
public virtual ICollection<TRole> Roles { get; }
public virtual string SecurityStamp { get; set; }
public virtual bool TwoFactorEnabled { get; set; }
public virtual string UserName { get; set; }
}
}

  

在这里可以看到 User 的所有自带的相关属性,另外,还可以看到 IdentityUser 还受到了 IdentityUserLogin、IdentityUserRole、IdentityUserClaim 的约束。

现在我们在“Yidosoft.Identity”项目的“Models”文件夹下添加一个名称为“User”的类。然后继承 IdentityUser 基类。代码如下:

 

using Microsoft.AspNet.Identity.EntityFramework;
namespace Yidosoft.Identity.Models
{
public class User : IdentityUser
{
}
}

 

而我们自定义的扩展的用户属性,只需要在 User 类中编写即可。如下代码,我们添加用户的 QQ 和微信号属性: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using System.Security.Claims;


namespace jsdhh2.Models
{
	public class User: IdentityUser
	{
		public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager)
		{
			// 请注意,authenticationType 必须与 CookieAuthenticationOptions.AuthenticationType 中定义的相应项匹配
			var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
			// 在此处添加自定义用户声明
			return userIdentity;
		}
		#region 添加字段
		public virtual string WX { get; set; }
		public virtual string QQ { get; set; }
		public virtual DateTime CreateTime { get; set; }
		public virtual   int? DepartmentId { get; set; }
		public virtual   string Address { get; set; }

		public virtual   int? Gender { get; set; }

		public virtual DateTime? BirthDate { get; set; }
		public virtual string TheHour { get; set; }
		public virtual DateTime? DetailedTime { get; set; }

		public virtual string RealName { get; set; }

		public virtual int? SpouseId { get; set; }
		public virtual string HeaderPic { get; set; }


		#endregion



	}
}

  

 

 

这样在使用 Entity Framework 的 Code First 特性时,就会将这些自定义的属性映射为相应的字段。

2.  继承 IdentityDbContext<User>

ASP.NET Identity 是使用 Entity Framework 来操作并与数据库交互的。所以需要创建数据上下文类,并且该类必须是继承了 IdentityDbContext<T>类的,并且泛型类中的类型参数 T 必须是在 4.1 节中创建的 User 类,User 类必须是继承了IdentityUser 类的。它们之间都存在约束,可见这也呈现的编程的严谨性。
  这里也将数据上下文类创建在“Models”文件夹中,当然如果你的项目具有分层结构,则可以放在合适的层中,这里重点是讲解 ASP.NET Identity,不存在分层。

在项目中新建一个文件夹DAL。在DAL中新建一个名称为“IdentityDbContext”的类文件,并继承 IdentityDbContext<User>类。IdentityDbContext<T>也是定义在:Microsoft.AspNet.Identity.EntityFramework 名称空间下的。如下代码:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using jsdhh2.Models;
using Microsoft.AspNet.Identity.EntityFramework;

namespace jsdhh2.DAL
{
	public class IdentityDbContext : IdentityDbContext<User>
	{
	}
}

  

  

然后在构造函数中传入数据库连接字符串或 web.config 配置文件中配置的连接字符串的名称。建议使用连接字符串的名称,这样以后变更了数据库连接字符串,直接在 web.config 文件中修改即可。最终的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using jsdhh2.Models;
using Microsoft.AspNet.Identity.EntityFramework;

namespace jsdhh2.DAL
{
	public class IdentityDbContext : IdentityDbContext<User>
	{
		public IdentityDbContext() : base("MyOaContent", throwIfV1Schema: false)
		{
		}
		/// <summary>
		/// 实例化一个IdentityDbContext。
		/// </summary>
		/// <returns></returns>
		public static IdentityDbContext Create()
		{
			return new IdentityDbContext();
		}
		
	}

}

在此代码中,IdentityDbContext 构造函数使用基类的构造函数传入参数。基类构造函数代码如下:

  

namespace Microsoft.AspNet.Identity.EntityFramework
{
public class IdentityDbContext<TUser> : IdentityDbContext<TUser, IdentityRole, string,
IdentityUserLogin, IdentityUserRole, IdentityUserClaim> where TUser : IdentityUser
{
public IdentityDbContext();
public IdentityDbContext(string nameOrConnectionString);
public IdentityDbContext(DbCompiledModel model);
public IdentityDbContext(string nameOrConnectionString, bool throwIfV1Schema);
public IdentityDbContext(DbConnection existingConnection, bool
contextOwnsConnection);
public IdentityDbContext(string nameOrConnectionString, DbCompiledModel model);
public IdentityDbContext(DbConnection existingConnection, DbCompiledModel model,
bool contextOwnsConnection);
}
}

这里使用的是第 4 个构造函数,包含两个参数:一个是数据库连接字符串的名称或连接字符串,这里使用 web.config 配置文件中的名称 YDDbConnection。另一个是布尔类型 throwIfV1Schema 参数,表示如果模式匹配 Identity 1.0.0,是否将抛出一个异常,这里设置为 false。另外,还有一个静态方法 Create(),用来实例化 Identity DbContext 数据上下文。

  3. 配置数据库连接字符串

打开“Yidosoft.Identity”项目中的 web.config 文件,在<configuration>节点添加<connectionStrings>节点。如下代码:

<configuration>
<configSections>
<section name="entityFramework"
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework,
Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</configSections>
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
<connectionStrings>
<add name="MyOaContent" connectionString="Data Source=192.168.1.206;Initial Catalog=YDIdentityDb;uid=sa;pwd=12345678" providerName="System.Data.SqlClient"/> </connectionStrings> </configuration>

  

注意:这里的 name 属性的值一定要与在 IdentityDbContext 构造函数中配置的名称完全一致。并且数据库的名称可以任意起,不必事先在数据库中创建好,EntityFramework 会帮我们创建。

4.  继承 UserManager<User>

UserManager<T>泛型类是一个用来管理用户的类,T 就是我们在 4.1 节中创建的User 类,并且 User 类必须继承 IdentityUser 类。同样我们也需要创建一个类并继承该基类。

  

在“Yidosoft.Identity”项目的“App_Start”文件夹中创建一个名称为“IdentityConfig”的类文件,并将自动创建的“IdentityConfig”类删除掉,名称空间修改为:Yidosoft.Identity。“IdentityConfig.cs”用来配置与 Identity 相关的操作。然后添加一个名称为“UserManager”的类,并继承 UserManager<User>基类。代码如下:(备注:要注意把ROLES的先注释“) 

 

实际上用户的操作都是定义在 IUserStore<User>接口中的,所以必须在UserManager 构造函数中将 IUserStore<User>作为参数传入。最终的代码修改如

 

using jsdhh2.Models;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.AspNet.Identity.EntityFramework;
using System.Threading.Tasks;
using Microsoft.Owin.Security;
using System.Security.Claims;


namespace jsdhh2
{

	public class EmailService : IIdentityMessageService
	{
		public Task SendAsync(IdentityMessage message)
		{
			//编写发送邮件的代码
			//Common.SendMail("smtp.126.com", 25, "lbj$4561200", "yidosoft@126.com", message.Destination, message.Subject, message.Body);
			return Task.FromResult(0);
		}
	}

	public class SmsService : IIdentityMessageService
	{
		public Task SendAsync(IdentityMessage message)
		{
			// 在此处插入 SMS 服务可发送短信。
			return Task.FromResult(0);
		}
	}

	/// <summary>
	/// 配置用户管理器
	/// </summary>
	public class UserManager : UserManager<User>
	{
		public UserManager(IUserStore<User> store) : base(store) { }

		public static UserManager Create(IdentityFactoryOptions<UserManager> options, IOwinContext context)
		{
			var manager = new UserManager(new UserStore<User>(context.Get<DAL.IdentityDbContext>()));

			manager.EmailService = new EmailService();
			var dataProtectionProvider = options.DataProtectionProvider;
			if (dataProtectionProvider != null)
			{
				manager.UserTokenProvider =
					new DataProtectorTokenProvider<User>(dataProtectionProvider.Create("EmailConfirmation"));
			}

			return manager;
		}
	}

	/// <summary>
	/// 配置应用程序登录管理器
	/// </summary>
	public class SignInManager : SignInManager<User, string>
	{
		public SignInManager(UserManager userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager)
		{
		}

		public override Task<ClaimsIdentity> CreateUserIdentityAsync(User user)
		{
			return user.GenerateUserIdentityAsync((UserManager)UserManager);
		}

		public static SignInManager Create(IdentityFactoryOptions<SignInManager> options, IOwinContext context)
		{
			return new SignInManager(context.GetUserManager<UserManager>(), context.Authentication);
		}
	}

	/// <summary>
	/// 配置角色管理器
	/// </summary>
	//public class RoleManager : RoleManager<Role>
	//{
	//	public RoleManager(RoleStore<Role> store) : base(store) { }
	//	public static RoleManager Create(IdentityFactoryOptions<RoleManager> options, IOwinContext context)
	//	{
	//		var manager = new RoleManager(new RoleStore<Role>(context.Get<Models.IdentityDbContext>()));
	//		return manager;
	//	}
	//}







}

  

这里还有一个静态的 Create()方法,用于实例化 UserManager 类。用来管理用户的所有相关操作。

 5.  注册 UserManager

配置身份验证主要是使用 CreatePerOwinContext()方法配置数据库上下文和用户管理器,以便为每个请求使用单个实例。

 

在“Yidosoft.Identity”项目的“App_Start”文件夹中添加一个名称为“Startup.Auth.cs”的部分(partial)类文件,类名为“Startup”,作为 OWIN Startup 类的一部分,名称空间修改为:Yidosoft.Identity。然后编写如下代码:

  

using System;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Google;
using Owin;
using jsdhh2.Models;
using jsdhh2.DAL;

namespace jsdhh2
{
    public partial class Startup
    {
        // For more information on configuring authentication, please visit https://go.microsoft.com/fwlink/?LinkId=301864

			 
        public void ConfigureAuth(IAppBuilder app)
        {
			// 配置数据库上下文、用户管理器和登录管理器,以便为每个请求使用单个实例
			//app.CreatePerOwinContext(ApplicationDbContext.Create);
			//app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
			//app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

			app.CreatePerOwinContext(IdentityDbContext.Create);
			//注册UserManger管理器
			app.CreatePerOwinContext<UserManager>(UserManager.Create);
			//注册SignInManager管理器
			app.CreatePerOwinContext<SignInManager>(SignInManager.Create);
			//注册RoleManager管理器
			//app.CreatePerOwinContext<RoleManager>(RoleManager.Create);
			app.UseCookieAuthentication(new CookieAuthenticationOptions
			{
				AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
				LoginPath = new PathString("/User/Login")
			});

}

  

  

在此代码中,还使用了 DefaultAuthenticationTypes.ApplicationCookie 配置默认的认证类型是ApplicationCookie。并且使用LoginPath指定认证失败时转向到的URL。

 

6.  创建 OWIN Startup 

备注,我一般以新建WEB项目时,选了个人验证方式,他自动生成了这些类,不用新建。

在 Visual Studio 2015 中,是可以直接创建“OWIN Startup 类”的。右击“Yidosoft.Identity”项目,如图 4-1 所示:

 

在图 4-1 中点击“添加”“OWIN Startup 类”,如图 4-2 所示:

 

 

由于我们在“Startup.Auth.cs”文件中创建了部分类 Startup,所以在“Startup.cs”文件中的“Startup”类也必须是部分类。完整的代码如下: 

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;

[assembly: OwinStartupAttribute(typeof(jsdhh2.Startup))]
namespace jsdhh2
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            ConfigureAuth(app);
        }
    }
}

  

这里只是在Configuration()方法中调用在Startup.Auth.cs中编写的ConfigureAuth()方法,并将 IAppBuilder 类型的参数传入。创建的 OWIN Startup 类作为身份验证的启动类。主要是与 OWIN 相关的配置。

 5. 创建控制器

在“Yidosoft.Identity”项目的“Controllers”文件夹上右击,点击“添加”“控制器”,如图 5-2 所示:

选择“MVC 5 控制器-空”,点击“添加”按钮。如图 5-3 所示:

 

中将控制器名称修改为“UserController”,点击“添加”按钮。

在控制器中可以使用 HttpContext.GetOwinContext().Get()方法将使用CreatePerOwinContext()方法注册的IdentityDbContext 和UserManager的实例获取。

然后就可以在控制器中使用了。如下代码: 

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using jsdhh2.Models;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.AspNet.Identity;
using  jsdhh2.ViewModels;
using jsdhh2;

namespace Yidosoft.Identity.Controllers
{
	public class UserController : Controller
	{
		private UserManager _userManager;
		public UserManager UserManager
		{
			get
			{
				return _userManager ?? HttpContext.GetOwinContext().GetUserManager<UserManager>();
			}
			private set
			{
				_userManager = value;
			}
		}

		private SignInManager _signInManager;
		public SignInManager SignInManager
		{
			get
			{
				return _signInManager ?? HttpContext.GetOwinContext().Get<SignInManager>();
			}
			private set
			{
				_signInManager = value;
			}
		}


		// GET: User
		public ActionResult Index()
		{
			return View();
		}


		[HttpGet]
		[AllowAnonymous]
		public ActionResult Add()
		{
			return View();
		}

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

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

		//[HttpGet]
		//public ActionResult Edit(string id)
		//{
		//	if (string.IsNullOrWhiteSpace(id))
		//	{
		//		return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest);
		//	}
		//	User user = UserManager.FindById(id);
		//	if (user == null)
		//	{
		//		return HttpNotFound();
		//	}
		//	var editUserViewModel = new EditUserViewModel()
		//	{
		//		Email = user.Email,
		//		QQNumber = user.QQNumber,
		//		WechatNumber = user.WechatNumber
		//	};
		//	return View(editUserViewModel);
		//}

		//[HttpPost]
		//[ValidateAntiForgeryToken]
		//public async Task<ActionResult> Edit(string id, EditUserViewModel editUserViewModel)
		//{
		//	if (ModelState.IsValid && !string.IsNullOrEmpty(id))
		//	{
		//		User user = UserManager.FindById(id);
		//		user.Email = editUserViewModel.Email;
		//		user.QQNumber = editUserViewModel.QQNumber;
		//		user.WechatNumber = editUserViewModel.WechatNumber;
		//		user.UserName = editUserViewModel.Email;
		//		var result = await UserManager.UpdateAsync(user);
		//		if (result.Succeeded)
		//		{
		//			return RedirectToAction("List", "User");
		//		}
		//		AddErrors(result);
		//	}
		//	return View(editUserViewModel);
		//}

		///// <summary>
		///// 登录
		///// </summary>
		///// <param name="returnUrl"></param>
		///// <returns></returns>
		//[HttpGet]
		//[AllowAnonymous]
		//public ActionResult Login(string returnUrl)
		//{
		//	ViewBag.ReturnUrl = returnUrl;
		//	return View();
		//}

		///// <summary>
		///// 登录
		///// </summary>
		///// <param name="model"></param>
		///// <param name="returnUrl"></param>
		///// <returns></returns>
		//[HttpPost]
		//[AllowAnonymous]
		//[ValidateAntiForgeryToken]
		//public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
		//{
		//	if (!ModelState.IsValid)
		//	{
		//		return View(model);
		//	}

		//	// 这不会计入到为执行帐户锁定而统计的登录失败次数中
		//	// 若要在多次输入错误密码的情况下触发帐户锁定,请更改为 shouldLockout: true
		//	var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
		//	switch (result)
		//	{
		//		case SignInStatus.Success:
		//			return RedirectToLocal(returnUrl);
		//		case SignInStatus.LockedOut:
		//			return View("Lockout");
		//		case SignInStatus.RequiresVerification:
		//			return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
		//		case SignInStatus.Failure:
		//		default:
		//			ModelState.AddModelError("", "无效的登录尝试。");
		//			return View(model);
		//	}
		//}

		///// <summary>
		///// 邮箱验证
		///// </summary>
		///// <param name="userId"></param>
		///// <param name="code"></param>
		///// <returns></returns>
		//[HttpGet]
		//[AllowAnonymous]
		//public async Task<ActionResult> ConfirmEmail(string userId, string code)
		//{
		//	if (userId == null || code == null)
		//	{
		//		return View("Error");
		//	}
		//	var result = await UserManager.ConfirmEmailAsync(userId, code);
		//	return View(result.Succeeded ? "ConfirmEmail" : "Error");
		//}

		///// <summary>
		///// 忘记密码
		///// </summary>
		///// <returns></returns>
		//[AllowAnonymous]
		//public ActionResult ForgotPassword()
		//{
		//	return View();
		//}

		///// <summary>
		///// 忘记密码
		///// </summary>
		///// <param name="model"></param>
		///// <returns></returns>
		//[HttpPost]
		//[AllowAnonymous]
		//[ValidateAntiForgeryToken]
		//public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
		//{
		//	if (ModelState.IsValid)
		//	{
		//		var user = await UserManager.FindByNameAsync(model.Email);
		//		if (user == null)
		//		{
		//			return View("Error");
		//		}

		//		//发送包含此链接的电子邮件
		//		string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
		//		var callbackUrl = Url.Action("ResetPassword", "User", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
		//		await UserManager.SendEmailAsync(user.Id, "重置密码", "请通过单击 <a href=\"" + callbackUrl + "\">此处</a>来重置你的密码");
		//		return RedirectToAction("ForgotPasswordConfirmation", "User");
		//	}

		//	// 如果我们进行到这一步时某个地方出错,则重新显示表单
		//	return View(model);
		//}

		//[AllowAnonymous]
		//public ActionResult ForgotPasswordConfirmation()
		//{
		//	return View();
		//}

		///// <summary>
		///// 重置密码
		///// </summary>
		///// <param name="code"></param>
		///// <returns></returns>
		//[HttpGet]
		//[AllowAnonymous]
		//public ActionResult ResetPassword(string code)
		//{
		//	return code == null ? View("Error") : View();
		//}

		///// <summary>
		///// 重置密码
		///// </summary>
		///// <param name="model"></param>
		///// <returns></returns>
		//[HttpPost]
		//[AllowAnonymous]
		//[ValidateAntiForgeryToken]
		//public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
		//{
		//	if (!ModelState.IsValid)
		//	{
		//		return View(model);
		//	}
		//	var user = await UserManager.FindByNameAsync(model.Email);
		//	if (user == null)
		//	{
		//		return View("Error");
		//	}
		//	var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
		//	if (result.Succeeded)
		//	{
		//		return RedirectToAction("ResetPasswordConfirmation", "User");
		//	}
		//	AddErrors(result);
		//	return View();
		//}

		//[AllowAnonymous]
		//public ActionResult ResetPasswordConfirmation()
		//{
		//	return View();
		//}


		private void AddErrors(IdentityResult result)
		{
			foreach (var error in result.Errors)
			{
				ModelState.AddModelError("", error);
			}
		}

		//private ActionResult RedirectToLocal(string returnUrl)
		//{
		//	if (Url.IsLocalUrl(returnUrl))
		//	{
		//		return Redirect(returnUrl);
		//	}
		//	return RedirectToAction("Index", "Home");
		//}
	}
}

  有点无语的是 public SignInManager SignInManager 老出错,以我的水平实在不知道错在哪,后来,把命名空间乱搞一下,成功了

using jsdhh2;

namespace Yidosoft.Identity.Controllers

  

 

 

 

 在控制器的方法中,就可以使用 UserManager 属性进行用户管理了。

6. 添加客户端验证(这步我也没安装自带的就有)

此步骤的操作也可以在空的 MVC 5 项目中第一次添加视图(也就是后面讲解的7.1.3 节)之后再操作。这里作为独立的一个章节拿出来讲解。在 ASP.NET MVC 5 空项目中,在第一次添加视图时,Visual Studio 2015 会自动添加一些与 UI 相关的文件,包括 Bootstrap、Jquery、modernizr 等。但是就没有添加与客户端验证相关的 JS 文件。默认情况下,ASP.NET MVC 5 是支持客户端和服务器端双重数据验证的。服务器端数据验证默认就支持。现在我们添加与客户端相关的 JS 文件。

ASP.NET MVC 5 的客户端数据验证是需要 jquery.validate.js 和jquery.validate.unobtrusive.js 这两个 JS 文件支持的。“Microsoft.jQuery.Unobtrusive.Validation”,这是由微软在 jQuery 的基础上编写的在 ASP.NET MVC 5 下使用的验证 JS 文件。可以通过 NuGet 包管理器安装这 2 个验证文件。如图 6-1 所示:

 

圈住的两个包安装。安装完成后如图 6-2 所示:

 

安装成功后,会在项目的“Scripts”文件夹中添加图 6-2 红线标注的 5 个文件,其
中还包括了 min.js 类型的文件。
打开“_Layout.cshtml”视图,将:
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
放在原 JS 文件的底部。如图 6-3 所示:

由于 jquery.validate.js 是依赖于 jquery.js 文件的,所以要放在 jquery.js 文件后面
才会生效

_Layout布局上加上:

@Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
	<script src="~/Scripts/jquery.validate.js"></script>
	<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>

  

 

 

 

 

 

 

 

 

 

 

 

 

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