zoukankan      html  css  js  c++  java
  • ASP.NET Identity系列02,在ASP.NET MVC中增删改查用户

    本篇体验在ASP.NET MVC中使用ASP.NET Identity增删改查用户。

    源码在这里: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="stylesheet" />
    
        <link href="~/Content/bootstrap-theme.min.css" 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>
    

    1

    前期准备


     

    分别安装如下组件。

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


    4

    创建用户

     

    在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>
    


    5

    点击"创建"按钮,创建成功返回显示用户页面。

    6

    oh, my god,只是配置了一下就有数据了? 数据在哪呢?

    点击左上角的"服务器资源管理器",右键"IdentityDb",点击"刷新"。

    7

    再打开AspNetUsers表,刚创建的用户赫然在列。

    8

    好像还有点欠缺,用户输入密码的时候,总应该有些限制吧。

    能想到的,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;
    
            }
    
        }
    
    }
    

    再次运行程序,创建用户页面,尝试输入不通过的密码。

    9


    不过,关于密码的规则,似乎可以在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真的很好很强大!

  • 相关阅读:
    C++--第25课
    C++--第24课
    C++--第23课
    C++--第22课
    C++--第21课
    C++--第20课
    C++--第19课
    C++--第18课
    C++--第17课
    Windows程序设计学习笔记(1):一个简单的windows程序
  • 原文地址:https://www.cnblogs.com/darrenji/p/4444431.html
Copyright © 2011-2022 走看看