MVC5 網站開發之七 用戶功能 2 用戶添加和瀏覽


目錄

MVC5網站開發之一 總體概述

MVC5 網站開發之二 創建項目

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

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

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

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

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

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

MVC5 網站開發之七 用戶功能 2 用戶添加和瀏覽

MVC5 網站開發之七 用戶功能 2 .1用戶資料的修改和刪除

 

 

一、數據存儲層

1、查找分頁列表

在寫用戶列表時遇到了問題,考慮到用戶可能會較多的情況需要分頁,在數據存儲層寫的方法是public IQueryable<T> FindPageList<TKey>(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, bool asc)。

主要問題就在紅色的order這兒,這個參數不好傳遞,比如:如果是已ID來排序哪TKey類型是int,如果以注冊時間來排序哪TKey類型就是datetime。如果我在業務邏輯層寫一個函數可以支持選擇排序類型,那么我沒有辦法聲明一個變量既可以存儲TKey為int的值,又可以存儲datetime的值,那么排序就要寫成下面這個樣子,感覺不舒服。

//排序
            switch(order)
            {
                case 0://ID升序
                    _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.UserID, true).ToList();
                    break;
                case 1://ID降序
                    _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.UserID, false).ToList();
                    break;
                case 2://注冊時間降序
                    _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.RegTime, true).ToList();
                    break;
                case 3://注冊時間升序
                    _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.RegTime, false).ToList();
                    break;
                case 4://最后登錄時間升序
                    _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.LastLoginTime, true).ToList();
                    break;
                case 5://最后登錄時間降序
                    _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.LastLoginTime, false).ToList();
                    break;
                default://ID降序
                    _users.Items = Repository.FindPageList((int)pageSize, (int)pageIndex, out _users.TotalNumber, _where, u => u.UserID, false).ToList();
                    break;
            }

后來將TKey設為dynamic類型,不論Expression<Func<T, dynamic>> order = u => u.UserID  或者u => u.RegTime都可以編譯通過,但是一運行就會出錯。

前幾天沒寫博客一直在考慮這個問題,后來還是換成用字符串的方式來動態排序。 步驟如下:

Ninesky.DataLibrary[右鍵]->添加->類,輸入類名OrderParam

namespace Ninesky.DataLibrary
{
    /// <summary>
    /// 排序參數
    /// </summary>
    public class OrderParam
    {
        /// <summary>
        /// 屬性名
        /// </summary>
        public string PropertyName { get; set; }

        /// <summary>
        /// 排序方式
        /// </summary>
        public OrderMethod Method { get; set; }
    }

    /// <summary>
    /// 排序方式
    /// </summary>
    public enum OrderMethod
    {
        /// <summary>
        /// 正序
        /// </summary>
        ASC,
        /// <summary>
        /// 倒序
        /// </summary>
        DESC
    }
}

打開Ninesky.DataLibrary/Repository.cs,將方法public IQueryable<T> FindPageList<TKey>(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, bool asc)的代碼修改為

/// <summary>
        /// 查找分頁列表
        /// </summary>
        /// <param name="pageSize">每頁記錄數。必須大於1</param>
        /// <param name="pageIndex">頁碼。首頁從1開始,頁碼必須大於1</param>
        /// <param name="totalNumber">總記錄數</param>
        /// <param name="where">查詢表達式</param>
        /// <param name="orderParams">排序【null-不設置】</param>
        public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, OrderParam[] orderParams)
        {
            if (pageIndex < 1) pageIndex = 1;
            if (pageSize < 1) pageSize = 10;
            IQueryable<T> _list = DbContext.Set<T>().Where(where);
            var _orderParames = Expression.Parameter(typeof(T), "o");
            if (orderParams != null && orderParams.Length > 0)
            {
                for (int i = 0; i < orderParams.Length; i++)
                {
                    //根據屬性名獲取屬性
                    var _property = typeof(T).GetProperty(orderParams[i].PropertyName);
                    //創建一個訪問屬性的表達式
                    var _propertyAccess = Expression.MakeMemberAccess(_orderParames, _property);
                    var _orderByExp = Expression.Lambda(_propertyAccess, _orderParames);
                    string _orderName = orderParams[i].Method == OrderMethod.ASC ? "OrderBy" : "OrderByDescending";
                    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), _orderName, new Type[] { typeof(T), _property.PropertyType }, _list.Expression, Expression.Quote(_orderByExp));
                    _list = _list.Provider.CreateQuery<T>(resultExp);
                }
            }
            totalNumber = _list.Count();
            return _list.Skip((pageIndex - 1) * pageIndex).Take(pageSize);
        }

