MVC5 網站開發之六 管理員 2、添加、刪除、重置密碼、修改密碼、列表瀏覽


 

目錄

奔跑吧,代碼小哥!

MVC5網站開發之一 總體概述

MVC5 網站開發之二 創建項目

MVC5 網站開發之三 數據存儲層功能實現

MVC5 網站開發之四 業務邏輯層的架構和基本功能

MVC5 網站開發之五 展示層架構

MVC5 網站開發之六 管理員 1、登錄、驗證和注銷

MVC5 網站開發之六 管理員 2、添加、刪除、重置密碼、修改密碼、列表瀏覽

MVC5 網站開發之七 用戶功能 1、角色的后台管理

 

一、安裝插件。

展示層前端框架以Bootstrap為主,因為Bootstrap的js功能較弱,這里添加一些插件作補充。其實很多js插件可以通過NuGet安裝,只是NuGet安裝時添加的內容較多,不如自己復制來的干凈,所以這里所有的插件都是下載然后復制到項目中。

1、Bootstrap 3 Datepicker 4.17.37

網址:https://eonasdan.github.io/bootstrap-datetimepicker/

下載並解壓壓縮包->將bootstrap-datetimepicker.js和bootstrap-datetimepicker.min.js復制到Ninesy.Web項目的Scripts文件夾,將bootstrap-datetimepicker.css和bootstrap-datetimepicker.min.css復制到Content文件夾。

2、bootstrap-dialog 3.3.4.1

網址:https://github.com/nakupanda/bootstrap3-dialog

下載並解壓壓縮包->將.js復制到Ninesy.Web項目的Scripts文件夾,將.css復制到Content文件夾。

3、bootstrap-select  1.10.0

網址:http://silviomoreto.github.io/bootstrap-select/

下載並解壓壓縮包->將bootstrap-select.js復制到Ninesy.Web項目的Scripts文件夾,和defaults-zh_CN.js重命名為bootstrap-select-zh_CN.js復制到Ninesy.Web項目的Scripts文件夾,將bootstrap-select.css、bootstrap-select.css.map和bootstrap-select.min.css復制到Content文件夾。

4、bootstrap-table 1.10.1
網址:http://bootstrap-table.wenzhixin.net.cn/

下載並解壓壓縮包->將bootstrap-table.js和bootstrap-table-zh-CN.js復制到Ninesy.Web項目的Scripts文件夾,將bootstrap-table.css復制到Content文件夾。

5、Bootstrap TreeView 1.2.0

網址:https://github.com/jonmiles/bootstrap-treeview

下載並解壓壓縮包->將bootstrap-treeview.js復制到Ninesy.Web項目的Scripts文件夾,將bootstrap-treeview.css復制到Content文件夾。

 

6、twbs-pagination

網址:http://esimakin.github.io/twbs-pagination/

下載並解壓壓縮包->將jquery.twbsPagination.jsjquery.twbsPagination.min.js復制到Ninesy.Web項目的Scripts文件夾。

7、對js和css進行捆綁和壓縮

打開Ninesky.Web->App_Start->BundleConfig.cs。添加紅框內的代碼。

image

 

二、獲取ModelState錯誤信息的方法

在項目中有些內容是通過AJAX方法提交,如果提交時客戶端沒有進行驗證,在服務器端進行驗證時會將錯誤信息保存在ModelState中,這里需要寫一個方法來獲取ModelState的錯誤信息,以便反饋給客戶端。

1、Ninesk.Web【右鍵】->添加->類,輸入類名General。

引用命名空間using System.Web.MvcSystem.Text。

添加靜態方法GetModelErrorString(),該方法用來獲取模型的錯誤字符串。

using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace Ninesky.Web
{
    /// <summary>
    /// 通用類
    /// </summary>
    public class General
    {
        /// <summary>
        /// 獲取模型錯誤
        /// </summary>
        /// <param name="modelState">模型狀態</param>
        /// <returns></returns>
        public static string GetModelErrorString(ModelStateDictionary modelState)
        {
            StringBuilder _sb = new StringBuilder();
            var _ErrorModelState = modelState.Where(m => m.Value.Errors.Count() > 0);
            foreach(var item in _ErrorModelState)
            {
                foreach (var modelError in item.Value.Errors)
                {
                    _sb.AppendLine(modelError.ErrorMessage);
                }
            }
            return _sb.ToString();
        }
    }
}

 

