一步一步創(chuàng)建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](八)

前言

Hi,
大家好,還是星期五,還是Rector,又在圖享網(wǎng)準(zhǔn)時(shí)和大家見(jiàn)面了。
今天給大家?guī)?lái)系列教程《一步一步創(chuàng)建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar]》的第八期了,不知道你有沒(méi)有按照教程將前七期的都實(shí)際練習(xí)一篇呢?如果是,你在練習(xí)的時(shí)候有沒(méi)有遇到什么問(wèn)題呢?
反正Rector是有收到部分童鞋發(fā)來(lái)他們練習(xí)過(guò)程中的問(wèn)題反饋的哦。

如果你仔細(xì)閱讀并實(shí)際練習(xí)了前面七期的教程,我相信,作為剛?cè)腴T(mén)或者經(jīng)驗(yàn)尚淺的你一定會(huì)有收獲的。

加油吧,騷年?。?! 人生苦短,就怕努力?。?!

Rector這是要成為心理導(dǎo)師的節(jié)奏啊,一來(lái)就給大家灌飽心靈雞湯。。。

**本文篇幅有點(diǎn)長(zhǎng),請(qǐng)作好心里準(zhǔn)備?。?!
同時(shí),也吐個(gè)槽,本文看似內(nèi)容簡(jiǎn)單的一B,但也花了筆者幾個(gè)小時(shí)來(lái)準(zhǔn)備示例以及寫(xiě)作,寫(xiě)技術(shù)文章真心傷不起
珍愛(ài)生命,遠(yuǎn)離程序!?。?br> **

還是回到我們的正題,開(kāi)始我們今天的系列教程:《一步一步創(chuàng)建ASP.NET MVC5程序Repository+Autofac+Automapper+SqlSugar

本文知識(shí)要點(diǎn)

  • 用戶注冊(cè)/登錄功能設(shè)計(jì)與實(shí)現(xiàn)

設(shè)計(jì)用戶表

這個(gè)表呢,Rector已經(jīng)為大家準(zhǔn)備好了,MySQL表結(jié)構(gòu)如下:

SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for ts_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user`  (
  `Id` int(10) NOT NULL AUTO_INCREMENT,
  `LoginName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '登錄名',
  `Password` varchar(150) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '密碼',
  `DisplayName` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '顯示名稱',
  `RealName` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '真實(shí)姓名',
  `EmailAddress` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '電子郵箱',
  `Avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '用戶頭像',
  `Status` int(2) NOT NULL DEFAULT 1 COMMENT '用戶的狀態(tài),0:禁用,1:正常',
  `Telephone` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '手機(jī)號(hào)碼',
  `Qq` varchar(15) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '',
  `WebsiteUrl` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '',
  `CreatedOn` datetime(0) NULL DEFAULT NULL COMMENT '用戶創(chuàng)建時(shí)間',
  `CreatedIp` varchar(24) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '創(chuàng)建用戶時(shí)的IP地址',
  `LoginCount` int(8) NULL DEFAULT 0 COMMENT '登錄次數(shù)累加器',
  `LatestLoginDate` datetime(0) NULL DEFAULT NULL COMMENT '最近一次登錄時(shí)間',
  `LatestLoginIp` varchar(24) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '最近一次登錄時(shí)的IP地址',
  `ModifiedOn` datetime(0) NULL DEFAULT NULL COMMENT '最近修改時(shí)間',
  `Type` int(2) NULL DEFAULT 0 COMMENT '用戶類型[-1:超級(jí)管理員,0:一般用戶]',
  PRIMARY KEY (`Id`) USING BTREE,
  UNIQUE INDEX `IX_LoginName`(`LoginName`) USING BTREE,
  UNIQUE INDEX `IX_EmailAddress`(`EmailAddress`) USING BTREE,
  INDEX `IX_CreatedOn`(`CreatedOn`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 0 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

請(qǐng)直接復(fù)制以上MySQL腳本,然后到對(duì)應(yīng)數(shù)據(jù)執(zhí)行即可,當(dāng)然你也可以在這個(gè)版本的源碼里面找到。
這個(gè)表就不準(zhǔn)備提前寫(xiě)入示例數(shù)據(jù)了,一會(huì)我們用注冊(cè)功能來(lái)寫(xiě)入數(shù)據(jù)。

創(chuàng)建領(lǐng)域?qū)嶓w和視圖實(shí)體

在項(xiàng)目 【TsBlog.Domain】中的Entities文件夾中創(chuàng)建 User.cs 實(shí)體類:

using SqlSugar;
using System;

namespace TsBlog.Domain.Entities
{
    [SugarTable("tb_user")]
    public class User
    {
        [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
        public int Id { get; set; }
        public string LoginName { get; set; }
        public string Password { get; set; }
        public string RealName { get; set; }
        public string EmailAddress { get; set; }
        public string Avatar { get; set; }
        public int Status { get; set; }
        public string Telephone { get; set; }
        public string Qq { get; set; }
        public string WebsiteUrl { get; set; }
        public DateTime CreatedOn { get; set; }
        public string CreatedIp { get; set; }
        public int LoginCount { get; set; }
        public DateTime? LatestLoginDate { get; set; }
        public string LatestLoginIp { get; set; }
        public DateTime? ModifiedOn { get; set; }
        public int Type { get; set; }
    }
}

再在項(xiàng)目【TsBlog.ViewModel】中創(chuàng)建 User 的文件夾,并創(chuàng)建以下幾個(gè)視圖實(shí)體類

LoginViewModel.cs

using System.ComponentModel.DataAnnotations;

namespace TsBlog.ViewModel.User
{
    /// <summary>
    /// 用戶登錄視圖實(shí)體
    /// </summary>
    public class LoginViewModel
    {
        [Required(ErrorMessage = "請(qǐng)輸入用戶")]
        [Display(Name = "用戶名")]
        public string UserName { get; set; }
        [Required(ErrorMessage = "請(qǐng)輸入密碼")]
        [Display(Name = "密碼")]
        [DataType(DataType.Password)]
        public string Password { get; set; }
    }
}

RegisterViewModel.cs

using System.ComponentModel.DataAnnotations;

namespace TsBlog.ViewModel.User
{
    /// <summary>
    /// 用戶注冊(cè)視圖實(shí)體
    /// </summary>
    public class RegisterViewModel
    {
        [Required(ErrorMessage = "請(qǐng)輸入用戶名")]
        [Display(Name = "用戶名")]
        public string UserName { get; set; }
        [Required(ErrorMessage = "請(qǐng)輸入密碼")]
        [Display(Name = "密碼")]
        [DataType(DataType.Password), MaxLength(20, ErrorMessage = "密碼最大長(zhǎng)度為20個(gè)字符"), MinLength(6, ErrorMessage = "密碼最小長(zhǎng)度為6個(gè)字符")]
        public string Password { get; set; }

        [Required(ErrorMessage = "請(qǐng)輸入確認(rèn)密碼")]
        [Display(Name = "確認(rèn)密碼")]
        [DataType(DataType.Password), Compare("Password", ErrorMessage = "兩次密碼不一致")]
        public string ConfirmPassword { get; set; }
    }
}

UserViewModel.cs:

using System;

namespace TsBlog.ViewModel.User
{
    /// <summary>
    /// 與領(lǐng)域用戶實(shí)體對(duì)應(yīng)的用戶視圖實(shí)體
    /// </summary>
    public class UserViewModel
    {
        public int Id { get; set; }
        public string LoginName { get; set; }
        public string Password { get; set; }
        public string RealName { get; set; }
        public string EmailAddress { get; set; }
        public string Avatar { get; set; }
        public int Status { get; set; }
        public string Telephone { get; set; }
        public string Qq { get; set; }
        public string WebsiteUrl { get; set; }
        public DateTime CreatedOn { get; set; }
        public string CreatedIp { get; set; }
        public int LoginCount { get; set; }
        public DateTime? LatestLoginDate { get; set; }
        public string LatestLoginIp { get; set; }
        public DateTime? ModifiedOn { get; set; }
        public int Type { get; set; }
    }
}

倉(cāng)儲(chǔ)層

在項(xiàng)目【TsBlog.Repositories】中創(chuàng)建 IUserRepository.cs 以及其實(shí)現(xiàn)類 UserRepository.cs。

IUserRepository.cs:

using TsBlog.Domain.Entities;

namespace TsBlog.Repositories
{
    public interface IUserRepository : IRepository<User>
    {

    }
}

UserRepository.cs:

using TsBlog.Domain.Entities;

namespace TsBlog.Repositories
{
    public class UserRepository : GenericRepository<User>, IUserRepository
    {

    }
}

服務(wù)層

在項(xiàng)目【TsBlog.Services】中創(chuàng)建 IUserService.cs 以及其實(shí)現(xiàn)類 UserService.cs。

IUserService.cs:

using TsBlog.Domain.Entities;

namespace TsBlog.Services
{
    public interface IUserService : IService<User>
    {
        User FindByLoginName(string loginName);
    }
}

UserService.cs:

using TsBlog.Domain.Entities;
using TsBlog.Repositories;

namespace TsBlog.Services
{
    public class UserService : GenericService<User>, IUserService
    {
        private readonly IUserRepository _repository;
        public UserService(IUserRepository repository) : base(repository)
        {
            _repository = repository;
        }

        public User FindByLoginName(string loginName)
        {
            return _repository.FindByClause(x => x.LoginName == loginName);
        }
    }
}

創(chuàng)建加密類

在解決方案文件夾【1.Libraries】中創(chuàng)建一個(gè)新的項(xiàng)目,取名為【TsBlog.Core】,在此項(xiàng)目中先創(chuàng)建一個(gè)名為 Security的文件夾,再創(chuàng)建一個(gè)加密類 Encryptor.cs

using System.Security.Cryptography;
using System.Text;

namespace TsBlog.Core.Security
{
    /// <summary>
    /// 加密靜態(tài)類
    /// </summary>
    public static class Encryptor
    {
        //MD5加密一個(gè)字符串
        public static string Md5Hash(string text)
        {
            MD5 md5 = new MD5CryptoServiceProvider();
            md5.ComputeHash(Encoding.ASCII.GetBytes(text));

            var result = md5.Hash;

            var strBuilder = new StringBuilder();
            foreach (var t in result)
            {
                strBuilder.Append(t.ToString("x2"));
            }

            return strBuilder.ToString();
        }
    }
}

在用戶注冊(cè)或者登錄時(shí),我們將使用這個(gè)MD5加密用戶的密碼,并將其保存到數(shù)據(jù)庫(kù)中(數(shù)據(jù)庫(kù)中保存明文的密碼是非常危險(xiǎn)的,特別是在重要的安全級(jí)別很高的項(xiàng)目中,千(不)萬(wàn)(信)別(你)這(試)樣(一)做(下)?。。。?/p>

創(chuàng)建控制器

在項(xiàng)目【TsBlog.Frontend】中創(chuàng)建控制器 AccountController.cs,并添加如下代碼:

AccountController.cs

using System;
using System.Web.Mvc;
using TsBlog.Core.Security;
using TsBlog.Domain.Entities;
using TsBlog.Services;
using TsBlog.ViewModel.User;

namespace TsBlog.Frontend.Controllers
{
    /// <summary>
    /// 用戶中心控制器
    /// </summary>
    public class AccountController : Controller
    {
        /// <summary>
        /// 用戶服務(wù)接口
        /// </summary>
        private readonly IUserService _userService;

        public AccountController(IUserService userService)
        {
            _userService = userService;
        }

        /// <summary>
        /// 登錄頁(yè)面
        /// </summary>
        /// <returns></returns>
        public ActionResult Login()
        {
            return View();
        }

        /// <summary>
        /// 提交登錄請(qǐng)求
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, ValidateAntiForgeryToken, AllowAnonymous]
        public ActionResult Login(LoginViewModel model)
        {
            //如果視圖模型中的屬性沒(méi)有驗(yàn)證通過(guò),則返回到登錄頁(yè)面,要求用戶重新填寫(xiě)
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            //根據(jù)用戶登錄名查詢指定用戶實(shí)體
            var user = _userService.FindByLoginName(model.UserName.Trim());

            //如果用戶不存在,則攜帶錯(cuò)誤消息并返回登錄頁(yè)面
            if (user == null)
            {
                ModelState.AddModelError("error_message", "用戶不存在");
                return View(model);
            }

            //如果密碼不匹配,則攜帶錯(cuò)誤消息并返回登錄頁(yè)面
            if (user.Password != Encryptor.Md5Hash(model.Password.Trim()))
            {
                ModelState.AddModelError("error_message", "密碼錯(cuò)誤,請(qǐng)重新登錄");
                return View(model);
            }

            //并用戶實(shí)體保存到Session中
            Session["user_account"] = user;
            //跳轉(zhuǎn)到首頁(yè)
            return RedirectToAction("index", "home");
        }

        /// <summary>
        /// 注冊(cè)頁(yè)面
        /// </summary>
        /// <returns></returns>
        public ActionResult Register()
        {
            return View();
        }

        /// <summary>
        /// 提交注冊(cè)請(qǐng)求
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost, ValidateAntiForgeryToken, AllowAnonymous]
        public ActionResult Register(RegisterViewModel model)
        {
            //如果視圖模型中的屬性沒(méi)有驗(yàn)證通過(guò),則返回到注冊(cè)頁(yè)面,要求用戶重新填寫(xiě)
            if (!ModelState.IsValid)
            {
                return View(model);
            }

            //創(chuàng)建一個(gè)用戶實(shí)體
            var user = new User
            {
                LoginName = model.UserName,
                Password = Encryptor.Md5Hash(model.Password.Trim()),
                CreatedOn = DateTime.Now
                //由于是示例教程,所以其他字段不作填充了
            };
            //將用戶實(shí)體對(duì)象寫(xiě)入數(shù)據(jù)庫(kù)中
            var ret = _userService.Insert(user);

            if (ret <= 0)
            {
                //如果注冊(cè)失敗,則攜帶錯(cuò)誤消息并返回注冊(cè)頁(yè)面
                ModelState.AddModelError("error_message", "注冊(cè)失敗");
                return View(model);

            }
            //如果注冊(cè)成功,則跳轉(zhuǎn)到登錄頁(yè)面
            return RedirectToAction("login");
        }
    }
}

添加必要JS庫(kù)

由于之前我們將項(xiàng)目中的多余的JS庫(kù)全部移除掉了,所以現(xiàn)在我們重新安裝一下我們項(xiàng)目中將要到的一些JS庫(kù),包括:jQuery,Bootstrap等,都使用Nuget來(lái)安裝,方便統(tǒng)一管理和升級(jí)。

安裝jQuery:

create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-01.png
create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-01.png

安裝Bootstrap:

create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-02.png
create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-02.png

安裝jquery.validate.bootstrap:

create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-03.png
create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-03.png

安裝完成后的JS庫(kù)文件夾:

create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-04.png
create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-04.png

完成注冊(cè)頁(yè)面

在 [Views/Account]文件夾中創(chuàng)建注冊(cè)頁(yè)面視圖 register.cshtml

@model TsBlog.ViewModel.User.RegisterViewModel
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>用戶注冊(cè)</title>
    <style type="text/css">

        * { box-sizing: border-box; }
        body { box-sizing: border-box; margin: 0; padding: 0; color: #333; }
        .account-container { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; width: 400px; height: 480px; background-color: #fff; /*border-radius: 3px;*/ box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); }

        .account-signin-container { margin-top: 15px; }
            .account-signin-container h1 { font-size: 20px; border-bottom: 2px solid #f7f7f7; margin: 0 0 15px; padding-bottom: 10px; padding-left: 15px; letter-spacing: 0.1em; }
        .account-form { padding: 15px; }
            .account-form .form-group { width: 100%; margin-bottom: 15px; }
                .account-form .form-group label { width: 100%; display: block; }
                .account-form .form-group input { border: 1px solid #ccc; line-height: 32px; font-size: 16px; padding: 2px 0px; padding-left: 5px; display: block; width: 100%; margin-top: 5px; }
            .account-form #btn_register { border: 0; background: #3b78e7; color: #fff; font-size: 18px; font-weight: bold; padding: 8px 25px; cursor: pointer; margin-top: 15px; display: inline-block; box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); border-radius: 3px; min-width: 100px; text-align: center; }
                .account-form #btn_register:hover { background: #4885F3; }
        span.error { color: #f00; }
        .btn-login { float: right; display: block; margin-top: 25px; color: #4885f3; }

        @@media(max-width:500px) {
            .account-container { width: 100%; height: 100vh; }
        }
    </style>
</head>
<body>
    <div class="account-container">
        <div class="account-modal-container">
            <div class="modal"></div>
            <div class="load-bar-container">
                <div class="load-bar">
                    <div class="bar"></div>
                    <div class="bar"></div>
                    <div class="bar"></div>
                </div>
            </div>
            <div class="account-signin-container">
                <h1>用戶注冊(cè)</h1>
                @using (Html.BeginForm("register", "account", FormMethod.Post, new { @class = "account-form", role = "form" }))
                {
                    @Html.ValidationMessage("error_message", new { @class = "error" })
                    @Html.AntiForgeryToken()
                    <div class="form-group">
                        <label>
                            <span>登錄名:</span>
                            @Html.TextBoxFor(m => m.UserName, new { placeholder = "請(qǐng)輸入登錄名" })
                            @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "error" })
                        </label>
                    </div>
                    <div class="form-group">
                        <label>
                            <span>密碼:</span>
                            @Html.PasswordFor(m => m.Password, new { placeholder = "請(qǐng)輸入密碼" })
                            @Html.ValidationMessageFor(m => m.Password, "", new { @class = "error" })
                        </label>
                    </div>
                    <div class="form-group">
                        <label>
                            <span>確認(rèn)密碼:</span>
                            @Html.PasswordFor(m => m.ConfirmPassword, new { placeholder = "請(qǐng)輸入確認(rèn)密碼" })
                            @Html.ValidationMessageFor(m => m.ConfirmPassword, "", new { @class = "error" })
                        </label>
                    </div>
                    <div class="form-group">
                        <button id="btn_register" type="submit">注 冊(cè)</button>
                        <a class="btn-login" href="~/account/login">登錄</a>
                    </div>
                }

            </div>
        </div>
    </div>
    <script src="~/Scripts/jquery-3.2.1.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
</body>
</html>

再在當(dāng)前文件夾下創(chuàng)建 login.cshtml 視圖文件用作登錄頁(yè)面:

@model TsBlog.ViewModel.User.LoginViewModel
@{
    Layout = null;
}
<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>用戶登錄</title>
    <style type="text/css">

        * { box-sizing: border-box; }
        body { box-sizing: border-box; margin: 0; padding: 0; color: #333; }

        .account-container { position: absolute; margin: auto; top: 0; right: 0; bottom: 0; left: 0; width: 400px; height: 450px; background-color: #fff; /*border-radius: 3px;*/ box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); }

        .account-signin-container { margin-top: 15px; }
            .account-signin-container h1 { font-size: 20px; border-bottom: 2px solid #f7f7f7; margin: 0 0 15px; padding-bottom: 10px; padding-left: 15px; letter-spacing: 0.1em; }
        .account-form { padding: 15px; }
            .account-form .form-group { width: 100%; margin-bottom: 15px; }
                .account-form .form-group label { width: 100%; display: block; }
                .account-form .form-group input { border: 1px solid #ccc; line-height: 32px; font-size: 16px; padding: 2px 0px; padding-left: 5px; display: block; width: 100%; margin-top: 5px; }
            .account-form #btn_login { border: 0; background: #3b78e7; color: #fff; font-size: 18px; font-weight: bold; padding: 8px 25px; cursor: pointer; margin-top: 15px; display: inline-block; box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.2); border-radius: 3px; min-width: 100px; text-align: center; }
                .account-form #btn_login:hover { background: #4885F3; }
        span.error { color: #f00; }
        .btn-register { float: right; display: block; margin-top: 25px; color: #4885f3; }

        @@media(max-width:500px) {
            .account-container { width: 100%; height: 100vh; }
        }
    </style>
</head>
<body>
    <div class="account-container">
        <div class="account-modal-container">
            <div class="modal"></div>
            <div class="load-bar-container">
                <div class="load-bar">
                    <div class="bar"></div>
                    <div class="bar"></div>
                    <div class="bar"></div>
                </div>
            </div>
            <div class="account-signin-container">
                <h1>用戶登錄</h1>
                @using (Html.BeginForm("login", "account", FormMethod.Post, new { @class = "account-form", role = "form" }))
                {
                    @Html.ValidationMessage("error_message", new { @class = "error" })
                    @Html.AntiForgeryToken()
                    <div class="form-group">
                        <label>
                            <span>登錄名:</span>
                            @Html.TextBoxFor(m => m.UserName, new { placeholder = "請(qǐng)輸入登錄名" })
                            @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "error" })
                        </label>
                    </div>
                    <div class="form-group">
                        <label>
                            <span>密碼:</span>
                            @Html.PasswordFor(m => m.Password, new { placeholder = "請(qǐng)輸入密碼" })
                            @Html.ValidationMessageFor(m => m.Password, "", new { @class = "error" })
                        </label>
                    </div>
                    <div class="form-group">
                        <button id="btn_login" type="submit">登 錄</button>
                        <a class="btn-register" href="~/account/register">注冊(cè)賬號(hào)</a>
                    </div>
                }

            </div>
        </div>
    </div>
    <script src="~/Scripts/jquery-3.2.1.min.js"></script>
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    <script src="~/res/assets/notie/notie.min.js"></script>
</body>
</html>

這兩個(gè)頁(yè)面均是響應(yīng)式的布局,可適應(yīng)不同設(shè)備。

好了,關(guān)于注冊(cè)和登錄的邏輯以及頁(yè)面都完成了,那么運(yùn)行項(xiàng)目,打開(kāi)注冊(cè)頁(yè)面:http://localhost:54739/account/register,具體的注冊(cè)請(qǐng)自行體驗(yàn):

create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-05.png
create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-05.png

注冊(cè)成功后,系統(tǒng)將帶你到登錄頁(yè)面:

create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-06.png
create-aspnet-mvc-5-web-application-repository-autofac-automapper-sqlsugar-step-by-step-08-06.png

具體功能也請(qǐng)自行體驗(yàn)。

以上,我們只完成了注冊(cè)和登錄的基本功能,接下來(lái)我們來(lái)體驗(yàn)一下簡(jiǎn)單的權(quán)限訪問(wèn),在本期教程之前,我們的: http://localhost:54739/home/index 以及 http://localhost:54739/home/post 是可以直接訪問(wèn)的,現(xiàn)在我們給這兩個(gè)頁(yè)面添加訪問(wèn)權(quán)限,即只有登錄后才能訪問(wèn),修改 HomeController.cs 如下:

using System.Web.Mvc;
using TsBlog.AutoMapperConfig;
using TsBlog.Services;

namespace TsBlog.Frontend.Controllers
{
    public class HomeController : Controller
    {
        private readonly IPostService _postService;
        public HomeController(IPostService postService)
        {
            _postService = postService;
        }
        public ActionResult Index()
        {
            //如果未登錄,則跳轉(zhuǎn)到登錄頁(yè)面
            if (Session["user_account"] == null)
            {
                return RedirectToAction("login", "account");
            }
            return View();
        }

        public ActionResult Post()
        {
            //如果未登錄,則跳轉(zhuǎn)到登錄頁(yè)面
            if (Session["user_account"] == null)
            {
                return RedirectToAction("login", "account");
            }

            var post = _postService.FindById(1).ToModel();
            return View(post);
        }
    }
}

重新編譯項(xiàng)目,按F5運(yùn)行,再打開(kāi)地址:http://localhost:54739/home/index ,發(fā)生了什么情況?
是不是被重定向到了登錄頁(yè)面,要求你登錄?
這就對(duì)了,輸入你剛才注冊(cè)的用戶名和密碼,登錄后,系統(tǒng)會(huì)重新帶你到:http://localhost:54739/home/index 頁(yè)面。

OK,今天這期的關(guān)于用戶注冊(cè)和登錄功能就介紹到這里,本期只實(shí)現(xiàn)了簡(jiǎn)單的功能,在后續(xù)的教程中將重構(gòu)和封裝相應(yīng)的功能代碼,敬請(qǐng)期待。。。

本期源碼托管地址:https://github.com/lampo1024/TsBlog/releases/tag/v1.8
數(shù)據(jù)庫(kù)腳本文件請(qǐng)到目錄下找:TsBlog\document\scripts\mysql\v1.8\

如果你喜歡Rector的本系列文章,請(qǐng)為我點(diǎn)個(gè)大大的贊。

看完教程如果覺(jué)得還不過(guò)癮的,遇到問(wèn)題的,想“勾對(duì)”的,歡迎加入圖享網(wǎng)官方QQ群:483350228。有什么,你懂的。。。

謝謝你的耐心閱讀,未完待續(xù),我們下期再見(jiàn)……

本文來(lái)源自 圖享網(wǎng) 《一步一步創(chuàng)建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](八)》

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容