方法中排序參數(OrderParam[]) 使用數組,是考慮到多級排序的情況。對FindPageList重載代碼進行修改,修改完的代碼如下:

//查找實體分頁列表
        #region FindPageList

        /// <summary>
        /// 查找分頁列表
        /// </summary>
        /// <param name="pageSize">每頁記錄數。必須大於1</param>
        /// <param name="pageIndex">頁碼。首頁從1開始,頁碼必須大於1</param>
        /// <param name="totalNumber">總記錄數</param>
        /// <returns></returns>
        public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber)
        {
            OrderParam _orderParam = null;
            return FindPageList(pageSize, pageIndex, out totalNumber, _orderParam);
        }

        /// <summary>
        /// 查找分頁列表
        /// </summary>
        /// <param name="pageSize">每頁記錄數。必須大於1</param>
        /// <param name="pageIndex">頁碼。首頁從1開始,頁碼必須大於1</param>
        /// <param name="totalNumber">總記錄數</param>
        /// <param name="order">排序鍵</param>
        /// <param name="asc">是否正序</param>
        /// <returns></returns>
        public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, OrderParam orderParam)
        {
            return FindPageList(pageSize, pageIndex, out totalNumber, (T)=> true, orderParam);
        }

        /// <summary>
        /// 查找分頁列表
        /// </summary>
        /// <param name="pageSize">每頁記錄數。必須大於1</param>
        /// <param name="pageIndex">頁碼。首頁從1開始,頁碼必須大於1</param>
        /// <param name="totalNumber">總記錄數</param>
        /// <param name="where">查詢表達式</param>
        public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where)
        {
            OrderParam _param = null;
            return FindPageList(pageSize, pageIndex, out totalNumber, where, _param);
        }

        /// <summary>
        /// 查找分頁列表
        /// </summary>
        /// <param name="pageSize">每頁記錄數。</param>
        /// <param name="pageIndex">頁碼。首頁從1開始</param>
        /// <param name="totalNumber">總記錄數</param>
        /// <param name="where">查詢表達式</param>
        /// <param name="orderParam">排序【null-不設置】</param>
        /// <returns></returns>
        public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, OrderParam orderParam)
        {
            OrderParam[] _orderParams = null;
            if (orderParam != null) _orderParams = new OrderParam[] { orderParam };
            return FindPageList(pageSize, pageIndex, out totalNumber, where, _orderParams);
        }

        /// <summary>
        /// 查找分頁列表
        /// </summary>
        /// <param name="pageSize">每頁記錄數。</param>
        /// <param name="pageIndex">頁碼。首頁從1開始</param>
        /// <param name="totalNumber">總記錄數</param>
        /// <param name="where">查詢表達式</param>
        /// <param name="orderParams">排序【null-不設置】</param>
        public IQueryable<T> FindPageList(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, OrderParam[] orderParams)
        {
            if (pageIndex < 1) pageIndex = 1;
            if (pageSize < 1) pageSize = 10;
            IQueryable<T> _list = DbContext.Set<T>().Where(where);
            var _orderParames = Expression.Parameter(typeof(T), "o");
            if (orderParams != null && orderParams.Length > 0)
            {
                for (int i = 0; i < orderParams.Length; i++)
                {
                    //根據屬性名獲取屬性
                    var _property = typeof(T).GetProperty(orderParams[i].PropertyName);
                    //創建一個訪問屬性的表達式
                    var _propertyAccess = Expression.MakeMemberAccess(_orderParames, _property);
                    var _orderByExp = Expression.Lambda(_propertyAccess, _orderParames);
                    string _orderName = orderParams[i].Method == OrderMethod.ASC ? "OrderBy" : "OrderByDescending";
                    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), _orderName, new Type[] { typeof(T), _property.PropertyType }, _list.Expression, Expression.Quote(_orderByExp));
                    _list = _list.Provider.CreateQuery<T>(resultExp);
                }
            }
            totalNumber = _list.Count();
            return _list.Skip((pageIndex - 1) * pageIndex).Take(pageSize);
        }

        #endregion