三、完善布局頁

上次完成了管理員登錄,這次要進行登錄后的一些功能,要先把后台的布局頁充實起來。

打開 Ninesky.Web/Areas/Control/Views/_Layout.cshtml。整成下面的代碼。自己渣一樣的美工,具體過程就不寫了。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - 系統管理</title>
    @Styles.Render("~/Content//controlcss")
    @RenderSection("style", required: false)
    @Scripts.Render("~/bundles/modernizr")
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</head>
<body>
    <div class="navbar navbar-default navbar-fixed-top">
        <div class="container">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("NINESKY 系統管理", "Index", "Home", new { area = "Control" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                <ul class="nav navbar-nav">
                    <li><a><span class="glyphicon glyphicon-user"></span> 用戶管理</a></li>
                    <li><a href="@Url.Action("Index","Admin")"><span class='glyphicon glyphicon-lock'></span> 管理員</a></li>
                    <li><a><span class="glyphicon glyphicon-list"></span> 欄目設置</a></li>
                    <li><a><span class="glyphicon glyphicon-cog"></span> 網站設置</a></li>
                </ul>
                <ul class="nav navbar-nav navbar-right">
                    <li>
                        <a  href="@Url.Action("MyInfo","Admin")"><span class="glyphicon glyphicon-envelope"></span> @Context.Session["Accounts"].ToString()</a>

                    </li>
                    <li>
                        <a href="@Url.Action("Logout","Admin")"><span class="glyphicon glyphicon-log-out"></span> 退出</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>

    <div class="container body-content">
        <div class="row">
            <div class="col-lg-3 col-md-3 col-sm-4">@RenderSection("SideNav", false)</div>
            <div class="col-lg-9 col-md-9 col-sm-8">@RenderBody()</div>
        </div>
        <hr />
        <footer class="navbar navbar-fixed-bottom text-center bg-primary ">
            <p>&copy; Ninesky v0.1 BASE BY 洞庭夕照 http://mzwhj.cnblogs.com</p>
        </footer>
    </div>
</body>
</html>

image

反正效果就是這個樣子了。

三、功能實現

按照設想,要在Index界面完成管理員的瀏覽、添加和刪除功能。這些功能采用ajax方式。

在添加AdminController的時候自動添加了Index()方法。

添加Index視圖

在Index方法上右鍵添加視圖

image

@{
    ViewBag.Title = "管理員";
}

<ol class="breadcrumb">
    <li><span class="glyphicon glyphicon-home"></span>  @Html.ActionLink("首頁", "Index", "Home")</li>
    <li class="active">@Html.ActionLink("管理員", "Index", "Admin")</li>
</ol>

@section style{
    @Styles.Render("~/Content/bootstrapplugincss")
}

@section scripts{
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/bootstrapplugin")
    
}

添加側欄導航視圖

Ninesky.Web/Areas/Control/Views/Admin【右鍵】->添加->視圖

image

視圖代碼如下

<div class="panel panel-default">
    <div class="panel-heading">
        <div class="panel-title"><span class="glyphicon glyphicon-lock"></span> 管理員</div>
    </div>
    <div class="panel-body">
        <div class="list-group">
            <div class="list-group-item"><span class="glyphicon glyphicon-list"></span>  @Html.ActionLink("管理","Index")</div>
        </div>
    </div>
</div>

在Index視圖中添加@section SideNav{@Html.Partial("SideNavPartialView")}(如圖)

image

1、管理員列表

在Admin控制器中添加ListJson()方法

/// <summary>
        /// 管理員列表
        /// </summary>
        /// <returns></returns>
        public JsonResult ListJson()
        {
            return Json(adminManager.FindList());
        }

為在index中使用bootstrap-table顯示和操作管理員列表,在index視圖中添加下圖代碼。

<div id="toolbar" class="btn-group" role="group">
    <button id="btn_add" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> 添加</button>
    <button id="btn_del" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span> 刪除</button>
</div>
<table id="admingrid"></table>

在@section scripts{ } 中添加js代碼

<script type="text/javascript">

        $(document).ready(function () {

            //表格
            var $table = $('#admingrid');
            $table.bootstrapTable({
                toolbar: "#toolbar",
                showRefresh: true,
                showColumns: true,
                showFooter: true,
                method: "post",
                url: "@Url.Action("ListJson")",
                columns: [
                    { title: "state", checkbox: true },
                    { title: "ID", field: "AdministratorID" },
                    { title: "帳號", field: "Accounts" },
                    { title: "登錄時間", field: "LoginTime", formatter: function (value) { return moment(value).format("YYYY-MM-DD HH:mm:ss") } },
                    { title: "登錄IP", field: "LoginIP" },
                    { title: "創建時間", field: "CreateTime", formatter: function (value) { return moment(value).format("YYYY-MM-DD HH:mm:ss") } },
                    { title: "操作", field: "AdministratorID", formatter: function (value, row, index) { return "<a href=\"javascript:void(0)\" onclick=\"ResetPassword(" + value + ",'" + row.Accounts + "')\">重置密碼</a>" } }
                ]
            });
            //表格結束
        });
    </script>
}

顯示效果如圖:

image

2、添加管理員

在控制器中添加AddPartialView()方法

/// <summary>
        /// 添加【分部視圖】
        /// </summary>
        /// <returns></returns>
        public PartialViewResult AddPartialView()
        {
            return PartialView();
        }

Models文件夾【右鍵】->添加->類,輸入類名 AddAdminViewModel。

using System.ComponentModel.DataAnnotations;

namespace Ninesky.Web.Areas.Control.Models
{
    /// <summary>
    /// 添加管理員模型
    /// </summary>
    public class AddAdminViewModel
    {
        /// <summary>
        /// 帳號
        /// </summary>
        [Required(ErrorMessage = "必須輸入{0}")]
        [StringLength(30, MinimumLength = 4, ErrorMessage = "{0}長度為{2}-{1}個字符")]
        [Display(Name = "帳號")]
        public string Accounts { get; set; }

        /// <summary>
        /// 密碼
        /// </summary>
      [DataType(DataType.Password)]        
        [Required(ErrorMessage = "必須輸入{0}")]
        [StringLength(20,MinimumLength =6, ErrorMessage = "{0}長度少於{1}個字符")]
        [Display(Name = "密碼")]
        public string Password { get; set; }
    }
}

右鍵添加視圖

image

注意:抓圖的時候忘記勾上引用腳本庫了就抓了,記得勾上。

@model Ninesky.Web.Areas.Control.Models.AddAdminViewModel

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Accounts, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Accounts, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Accounts, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
            </div>
        </div>

    </div>
}
@Scripts.Render("~/bundles/jqueryval")

