源码在这里:https://github.com/darrenji/useidentitycruduserinmvc,本地下载
在vs2013中创建一个mvc项目,用默认的"无身份验证"作为身份验证机制。
通过控制台下载bootstrap。
install-package -version 3.0.3 bootstrap
下载成功后,在解决方案下的content和scripts多了该版本的css和js文件。
把创建项目默认homecontroller中的所有action以及/views/home下的所有视图删除。
热热身
先来做一个简单练习。
在homecontroller中的index方法中,把一个字典传递给视图。
public class homecontroller : controller { public actionresult index() { dictionary<string, object> data = new dictionary<string, object>(); data.add("placeholder", "placeholder"); return view(data); } }
_layout.cshtml设置如下:
<head> <meta http-equiv="content-type" content="text/html; charset=utf-8"/> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>asp.net identity实战</title> <link href="~/content/bootstrap.min.css" rel="external nofollow" rel="stylesheet" /> <link href="~/content/bootstrap-theme.min.css" rel="external nofollow" rel="stylesheet" /> <style> .container {padding-top:10px;} .validation-summary-errors{color:red;} </style> </head> <body> <div class="container"> @renderbody() </div> @scripts.render("~/bundles/jquery") @scripts.render("~/bundles/bootstrap") @rendersection("scripts", required: false) </body>
home/index.cshtml视图中:
@{ viewbag.title = "index"; layout = "~/views/shared/_layout.cshtml"; } <div class="panel panel-primary"> <div class="panel-heading">用户明细</div> <table class="table table-striped"> @foreach (string key in model.keys) { <tr> <th>@key</th> <td>@model[key]</td> </tr> } </table> </div>
前期准备
分别安装如下组件。
install-package microsoft.aspnet.identity.entityframework –version 2.0.0
install-package microsoft.aspnet.identity.owin -version 2.0.0
install-package microsoft.owin.host.systemweb -version 2.1.0
配置web.config如下:
<?xml version="1.0" encoding="utf-8"?> <!-- 有关如何配置 asp.net 应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?linkid=301880 --> <configuration> <configsections> <!-- for more information on entity framework configuration, visit http://go.microsoft.com/fwlink/?linkid=237468 --> <section name="entityframework" type="system.data.entity.internal.configfile.entityframeworksection, entityframework, version=6.0.0.0, culture=neutral, publickeytoken=b77a5c561934e089" requirepermission="false" /> </configsections> <connectionstrings> <add name="identitydb" providername="system.data.sqlclient" connectionstring="data source=(localdb)\v11.0;initial catalog=identitydb;integrated security=true;connect timeout=15;encrypt=false;trustservercertificate=false;multipleactiveresultsets=true"/> </connectionstrings> <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" /> <add key="owin:appstartup" value="webapplication4.identityconfig" /> </appsettings> <system.web> <compilation debug="true" targetframework="4.5" /> <httpruntime targetframework="4.5" /> </system.web> <runtime> <assemblybinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentassembly> <assemblyidentity name="system.web.helpers" publickeytoken="31bf3856ad364e35" /> <bindingredirect oldversion="1.0.0.0-3.0.0.0" newversion="3.0.0.0" /> </dependentassembly> <dependentassembly> <assemblyidentity name="system.web.mvc" publickeytoken="31bf3856ad364e35" /> <bindingredirect oldversion="1.0.0.0-5.0.0.0" newversion="5.0.0.0" /> </dependentassembly> <dependentassembly> <assemblyidentity name="system.web.optimization" publickeytoken="31bf3856ad364e35" /> <bindingredirect oldversion="1.0.0.0-1.1.0.0" newversion="1.1.0.0" /> </dependentassembly> <dependentassembly> <assemblyidentity name="system.web.webpages" publickeytoken="31bf3856ad364e35" /> <bindingredirect oldversion="1.0.0.0-3.0.0.0" newversion="3.0.0.0" /> </dependentassembly> <dependentassembly> <assemblyidentity name="webgrease" publickeytoken="31bf3856ad364e35" /> <bindingredirect oldversion="0.0.0.0-1.5.2.14234" newversion="1.5.2.14234" /> </dependentassembly> </assemblybinding> </runtime> <entityframework> <defaultconnectionfactory type="system.data.entity.infrastructure.sqlconnectionfactory, entityframework" /> <providers> <provider invariantname="system.data.sqlclient" type="system.data.entity.sqlserver.sqlproviderservices, entityframework.sqlserver" /> </providers> </entityframework> </configuration>
以上,
- 增加了connectionstrings节点,将自动创建localdb数据库
- 在appsettings节点中增加了一个key为owin:appstartup项,这是确保owin运行正常的全局配置
在models文件夹下创建如下类。
public class appuser : identityuser { }
在解决方案下创建infrastructure文件夹。
在infrastructure文件夹下创建一个上下文类,需要实现identitydbcontext<>接口。
public class appidentitydbcontext : identitydbcontext<appuser> { public appidentitydbcontext() : base("identitydb") { } static appidentitydbcontext() { //使用ef code first第一次创建的时候调用 database.setinitializer<appidentitydbcontext>(new identitydbinit()); } public static appidentitydbcontext create() { return new appidentitydbcontext(); } } //初始化 public class identitydbinit : dropcreatedatabaseifmodelchanges<appidentitydbcontext> { protected override void seed(appidentitydbcontext context) { performinitialsetup(context); base.seed(context); } //初始化工作 public void performinitialsetup(appidentitydbcontext context) { } }
在infrastructure文件夹下创建一个管理用户的类,需要继承usermanager<appuser>类。
还记得,先前在appsettings节点中配置了一个如下方式:
<add key="owin:appstartup" value="webapplication4.identityconfig" />
owin需要一个全局启动文件,默认会到项目的顶级命名空间下找identityconfig这个类。
那就在app_start中创建identityconfig这个类,这个类在webapplication4这个命名空间下。
namespace webapplication4 { public class identityconfig { public void configuration(iappbuilder app) { app.createperowincontext<appidentitydbcontext>(appidentitydbcontext.create); app.createperowincontext<appusermanager>(appusermanager.create); app.usecookieauthentication(new cookieauthenticationoptions { authenticationtype = defaultauthenticationtypes.applicationcookie, loginpath = new microsoft.owin.pathstring("/account/login") }); } } }
显示用户
创建admincontroller,现在可以向视图传递所有的用户了,编写如下:
public class admincontroller : controller { public actionresult index() { return view(usermanager.users); } private appusermanager usermanager { get { return httpcontext.getowincontext().getusermanager<appusermanager>(); } } }
再创建admin/index.cshtml类型为ienumerable<appuser>的强类型视图。
@model ienumerable<webapplication4.models.appuser> @{ viewbag.title = "index"; layout = "~/views/shared/_layout.cshtml"; } <div class="panel panel-primary"> <div class="panel-heading"> 所有用户账户 </div> <table class="table table-striped"> <tr><th>id</th><th>name</th><th>email</th><th></th></tr> @if (model.count() == 0) { <tr><td colspan="4" class="text-center">还没有创建用户</td></tr> } else { foreach (webapplication4.models.appuser user in model) { <tr> <td>@user.id</td> <td>@user.username</td> <td>@user.email</td> <td> @using (html.beginform("delete", "admin", new { id = user.id })) { @html.actionlink("编辑", "edit", new { id = user.id }, new { @class = "btn btn-primary btn-xs" }) <button class="btn btn-danger btn-xs" type="submit"> 删除 </button> } </td> </tr> } } </table> </div> @html.actionlink("创建用户", "create", null, new { @class = "btn btn-primary" })
创建用户
在models文件夹下创建一个视图模型。
namespace webapplication4.models { public class createmodel { public string id { get; set; } [required] public string name { get; set; } [required] public string email { get; set; } [required] public string password { get; set; } } }
在admincontroller中添加创建用户相关的方法。
public class admincontroller : controller { public actionresult index() { return view(usermanager.users); } //创建显示 public actionresult create() { return view(); } [httppost] public async task<actionresult> create(createmodel model) { if(modelstate.isvalid) { var user = new appuser{username = model.name, email = model.email}; identityresult result = await usermanager.createasync(user, model.password); if(result.succeeded) { return redirecttoaction("index"); }else{ adderrorsfromresult(result); } } return view(model); } //创建接收 private void adderrorsfromresult(identityresult result) { foreach(var error in result.errors) { modelstate.addmodelerror("", error); } } private appusermanager usermanager { get { return httpcontext.getowincontext().getusermanager<appusermanager>(); } } }
在admin/create.cshtml视图页中:
@model webapplication4.models.createmodel @{ viewbag.title = "create"; layout = "~/views/shared/_layout.cshtml"; } <h2>create</h2> @using (html.beginform()) { @html.antiforgerytoken() <div class="form-horizontal"> <h4>创建用户</h4> <hr /> @html.validationsummary(true) <div class="form-group"> @html.labelfor(model => model.name, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @html.editorfor(model => model.name) @html.validationmessagefor(model => model.name) </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"> @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"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="创建用户" class="btn btn-default" /> </div> </div> </div> } <div> @html.actionlink("返回", "index") </div>
点击"创建"按钮,创建成功返回显示用户页面。
oh, my god,只是配置了一下就有数据了? 数据在哪呢?
点击左上角的"服务器资源管理器",右键"identitydb",点击"刷新"。
再打开aspnetusers表,刚创建的用户赫然在列。
好像还有点欠缺,用户输入密码的时候,总应该有些限制吧。
能想到的,asp.net identity都为我们准备好了。有一个passwordvalidator类就是干这个的。
在infrastructure文件夹中创建一个passwordvalidator类的继承子类。
namespace webapplication4.infrastructure { public class custompasswordvalidator : passwordvalidator { public override async task<identityresult> validateasync(string pass) { identityresult result = await base.validateasync(pass); if (pass.contains("12345")) { var errors = result.errors.tolist(); errors.add("密码中包含太多连续数字"); result = new identityresult(errors); } return result; } } }
然后需要把这个规则告诉usermanager。
namespace webapplication4.infrastructure { public class appusermanager : usermanager<appuser> { public appusermanager(iuserstore<appuser> store) : base(store) { } public static appusermanager create(identityfactoryoptions<appusermanager> options, iowincontext context) { //identity ef上下文 appidentitydbcontext db = context.get<appidentitydbcontext>(); //与identity ef相关的userstore iuserstore<appuser> us = new userstore<appuser>(db); appusermanager manager = new appusermanager(us); //密码相关 manager.passwordvalidator = new custompasswordvalidator { requiredlength = 6, requirenonletterordigit = false, requiredigit = false, requirelowercase = true, requireuppercase = true }; return manager; } } }
再次运行程序,创建用户页面,尝试输入不通过的密码。
不过,关于密码的规则,似乎可以在view model的验证层面就可以解决掉。
编辑和删除用户
在admincontroller中增加编辑和删除的部分。
public class admincontroller : controller { public actionresult index() { return view(usermanager.users); } //创建显示 public actionresult create() { return view(); } //创建接收 [httppost] public async task<actionresult> create(createmodel model) { if(modelstate.isvalid) { var user = new appuser{username = model.name, email = model.email}; identityresult result = await usermanager.createasync(user, model.password); if(result.succeeded) { return redirecttoaction("index"); }else{ adderrorsfromresult(result); } } return view(model); } //编辑显示 public async task<actionresult> edit(string id) { appuser user = await usermanager.findbyidasync(id); if(user != null) { createmodel createmodel = new createmodel(); createmodel.id = user.id; createmodel.email = user.email; createmodel.name = user.username; createmodel.password = user.passwordhash; return view(createmodel); } else { return redirecttoaction("index"); } } //接收编辑 [httppost] public async task<actionresult> edit(createmodel createmodel) { if(modelstate.isvalid) { appuser user = await usermanager.findbyidasync(createmodel.id); if (user != null) { //关于邮箱 user.email = createmodel.email; identityresult validemail = await usermanager.uservalidator.validateasync(user); if (!validemail.succeeded) { adderrorsfromresult(validemail); } user.username = createmodel.name; //关于密码 identityresult validpass = null; if (createmodel.password != string.empty) { validpass = await usermanager.passwordvalidator.validateasync(createmodel.password); if (validpass.succeeded) { user.passwordhash = usermanager.passwordhasher.hashpassword(createmodel.password); } else { adderrorsfromresult(validpass); } } user.email = createmodel.email; //验证结果 if ((validemail.succeeded && validpass == null) || (validemail.succeeded && createmodel.password != string.empty && validpass.succeeded)) { identityresult result = await usermanager.updateasync(user); if (result.succeeded) { return redirecttoaction("index"); } else { adderrorsfromresult(result); } } else { modelstate.addmodelerror("", "无此用户"); } } return view(createmodel); } else { return view(createmodel); } } //删除 [httppost] public async task<actionresult> delete(string id) { appuser user = await usermanager.findbyidasync(id); if(user != null) { identityresult result = await usermanager.deleteasync(user); if(result.succeeded) { return redirecttoaction("index"); } else { return view("error", result.errors); } } else { return view("error", new string[] { "没有此用户" }); } } private void adderrorsfromresult(identityresult result) { foreach(var error in result.errors) { modelstate.addmodelerror("", error); } } private appusermanager usermanager { get { return httpcontext.getowincontext().getusermanager<appusermanager>(); } } }
admin/edit.cshtml视图。
@model webapplication4.models.createmodel @{ viewbag.title = "edit"; layout = "~/views/shared/_layout.cshtml"; } <h2>edit</h2> @using (html.beginform()) { @html.antiforgerytoken() <div class="form-horizontal"> <hr /> @html.validationsummary(true) @html.hiddenfor(model => model.id) <div class="form-group"> @html.labelfor(model => model.name, new { @class = "control-label col-md-2" }) <div class="col-md-10"> @html.editorfor(model => model.name) @html.validationmessagefor(model => model.name) </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"> @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"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="保存" class="btn btn-default" /> </div> </div> </div> } <div> @html.actionlink("返回", "index") </div>
另外,如果删除失败,跳转到shared/error.cshtml视图页。
@model ienumerable<string> @{ viewbag.title = "error";} <div class="alert alert-danger"> @switch (model.count()) { case 0: @: something went wrong. please try again break; case 1: @model.first(); break; default: @: 发现如下错误: <ul> @foreach (string error in model) { <li>@error</li> } </ul> break; } </div> @html.actionlink("确定", "index", null, new { @class = "btn btn-default" })
至此,使用asp.net identy实现对用户的增删改查完毕,asp.net identity真的很好很强大!
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对代码网的支持。如果你想了解更多相关内容请查看下面相关链接
发表评论