2、查找列表

基於分頁列表同樣的原因,對FindList方法也進行修改。

//查找實體列表
        #region FindList
        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <returns></returns>
        public IQueryable<T> FindList()
        {
            return DbContext.Set<T>();
        }

        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <param name="where">查詢Lambda表達式</param>
        /// <returns></returns>
        public IQueryable<T> FindList(Expression<Func<T, bool>> where)
        {
            return DbContext.Set<T>().Where(where);
        }

        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <param name="where">查詢Lambda表達式</param>
        /// <param name="number">獲取的記錄數量</param>
        /// <returns></returns>
        public IQueryable<T> FindList(Expression<Func<T, bool>> where, int number)
        {
            return DbContext.Set<T>().Where(where).Take(number);
        }

        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <param name="where">查詢Lambda表達式</param>
        /// <param name="orderParam">排序參數</param>
        /// <returns></returns>
        public IQueryable<T> FindList(Expression<Func<T, bool>> where, OrderParam orderParam)
        {
            return FindList(where, orderParam, 0);
        }

        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <param name="where">查詢Lambda表達式</param>
        /// <param name="orderParam">排序參數</param>
        /// <param name="number">獲取的記錄數量【0-不啟用】</param>
        public IQueryable<T> FindList(Expression<Func<T, bool>> where, OrderParam orderParam, int number)
        {
            OrderParam[] _orderParams = null;
            if (orderParam != null) _orderParams = new OrderParam[] { orderParam };
            return FindList(where, _orderParams, number);
        }

        /// <summary>
        /// 查找實體列表
        /// </summary>
        /// <param name="where">查詢Lambda表達式</param>
        /// <param name="orderParams">排序參數</param>
        /// <param name="number">獲取的記錄數量【0-不啟用】</param>
        /// <returns></returns>
        public IQueryable<T> FindList(Expression<Func<T, bool>> where, OrderParam[] orderParams, int number)
        {
            var _list = DbContext.Set<T>().Where(where);
            var _orderParames = Expression.Parameter(typeof(T), "o");
            if (orderParams != null && orderParams.Length > 0)
            {
                for (int i = 0; i < orderParams.Length; i++)
                {
                    //根據屬性名獲取屬性
                    var _property = typeof(T).GetProperty(orderParams[i].PropertyName);
                    //創建一個訪問屬性的表達式
                    var _propertyAccess = Expression.MakeMemberAccess(_orderParames, _property);
                    var _orderByExp = Expression.Lambda(_propertyAccess, _orderParames);
                    string _orderName = orderParams[i].Method == OrderMethod.ASC ? "OrderBy" : "OrderByDescending";
                    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), _orderName, new Type[] { typeof(T), _property.PropertyType }, _list.Expression, Expression.Quote(_orderByExp));
                    _list = _list.Provider.CreateQuery<T>(resultExp);
                }
            }
            if (number > 0) _list = _list.Take(number);
            return _list;
        }
        #endregion

二、業務邏輯層

1、用戶模型

Ninesky.Core【右鍵】->添加->類,輸入類名User

引用System.ComponentModel.DataAnnotations命名空間

using System;
using System.ComponentModel.DataAnnotations;

namespace Ninesky.Core
{
    /// <summary>
    /// 用戶模型
    /// </summary>
    public class User
    {
        [Key]
        public int UserID { get; set; }

        /// <summary>
        /// 角色ID
        /// </summary>
        [Required(ErrorMessage = "必須輸入{0}")]
        [Display(Name = "角色ID")]
        public int RoleID { get; set; }