在Index視圖 script腳本區域,“//表格結束”后面添加js代碼

//表格結束
            //工具欄
            //添加按鈕
            $("#btn_add").click(function () {
                var addDialog = new BootstrapDialog({
                    title: "<span class='glyphicon glyphicon-plus'></span>添加管理員",
                    message: function (dialog) {
                        var $message = $('<div></div>');
                        var pageToLoad = dialog.getData('pageToLoad');
                        $message.load(pageToLoad);

                        return $message;
                    },
                    data: {
                        'pageToLoad': '@Url.Action("AddPartialView")'
                    },
                    buttons: [{
                        icon: "glyphicon glyphicon-plus",
                        label: "添加",
                        action: function (dialogItself) {
                            $.post($("form").attr("action"), $("form").serializeArray(), function (data) {
                                if (data.Code == 1) {
                                    BootstrapDialog.show({
                                        message: data.Message,
                                        buttons: [{
                                            icon: "glyphicon glyphicon-ok",
                                            label: "確定",
                                            action: function (dialogItself) {
                                                $table.bootstrapTable("refresh");
                                                dialogItself.close();
                                                addDialog.close();
                                            }
                                        }]

                                    });
                                }
                                else BootstrapDialog.alert(data.Message);
                            }, "json");
                            $("form").validate();
                        }
                    }, {
                        icon: "glyphicon glyphicon-remove",
                        label: "關閉",
                        action: function (dialogItself) {
                            dialogItself.close();
                        }
                    }]
                });
                addDialog.open();
            });
            //添加按鈕結束