        /// <summary>
        /// 用戶名
        /// </summary>
        [StringLength(50, MinimumLength = 4, ErrorMessage = "{0}長度為{2}-{1}個字符")]
        [Display(Name = "用戶名")]
        public string Username { get; set; }

        /// <summary>
        /// 名稱【可做昵稱、真實姓名等】
        /// </summary>
        [StringLength(20, ErrorMessage = "{0}必須少於{1}個字符")]
        [Display(Name = "名稱")]
        public string Name { get; set; }

        /// <summary>
        /// 性別【0-女,1-男,2-保密】
        /// </summary>
        [Required(ErrorMessage = "必須輸入{0}")]
        [Range(0,2,ErrorMessage ="{0}范圍{1}-{2}")]
        [Display(Name = "性別")]
        public int Sex { get; set; }

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

        /// <summary>
        /// Email
        /// </summary>
        [DataType(DataType.EmailAddress)]
        [StringLength(50, MinimumLength = 4, ErrorMessage = "{0}長度為{2}-{1}個字符")]
        [Display(Name = "Email")]
        public string Email { get; set; }

        /// <summary>
        /// 最后登錄時間
        /// </summary>
        [DataType(DataType.DateTime)]
        [Display(Name = "最后登錄時間")]
        public Nullable<DateTime> LastLoginTime { get; set; }


        /// <summary>
        /// 最后登錄IP
        /// </summary>
        [Display(Name = "最后登錄IP")]
        public string LastLoginIP { get; set; }

        /// <summary>
        /// 注冊時間
        /// </summary>
        [Required(ErrorMessage = "必須輸入{0}")]
        [Display(Name = "注冊時間")]
        public DateTime RegTime { get; set; }

        /// <summary>
        /// 角色
        /// </summary>
        public virtual Role Role { get; set; }

    }
}

用戶名、密碼和Email未設置成必填是考慮到,以后可以擴展QQ賬號、微博賬號等Owin方式登錄等功能,用Owin登錄的賬號不會有這幾個參數。對於用戶添加和注冊,可以寫一個視圖模型進行驗證。

2、添加表映射

打開Ninesky.Core/NineskyContext.cs,添加Users表映射(紅框部分)

image

3、更新數據表

在【工具欄】->【工具】->NuGet包管理器->程序包管理器控制台,運行命令Update-Database

4、用戶管理類

Ninesky.Core【右鍵】->添加->類,輸入類名UserManager,類繼承自BaseManager<User>

引用命名空間:using Ninesky.Core.Types; using Ninesky.DataLibrary;

因一般網站用戶的數量肯能要較多,在顯示用戶列表的時候要分頁顯示,在數據存儲層(Ninesky.DataLibrary)的Repository類中 public IQueryable<T> FindPageList<TKey>(int pageSize, int pageIndex, out int totalNumber, Expression<Func<T, bool>> where, Expression<Func<T, TKey>> order, bool asc)等分頁方法,方法參數where為Lambda表達式樹,在UserManager類的方法中我希望動態構造表達式樹,這里需要借助一個小工具LINQKit。

Ninesky.Core->引用【右鍵】->管理NuGet程序包。

image

在NuGet包管理器中搜索linqkit,安裝LinqKit最新版本。

在UserController中引用命名空間using LinqKit;

4.1 分頁列表

添加FindPageList方法,代碼如下:

/// <summary>
        /// 分頁列表
        /// </summary>
        /// <param name="pagingUser">分頁數據</param>
        /// <param name="roleID">角色ID</param>
        /// <param name="username">用戶名</param>
        /// <param name="name">名稱</param>
        /// <param name="sex">性別</param>
        /// <param name="email">Email</param>
        /// <param name="order">排序【null(默認)-ID降序,0-ID升序,1-ID降序,2-注冊時間降序,3-注冊時間升序,4-最后登錄時間升序,5-最后登錄時間降序】</param>
        /// <returns></returns>
        public Paging<User> FindPageList(Paging<User> pagingUser, int? roleID, string username, string name, int? sex, string email, int? order)
        {
            //查詢表達式
            var _where = PredicateBuilder.True<User>();
            if (roleID != null && roleID > 0) _where = _where.And(u => u.RoleID == roleID);
            if (!string.IsNullOrEmpty(username)) _where = _where.And(u => u.Username.Contains(username));
            if (!string.IsNullOrEmpty(name)) _where = _where.And(u => u.Name.Contains(name));
            if (sex != null && sex >= 0 && sex <= 2) _where = _where.And(u => u.Sex == sex);
            if (!string.IsNullOrEmpty(email)) _where = _where.And(u => u.Email.Contains(email));
            //排序
            OrderParam _orderParam;
            switch(order)
            {
                case 0://ID升序
                    _orderParam = new OrderParam() { PropertyName = "UserID", Method = OrderMethod.ASC };
                    break;
                case 1://ID降序
                    _orderParam = new OrderParam() { PropertyName = "UserID", Method = OrderMethod.DESC };
                    break;
                case 2://注冊時間降序
                    _orderParam = new OrderParam() { PropertyName = "RegTime", Method = OrderMethod.ASC };
                    break;
                case 3://注冊時間升序
                    _orderParam = new OrderParam() { PropertyName = "RegTime", Method = OrderMethod.DESC };
                    break;
                case 4://最后登錄時間升序
                    _orderParam = new OrderParam() { PropertyName = "LastLoginTime", Method = OrderMethod.ASC };
                    break;
                case 5://最后登錄時間降序
                    _orderParam = new OrderParam() { PropertyName = "LastLoginTime", Method = OrderMethod.DESC };
                    break;
                default://ID降序
                    _orderParam = new OrderParam() { PropertyName = "UserID", Method = OrderMethod.DESC };
                    break;
            }
            pagingUser.Items = Repository.FindPageList(pagingUser.PageSize,pagingUser.PageIndex, out pagingUser.TotalNumber, _where.Expand(),_orderParam).ToList();
            return pagingUser;
        }

4.2 判斷用戶名是否存在

添加HasUsername方法,代碼如下

/// <summary>
        /// 用戶名是否存在
        /// </summary>
        /// <param name="accounts">用戶名[不區分大小寫]</param>
        /// <returns></returns>
        public bool HasUsername(string username)
        {
            return base.Repository.IsContains(u => u.Username.ToUpper() == username.ToUpper());
        }

4.3判斷Email是否存在

添加HasEmail方法,代碼如下

/// <summary>
        /// Email是否存在
        /// </summary>
        /// <param name="email">Email[不區分大小寫]</param>
        /// <returns></returns>
        public bool HasEmail(string email)
        {
            return base.Repository.IsContains(u => u.Email.ToUpper() == email.ToUpper());
        }

4.4 添加用戶

因添加用戶時,賬號和Email不能重復所以添加前先判斷一下用戶名和密碼是否存在。這里用戶名為空時不進行判斷是因為考慮有可能以后使用可能用QQ等其他方式登錄。

/// <summary>
        /// 添加【返回值Response.Code:0-失敗,1-成功,2-賬號已存在,3-Email已存在】
        /// </summary>
        /// <param name="user">用戶</param>
        /// <returns></returns>
        public override Response Add(User user)
        {
            Response _resp = new Response();
            //賬號是否存在
            if (!string.IsNullOrEmpty(user.Username) && HasUsername(user.Username))
            {
                _resp.Code = 2;
                _resp.Message = "用戶名已存在";
            }
            //Email是否存在
            if (!string.IsNullOrEmpty(user.Email) && HasUsername(user.Email))
            {
                _resp.Code = 3;
                _resp.Message = "Email已存在";
            }
            if(_resp.Code == 0) _resp = base.Add(user);
            return _resp;
        }

三、展示層

Ninesky.Web/Areas/Control/Controllers【右鍵】->添加->控制器。選擇 MVC5 控制器 – 空, 輸入控制器名稱UserController。

在控制器中引入命名空間Ninesky.Core;(1)

為控制器添加身份驗證[AdminAuthorize](2)

添加變量private RoleManager roleManager = new RoleManager();(3)

image

1、用戶瀏覽

1.1、分頁列表方法

在UserController中添加方法PageListJson,返回Json格式的分頁數據。

 

/// <summary>
        /// 分頁列表【json】
        /// </summary>
        /// <param name="roleID">角色ID</param>
        /// <param name="username">用戶名</param>
        /// <param name="name">名稱</param>
        /// <param name="sex">性別</param>
        /// <param name="email">Email</param>
        /// <param name="pageIndex">頁碼</param>
        /// <param name="pageSize">每頁記錄數</param>
        /// <param name="order">排序</param>
        /// <returns>Json</returns>
        public ActionResult PageListJson(int? roleID, string username,string name,int? sex,string email,int? pageNumber, int? pageSize,int? order)
        {
            Paging<User> _pagingUser = new Paging<Core.User>();
            if (pageNumber != null && pageNumber > 0) _pagingUser.PageIndex = (int)pageNumber;
            if (pageSize != null && pageSize > 0) _pagingUser.PageSize = (int)pageSize;
            var _paging = userManager.FindPageList(_pagingUser, roleID, username, name, sex, email, null);
            return Json(new { total = _paging.TotalNumber, rows = _paging.Items });
        }

1.2、默認頁視圖

在UserController中添加Index方法

/// <summary>
        /// 默認頁
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            return View();
        }

在Index 方法上點右鍵 –>添加->視圖

image

@{
    ViewBag.Title = "用戶管理";
}

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

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

<table id="usergrid"></table>
@section style{
    @Styles.Render("~/Content/bootstrapplugincss")
}

@section scripts{
    @Scripts.Render("~/bundles/jqueryval")
    @Scripts.Render("~/bundles/bootstrapplugin")
    <script type="text/javascript">
        $(document).ready(function () {
            //表格
            var $table = $('#usergrid');
            $table.bootstrapTable({
                showRefresh: true,
                showColumns: true,
                pagination: true,
                sidePagination: "server",
                pageList:"[5, 10, 20, 50, 100]",
                method: "post",
                url: "@Url.Action("PageListJson")",
                columns: [
                    { title: "ID", field: "UserID" },
                    { title: "角色", field: "RoleID" },
                    { title: "用戶名", field: "Username" },
                    { title: "名稱", field: "Name", formatter: function (value, row, index) { return "<a href='@Url.Action("Modify", "User")/" + row.UserID + "'>" + value + "</a>" } },
                    { title: "性別", field: "Sex" },
                    { title: "Email", field: "Email", visible:false },
                    { title: "最后登錄時間", field: "LastLoginTime" },
                    { title: "最后登錄IP", field: "LastLoginIP", visible:false },
                    { title: "注冊時間", field: "RegTime",visible:false },
                    { title: "操作", field: "UserID", formatter: function (value) { return "<a class='btn btn-sm btn-danger' data-operation='deleteuser' data-value='" + value + "'>刪除</a>" } }
                ],
                onLoadSuccess: function () {
                    //刪除按鈕
                    //刪除按鈕結束
                }
            });
            //表格結束
        });
    </script>
}

1.3側導航局部視圖

Ninesky.Web/Areas/Control/Views/User【右鍵】->添加->視圖,輸入視圖名稱

image

<div class="panel panel-default">
    <div class="panel-heading">
        <div class="panel-title"><span class="glyphicon glyphicon-user"></span> 用戶管理</div>
    </div>
    <div class="panel-body">
        <div class="list-group">
            <div class="list-group-item"><span class="glyphicon glyphicon-plus"></span>  @Html.ActionLink("添加用戶", "Add", "User")</div>
            <div class="list-group-item"><span class="glyphicon glyphicon-list"></span>  @Html.ActionLink("用戶管理", "Index", "User")</div>
        </div>
    </div>
</div>

2、添加用戶

2.1 添加用戶視圖模型

Ninesky.Web/Areas/Control/Models【右鍵】->添加->“AddUserViewModel”

using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace Ninesky.Web.Areas.Control.Models
{
    /// <summary>
    ///  添加用戶視圖模型類
    /// </summary>
    public class AddUserViewModel
    {
        /// <summary>
        /// 角色ID
        /// </summary>
        [Required(ErrorMessage = "必須選擇{0}")]
        [Display(Name = "角色ID")]
        public int RoleID { get; set; }

        /// <summary>
        /// 用戶名
        /// </summary>
        [Remote("CanUsername","User",HttpMethod = "Post", ErrorMessage ="用戶名已存在")]
        [StringLength(50, MinimumLength = 4, ErrorMessage = "{0}長度為{2}-{1}個字符")]
        [Required(ErrorMessage = "必須輸入{0}")]
        [Display(Name = "用戶名")]
        public string Username { get; set; }

        /// <summary>
        /// 姓名【可做昵稱、真實姓名等】
        /// </summary>
        [StringLength(20, ErrorMessage = "{0}必須少於{1}個字符")]
        [Display(Name = "姓名")]
        public string Name { get; set; }

        /// <summary>
        /// 性別【0-女,1-男,2-保密】
        /// </summary>
        [Required(ErrorMessage = "必須選擇{0}")]
        [Range(0, 2, ErrorMessage = "{0}范圍{1}-{2}")]
        [Display(Name = "性別")]
        public int Sex { get; set; }

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

        /// <summary>
        /// 確認密碼
        /// </summary>
        [System.ComponentModel.DataAnnotations.Compare("Password",ErrorMessage ="兩次輸入的密碼不一致")]
        [DataType(DataType.Password)]
        [Display(Name = "確認密碼")]
        public string ConfirmPassword { get; set; }

        /// <summary>
        /// Email
        /// </summary>
        [Required(ErrorMessage = "必須輸入{0}")]
        [DataType(DataType.EmailAddress)]
        [Remote("CanEmail", "User",HttpMethod = "Post", ErrorMessage = "Email已存在")]
        [StringLength(50, MinimumLength = 4, ErrorMessage = "{0}長度為{2}-{1}個字符")]
        [Display(Name = "Email")]
        public string Email { get; set; }
    }
}

模型中使用到了遠程驗證(Remote)、屬性比較(Compare)等驗證方式。

2.2用戶名和Email遠程驗證方法

在UserController中添加CanUsername和CanEmail方法

/// <summary>
        /// 用戶名是否可用
        /// </summary>
        /// <param name="UserName">用戶名</param>
        /// <returns></returns> 
        [HttpPost]
        public JsonResult CanUsername(string UserName)
        {
            return Json(!userManager.HasUsername(UserName));
        }

        /// <summary>
        /// Email是否存可用
        /// </summary>
        /// <param name="Email">Email</param>
        /// <returns></returns> 
        [HttpPost]
        public JsonResult CanEmail(string Email)
        {
            return Json(!userManager.HasEmail(Email));
        }

2.3 添加用戶頁面

在UserController中添加Add方法

/// <summary>
        /// 添加用戶
        /// </summary>
        /// <returns></returns>
        public ActionResult Add()
        {
            //角色列表
            var _roles = new RoleManager().FindList();
            List<SelectListItem> _listItems = new List<SelectListItem>(_roles.Count());
            foreach(var _role in _roles)
            {
                _listItems.Add(new SelectListItem() { Text = _role.Name, Value = _role.RoleID.ToString() });
            }
            ViewBag.Roles = _listItems;
            //角色列表結束
            return View();
        }

方法中向視圖傳遞角色列表ViewBag.Roles

右鍵添加視圖

image

代碼如下:

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

@{
    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", "User")</li>
    <li class="active">@Html.ActionLink("添加用戶", "Add", "User")</li>
</ol>
@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()
    
    <div class="form-horizontal">
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.RoleID, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.DropDownListFor(model => model.RoleID, (IEnumerable<SelectListItem>)ViewBag.Roles, new { @class = "form-control" });
                @Html.ValidationMessageFor(model => model.RoleID, "", new { @class = "text-danger" })
            </div>
        </div>

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

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

        <div class="form-group">
            @Html.LabelFor(model => model.Sex, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.RadioButtonFor(model => model.Sex, 1) 男
                @Html.RadioButtonFor(model => model.Sex, 0) 女
                @Html.RadioButtonFor(model => model.Sex, 2) 保密
                
                @Html.ValidationMessageFor(model => model.Sex, "", 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 class="form-group">
            @Html.LabelFor(model => model.ConfirmPassword, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.ConfirmPassword, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.ConfirmPassword, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.Email, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Email, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.Email, "", new { @class = "text-danger" })
            </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>
}
@Scripts.Render("~/bundles/jqueryval")
 

2.4添加處理方法

UserController中添加Add(AddUserViewModel userViewModel)方法

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Add(AddUserViewModel userViewModel)
        {
            if (userManager.HasUsername(userViewModel.Username)) ModelState.AddModelError("Username","用戶名已存在");
            if (userManager.HasEmail(userViewModel.Email)) ModelState.AddModelError("Email", "Email已存在");
            if (ModelState.IsValid)
            {
                Core.User _user = new Core.User();
                _user.RoleID = userViewModel.RoleID;
                _user.Username = userViewModel.Username;
                _user.Name = userViewModel.Name;
                _user.Sex = userViewModel.Sex;
                _user.Password = Core.General.Security.SHA256(userViewModel.Password);
                _user.Email = userViewModel.Email;
                _user.RegTime = System.DateTime.Now;
                var _response = userManager.Add(_user);
                if (_response.Code == 1) return View("Prompt",new Prompt() { Title="添加用戶成功",
                 Message="您已成功添加了用戶【"+ _response.Data.Username+ ""+ _response.Data.Name + ")】",
                 Buttons= new List<string> {"<a href=\"" + Url.Action("Index", "User") + "\" class=\"btn btn-default\">用戶管理</a>",
                 "<a href=\"" + Url.Action("Details", "User",new { id= _response.Data.UserID }) + "\" class=\"btn btn-default\">查看用戶</a>",
                 "<a href=\"" + Url.Action("Add", "User") + "\" class=\"btn btn-default\">繼續添加</a>"} });
                else ModelState.AddModelError("", _response.Message);
            }
            //角色列表
            var _roles = new RoleManager().FindList();
            List<SelectListItem> _listItems = new List<SelectListItem>(_roles.Count());
            foreach (var _role in _roles)
            {
                _listItems.Add(new SelectListItem() { Text = _role.Name, Value = _role.RoleID.ToString() });
            }
            ViewBag.Roles = _listItems;
            //角色列表結束

            return View(userViewModel);
        }

 

2.5添加成功提示

UserController中[右鍵]添加視圖-Prompt

image

@model Ninesky.Web.Models.Prompt

@{
    ViewBag.Title = "提示";
}

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

<ol class="breadcrumb">
    <li><span class="glyphicon glyphicon-home"></span>  @Html.ActionLink("首頁", "Index", "Home")</li>
    <li class="active"> @Html.ActionLink("用戶管理", "Index", "User")</li>
</ol>
@Html.Partial("PromptPartialView", Model)

2.6 添加提示消息局部視圖

Ninesky.Web/Areas/Control/Views/Shared【右鍵】->添加->視圖。視圖名為PromptPartialView。

image

代碼如下:

@model Ninesky.Web.Models.Prompt

<div class="panel panel-default">
    <div class="panel-heading"><div class="panel-title">@Model.Title</div></div>
    <div class="panel-body">
        <p>@Html.Raw(Model.Message)</p>
        @if (Model.Buttons != null && Model.Buttons.Count > 0)
        {
            <p>
                @foreach (var item in Model.Buttons)
                {
                    @Html.Raw(item + "&nbsp;&nbsp;")

                }
            </p>
        }
    </div>
</div>

 

運行效果

image

image

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

前幾天就忙完了,中間休息了一下,順便調整一下狀態。

由於代碼20多天前些了一部分,到現在有些忘記當時的想法了,今天又寫了一些感覺銜接不好,有點亂。


免責聲明!

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



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