image

3、刪除管理員

考慮到批量刪除,上次寫AdministratorManager沒有寫批量刪除方法,這次補上。

打開Ninesky.Core/AdministratorManager.cs, 添加如下代碼

/// <summary>
        /// 刪除【批量】返回值Code:1-成功,2-部分刪除,0-失敗
        /// </summary>
        /// <param name="administratorIDList"></param>
        /// <returns></returns>
        public Response Delete(List<int> administratorIDList)
        {
            Response _resp = new Response();
            int _totalDel = administratorIDList.Count;
            int _totalAdmin = Count();
            foreach (int i in administratorIDList)
            {
                if (_totalAdmin > 1)
                {
                    base.Repository.Delete(new Administrator() { AdministratorID = i }, false);
                    _totalAdmin--;
                }
                else _resp.Message = "最少需保留1名管理員";
            }
            _resp.Data = base.Repository.Save();
            if(_resp.Data == _totalDel)
            {
                _resp.Code = 1;
                _resp.Message = "成功刪除" + _resp.Data + "名管理員";
            }
            else if (_resp.Data > 0)
            {
                _resp.Code = 2;
                _resp.Message = "成功刪除" + _resp.Data + "名管理員";
            }
            else
            {
                _resp.Code = 0;
                _resp.Message = "刪除失敗";
            }
            return _resp;
        }

另外要修改一下Ninesky.DataLibrary.Repository的刪除public int Delete(T entity, bool isSave)代碼將Remove方式 改為Attach,不然會出錯。

/// <summary>
        /// 刪除實體
        /// </summary>
        /// <param name="entity">實體</param>
        /// <param name="isSave">是否立即保存</param>
        /// <returns>在“isSave”為True時返回受影響的對象的數目,為False時直接返回0</returns>
        public int Delete(T entity, bool isSave)
        {
            DbContext.Set<T>().Attach(entity);
            DbContext.Entry<T>(entity).State = EntityState.Deleted;
            return isSave ? DbContext.SaveChanges() : 0;
        }

打開AdminController 添加DeleteJson(List<int> ids)方法

/// <summary>
        /// 刪除 
        /// Response.Code:1-成功,2-部分刪除,0-失敗
        /// Response.Data:刪除的數量
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public JsonResult DeleteJson(List<int> ids)
        {
            int _total = ids.Count();
            Response _res = new Core.Types.Response();
            int _currentAdminID = int.Parse(Session["AdminID"].ToString());
            if (ids.Contains(_currentAdminID))
            {
                ids.Remove(_currentAdminID);
            }
            _res = adminManager.Delete(ids);
            if(_res.Code==1&& _res.Data < _total)
            {
                _res.Code = 2;
                _res.Message = "共提交刪除"+_total+"名管理員,實際刪除"+_res.Data+"名管理員。\n原因:不能刪除當前登錄的賬號";
            }
            else if(_res.Code ==2)
            {
                _res.Message = "共提交刪除" + _total + "名管理員,實際刪除" + _res.Data + "名管理員。";
            }
            return Json(_res);
        }

在Index視圖 script腳本區域,“//添加按鈕結束”后面添加刪除js代碼

//添加按鈕結束

            //刪除按鈕
            $("#btn_del").click(function () {
                var selected = $table.bootstrapTable('getSelections');
                if ($(selected).length > 0) {
                    BootstrapDialog.confirm("確定刪除選中的" + $(selected).length + "位管理員", function (result) {
                        if (result) {
                            var ids = new Array($(selected).length);
                            $.each(selected, function (index, value) {
                                ids[index] = value.AdministratorID;
                            });
                            $.post("@Url.Action("DeleteJson","Admin")", { ids: ids }, function (data) {
                                if (data.Code != 0) {
                                    BootstrapDialog.show({
                                        message: data.Message,
                                        buttons: [{
                                            icon: "glyphicon glyphicon-ok",
                                            label: "確定",
                                            action: function (dialogItself) {
                                                $table.bootstrapTable("refresh");
                                                dialogItself.close();
                                            }
                                        }]

                                    });
                                }
                                else BootstrapDialog.alert(data.Message);

                            }, "json");
                        }
                    });
                }
                else BootstrapDialog.warning("請選擇要刪除的行");
            });
            //刪除按鈕結束

4、重置密碼

在AdminController中 添加ResetPassword(int id)方法。方法中將密碼重置為Ninesky。

/// <summary>
        /// 重置密碼【Ninesky】
        /// </summary>
        /// <param name="id">管理員ID</param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult ResetPassword(int id)
        {
            string _password = "Ninesky";
            Response _resp = adminManager.ChangePassword(id, Security.SHA256(_password));
            if (_resp.Code == 1) _resp.Message = "密碼重置為:" + _password;
            return Json(_resp);
        }

在添加script代碼中表格代碼段可以看到,這里通過 連接的onclick調用ResetPassword方法,所以ResetPassword方法要放在表格生成前面,不然會出現 方法未定義的錯誤。

image

這里把代碼放到$(document).ready的前面。

<script type="text/javascript">        //重置密碼
        function ResetPassword(id, accounts) {
            BootstrapDialog.confirm("確定重置" + accounts + "的密碼", function (result) {
                if (result) {
                    $.post("@Url.Action("ResetPassword", "Admin")", { id: id }, function (data) {
                        BootstrapDialog.alert(data.Message);
                    }, "json");
                }
            });
        };
        //重置密碼結束

        $(document).ready(function () {

            //表格

5、修改管理員密碼

在在AdminController中 添加MyInfo()方法。

/// <summary>
        /// 我的資料
        /// </summary>
        /// <returns></returns>
        public ActionResult MyInfo()
        {
            return View(adminManager.Find(Session["Accounts"].ToString()));
        }

右鍵添加視圖

image

@model Ninesky.Core.Administrator

@{
    ViewBag.Title = "我的資料";
}

@section SideNav{@Html.Partial("SideNavPartialView")}

<ol class="breadcrumb">
    <li><span class="glyphicon glyphicon-home"></span>  @Html.ActionLink("首頁", "Index", "Home")</li>
    <li>@Html.ActionLink("管理員", "Index", "Admin")</li>
    <li class="active">我的資料</li>
</ol>
@Html.Raw(ViewBag.Message)
@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })

        <div class="form-group">
            @Html.LabelFor(model => model.Accounts, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DisplayTextFor(model => model.Accounts)

            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Password, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Password, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Password, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.LoginIP, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DisplayTextFor(model => model.LoginIP)
                
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.LoginTime, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DisplayTextFor(model => model.LoginTime)
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.CreateTime, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DisplayTextFor(model => model.CreateTime)
            </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>
}

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

在在AdminController中 添加處理方法MyInfo(FormCollection form)方法。

[ValidateAntiForgeryToken]
        [HttpPost]
        public ActionResult MyInfo(FormCollection form)
        {
            var _admin = adminManager.Find(Session["Accounts"].ToString());

            if (_admin.Password != form["Password"])
            {
                _admin.Password = Security.SHA256(form["Password"]);
                var _resp = adminManager.ChangePassword(_admin.AdministratorID, _admin.Password);
                if(_resp.Code ==1) ViewBag.Message = "<div class=\"alert alert-success\" role=\"alert\"><span class=\"glyphicon glyphicon-ok\"></span>修改密碼成功!</div>";
                else ViewBag.Message = "<div class=\"alert alert-danger\" role=\"alert\"><span class=\"glyphicon glyphicon-remove\"></span>修改密碼失敗!</div>";
            }
            return View(_admin);
        }

==========================================================

管理員功能到此寫完。感慨一下:時間太少,熬夜到凌晨真不容易!

代碼見:https://ninesky.codeplex.com/SourceControl/latest

代碼下載:https://ninesky.codeplex.com 點擊SOURCE CODE 點擊Download下載源文件。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM