• Layui+MVC+EF (项目从新创建开始)


    最近学习Layui ,就准备通过Layui来实现之前练习的项目,

    先创建一个新的Web 空项目,选MVC

    新建项目

    创建各种类库,模块之间添加引用,并安装必要Nuget包(EF包)

         模块名称            模块之间引用                    安装Nuget包


    BizLogic-------业务逻辑      (BizModel.DLL, DataEntity.DLL, Util.DLL)                      entityframework


    BizModel------实体类      


    DataEntity-----DB映射模块             (Util.DLL)                     entityframework 


    Util---------------公共类库


    Web--------------界面UI     (BizLogic.DLL, BizModel.DLL, DataEntity.DLL, Util.DLL)       entityframework

     创建并生成EF

      

     中小项目 可以直接关闭懒加载

     连接DB配置,移动到UI层

     下面编写公共方法

    DataResult.cs ------------通用数据结果类

    PagedResult.cs----------分页通过数据结果

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CarterHotel.Util
    {
        /// <summary>
        /// 通用数据结果类
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        public class DataResult<TModel>
        {
            /// <summary>
            /// 操作是否成功
            /// </summary>
            public bool IsSuccess { get; set; }
            /// <summary>
            /// 错误提示信息
            /// </summary>
            public string ErrorMessage { get; set; }
            /// <summary>
            /// 数据结果
            /// </summary>
            public TModel Data { get; set; }
    
            public DataResult()
            {
                IsSuccess = true;
            }
    
            public DataResult(string errorMessage)
            {
                IsSuccess = false;
                ErrorMessage = errorMessage;
            }
    
            public DataResult(TModel data)
            {
                IsSuccess = true;
                Data = data;
            }
        }
    }
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CarterHotel.Util
    {
        /// <summary>
        /// 分页通过数据结果
        /// </summary>
        public class PagedResult<TModel>:DataResult<TModel>//继承DataResult
        {
            /// <summary>
            /// 当前页索引
            /// </summary>
            public int PageIndex { get; set; }
            
            /// <summary>
            /// 每页记录条数
            /// </summary>
            public int PageSize { get; set; }
    
            /// <summary>
            /// 数据记录条数
            /// </summary>
            public int TotalCount { get; set; }
    
            /// <summary>
            /// 当前页数据
            /// </summary>
            public List<TModel> CurrentPageData { get; set; }
    
            public PagedResult(int pageIndex, int pageSize, int totalCount, List<TModel> currentPageData)
            {
                IsSuccess = true;
                PageIndex = pageIndex;
                TotalCount = totalCount;
                CurrentPageData = currentPageData;
            }
    
            public PagedResult(int totalCount, List<TModel> currentPageData)
            {
                IsSuccess = true;
                TotalCount = totalCount;
                CurrentPageData = currentPageData;
            }
        }
    }

    创建EncryptionMD5.cs 单向MD5加密

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Cryptography;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CarterHotel.Util
    {
        /// <summary>
        /// MD5
        /// 单向加密
        /// </summary>
        public class EncryptionMD5
        {
            /// <summary>
            /// 获得一个字符串的加密密文
            /// 此密文为单向加密,即不可逆(解密)密文
            /// </summary>
            /// <param name="plainText">待加密明文</param>
            /// <returns>已加密密文</returns>
            public static string EncryptString(string plainText)
            {
                return EncryptStringMD5(plainText);
            }
    
            /// <summary>
            /// 获得一个字符串的加密密文
            /// 此密文为单向加密,即不可逆(解密)密文
            /// </summary>
            /// <param name="plainText">待加密明文</param>
            /// <returns>已加密密文</returns>
            public static string EncryptStringMD5(string plainText)
            {
                MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
                byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(plainText));
                StringBuilder encryptText = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                {
                    encryptText.Append(data[i].ToString("x2"));
                }
                return encryptText.ToString();
    
            }
    
            /// <summary>
            /// 判断明文与密文是否相符
            /// </summary>
            /// <param name="plainText">待检查的明文</param>
            /// <param name="encryptText">待检查的密文</param>
            /// <returns>bool</returns>
            public static bool EqualEncryptString(string plainText, string encryptText)
            {
                return EqualEncryptStringMD5(plainText, encryptText);
            }
    
            /// <summary>
            /// 判断明文与密文是否相符
            /// </summary>
            /// <param name="plainText">待检查的明文</param>
            /// <param name="encryptText">待检查的密文</param>
            /// <returns>bool</returns>
            public static bool EqualEncryptStringMD5(string plainText, string encryptText)
            {
                bool result = false;
                if (string.IsNullOrEmpty(plainText) || string.IsNullOrEmpty(encryptText))
                    return result;
                result = EncryptStringMD5(plainText).Equals(encryptText);
                return result;
            }
        }
    }

     接下来对公共错误页面的编写

     在UI层新建StaticContent文件夹 并将下载好的Layui 样式 js 文件放到文件夹下,并添加对应的视图,异常处理过滤器

     下面 错误页面html代码

    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>错误提示</title>
        <link href="~/StaticContent/layui/css/layui.css" rel="stylesheet" />
        <style>
            .layadmin-tips {
                margin-top: 30px;
                text-align: center
            }
    
                .layadmin-tips .layui-icon[face] {
                    display: inline-block;
                    font-size: 300px;
                    color: #393D49;
                }
    
                .layadmin-tips .layui-text {
                    width: 500px;
                    margin: 30px auto;
                    padding-top: 20px;
                    border-top: 5px solid #009688;
                    font-size: 22px
                }
        </style>
    </head>
    <body>
        <div class="layui-fluid">
            <div class="layadmin-tips">
                <i class="layui-icon layui-icon-face-surprised" face></i>
                <div class="layui-text">好像出错了</div>
            </div>
        </div>
    </body>
    </html>

    增加异常处理过滤器 App_Start 新创建Filter-->HandleExceptionFileterAttribute类 并实现IExceptionFilter 接口; 

    2,在App_Start 下创建FilterConfig 过滤器配置类,并注册过滤器

     代码如下

    using CarterHotel.Util;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace CarterHotel.Web.App_Start.Filters
    {
        /// <summary>
        /// 异常处理过滤器
        /// </summary>
        public class HandleExceptionFileterAttribute : IExceptionFilter
        {
            public void OnException(ExceptionContext filterContext)
            {
                //判断当前的请求是否为ajax
                bool isAjaxRequest = filterContext.HttpContext.Request.IsAjaxRequest();
                if (isAjaxRequest)
                {
                    filterContext.Result = new JsonResult()
                    {
                        Data = new DataResult<string>(errorMessage: "系统发生错误")
                    };
                }
                else
                {
                    filterContext.Result = new RedirectResult(url: "/Error");
                }
    
                //异常发生后,进行处理以后,需要告诉应用程序,这个异常处理意见处理过了
                filterContext.ExceptionHandled = true;
            }
        }
    }

    注册过滤器

    using CarterHotel.Web.App_Start.Filters;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    
    namespace CarterHotel.Web.App_Start
    {
        /// <summary>
        /// 过滤器配置类
        /// </summary>
        public static class FilterConfig
        {
            /// <summary>
            /// 过滤器注册
            /// </summary>
            /// <param name="filters"></param>
            public static void RegisterFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleExceptionFileterAttribute());
            }
        }
    }

     控制器里增加Home控制器

     此时此刻公共错误页面已经完成,我们可以测试,公共错误页面是否有问题;

    JS文件

    StaticContent-->scripts-->unobtrusive.js(内容如下)

    layui.define(["jquery"], function (exports) {
        var jQuery = layui.jquery;
    
        (function ($) {
            var data_click = "unobtrusiveAjaxClick",
                data_target = "unobtrusiveAjaxClickTarget",
                data_validation = "unobtrusiveValidation";
    
            function getFunction(code, argNames) {
                var fn = window, parts = (code || "").split(".");
                while (fn && parts.length) {
                    fn = fn[parts.shift()];
                }
                if (typeof (fn) === "function") {
                    return fn;
                }
                argNames.push(code);
                return Function.constructor.apply(null, argNames);
            }
    
            function isMethodProxySafe(method) {
                return method === "GET" || method === "POST";
            }
    
            function asyncOnBeforeSend(xhr, method) {
                if (!isMethodProxySafe(method)) {
                    xhr.setRequestHeader("X-HTTP-Method-Override", method);
                }
            }
    
            function asyncOnSuccess(element, data, contentType) {
                var mode;
    
                if (contentType.indexOf("application/x-javascript") !== -1) {  // jQuery already executes JavaScript for us
                    return;
                }
    
                mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
                $(element.getAttribute("data-ajax-update")).each(function (i, update) {
                    var top;
    
                    switch (mode) {
                        case "BEFORE":
                            top = update.firstChild;
                            $("<div />").html(data).contents().each(function () {
                                update.insertBefore(this, top);
                            });
                            break;
                        case "AFTER":
                            $("<div />").html(data).contents().each(function () {
                                update.appendChild(this);
                            });
                            break;
                        case "REPLACE-WITH":
                            $(update).replaceWith(data);
                            break;
                        default:
                            $(update).html(data);
                            break;
                    }
                });
            }
    
            function asyncRequest(element, options) {
                var confirm, loading, method, duration;
    
                confirm = element.getAttribute("data-ajax-confirm");
                if (confirm && !window.confirm(confirm)) {
                    return;
                }
    
                loading = $(element.getAttribute("data-ajax-loading"));
                duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;
    
                $.extend(options, {
                    type: element.getAttribute("data-ajax-method") || undefined,
                    url: element.getAttribute("data-ajax-url") || undefined,
                    cache: !!element.getAttribute("data-ajax-cache"),
                    beforeSend: function (xhr) {
                        var result;
                        asyncOnBeforeSend(xhr, method);
                        result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments);
                        if (result !== false) {
                            loading.show(duration);
                        }
                        return result;
                    },
                    complete: function () {
                        loading.hide(duration);
                        getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
                    },
                    success: function (data, status, xhr) {
                        asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
                        getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments);
                    },
                    error: function () {
                        getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments);
                    }
                });
    
                options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
    
                method = options.type.toUpperCase();
                if (!isMethodProxySafe(method)) {
                    options.type = "POST";
                    options.data.push({ name: "X-HTTP-Method-Override", value: method });
                }
    
                $.ajax(options);
            }
    
            function validate(form) {
                var validationInfo = $(form).data(data_validation);
                return !validationInfo || !validationInfo.validate || validationInfo.validate();
            }
    
            $(document).on("click", "a[data-ajax=true]", function (evt) {
                evt.preventDefault();
                asyncRequest(this, {
                    url: this.href,
                    type: "GET",
                    data: []
                });
            });
    
            $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
                var name = evt.target.name,
                    target = $(evt.target),
                    form = $(target.parents("form")[0]),
                    offset = target.offset();
    
                form.data(data_click, [
                    { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
                    { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
                ]);
    
                setTimeout(function () {
                    form.removeData(data_click);
                }, 0);
            });
    
            $(document).on("click", "form[data-ajax=true] :submit", function (evt) {
                var name = evt.currentTarget.name,
                    target = $(evt.target),
                    form = $(target.parents("form")[0]);
    
                form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []);
                form.data(data_target, target);
    
                setTimeout(function () {
                    form.removeData(data_click);
                    form.removeData(data_target);
                }, 0);
            });
    
            $(document).on("submit", "form[data-ajax=true]", function (evt) {
                var clickInfo = $(this).data(data_click) || [],
                    clickTarget = $(this).data(data_target),
                    isCancel = clickTarget && clickTarget.hasClass("cancel");
                evt.preventDefault();
                if (!isCancel && !validate(this)) {
                    return;
                }
                asyncRequest(this, {
                    url: this.action,
                    type: this.method || "GET",
                    data: clickInfo.concat($(this).serializeArray())
                });
            });
        }(jQuery));
        exports('unobtrusive',null)
    });

    StaticContentimageuser.png 图片如下

    二, 实现基于layui前台页面后台管理的搭建

    1, 添加区域

    2, 在Shared-->_Layout.cshtml  (新增)

    3, Views-->_ViewStart.cshtml   (新增)

      _Layout.cshtml(下面增加的js需要在这里注册)

    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>后台管理</title>
        <link href="~/StaticContent/layui/css/layui.css" rel="stylesheet" />
        @RenderSection("styles",false)
    </head>
    <body>
        @RenderBody()
        <script src="~/StaticContent/layui/layui.js"></script>
        <script type="text/javascript">

    //js模块自定义,需要注意下

    layui.config({
    base: '/StaticContent/scripts/'
    }).extend({
    request: 'request',
    unobtrusive: 'unobtrusive'
    })

      

        </script>
        @RenderSection("scripts",false);
    </body>
    </html>

    _ViewStart.cshtml

    @{ 
    
        Layout = "~/Areas/Manage/Views/Shared/_Layout.cshtml";
    }

    在增加的区域里控制器增加Main控制器,并添加对应的视图及控制器

     视图代码

    <body class="layui-layout-body">
        <div class="layui-layout-admin">
            <!--头部内容-->
            <div class="layui-header">
                <div class="layui-logo">后台管理</div>
                <ul class="layui-nav layui-layout-right">
                    <li class="layui-nav-item">
                        <a href="#">
                            <img src="~/StaticContent/image/user.png" class="layui-nav-img" /> @View.UserName
                        </a>
                        <dl class="layui-nav-child">
                            <dd><a href="#">修改密码</a></dd>
                            <dd><a href="@Url.Action("LoginOut","Account")">退出登入</a></dd>
                        </dl>
                    </li>
                </ul>
            </div>
            <!--侧边导航-->
            <div class="layui-side layui-bg-black">
                <div class="layui-side-scroll">
                    <ul class="layui-nav layui-nav-tree">
                        <li class="layui-nav-item">
                            <a href="javascript:;">
                                <i class="layui-icon layui-icon-home">主页</i>
                            </a>
                        </li>
                    </ul>
                </div>
            </div>
            <!--主内容区-->
            <div class="layui-body" style="overflow:hidden">
                <iframe src="https://www.baidu.com/" frameborder="0" style="height:100%;100%"></iframe>
            </div>
            <!--底部区域-->
            <div class="layui-footer">
                ©1999-2020 个人开发
            </div>
        </div>
    </body>
    @section Scripts
    {
        <script type="text/javascript">
            layui.use('element')
        </script>
    }

    Main控制器代码如下,随便在web.config 增加 form授权认证

    using System.Web.Mvc;
    
    namespace CreateTest.Web.Areas.Manage.Controllers
    {
        public class MainController : Controller
        {
            // GET: Manage/Main
            [Authorize]
            public ActionResult Index()
            {
                ViewBag.UserName = HttpContext.User.Identity.Name;
                return View();
            }
    
            public ActionResult Main()
            {
                return View();
            }
        }
    }
    View Code

    运行测试,整个页面已经搭建了7788,运行页面如下

     主页面是用的度娘做的测试,下面我们创建Main页面

     Main页面增加,测试OK的

     到这里我们已经整个框架已经搭建的差不多了,下面将实现具体功能的实现,

    一, 实现登入功能

    1, 完成登入业务逻辑

    2, 完成 Account控制器登入(退出)功能

    3, 实现前台登入页面

    using CarterHotel.DataEntity;
    using CarterHotel.Util;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace CarterHotel.BizLogic.AdminManage
    {
        public class AccountService
        {
            /// <summary>
            /// 管理员登入
            /// </summary>
            /// <param name="saveEntity">账号密码</param>
            /// <returns></returns>
            public DataResult<SysAdmins> AdminLogin(SysAdmins saveEntity)
            {
                using (HotelDBConnection db = new HotelDBConnection())
                {
                    SysAdmins getEntity = db.SysAdmins.FirstOrDefault(a => a.LoginId == saveEntity.LoginId);
                    if (getEntity == null)
                    {
                        return new DataResult<SysAdmins>("用户不存在");
                    }
                    else
                    {
                        if (!EncryptionMD5.EqualEncryptStringMD5(saveEntity.LoginPwd,getEntity.LoginPwd))
                        {
                            return new DataResult<SysAdmins>("密码不正确");
                        }
                        else
                        {
                            return new DataResult<SysAdmins>(getEntity);
                        }
                    }
                }
            }
        }
    }
    View Code

     AccountController 控制器代码

    using CreateTest.BizLogic.AdminManage;
    using CreateTest.DataEntity;
    using CreateTest.Util.Result;
    using System.Web.Mvc;
    using System.Web.Security;
    
    namespace CreateTest.Web.Areas.Manage.Controllers
    {
        public class AccountController : Controller
        {
            private AccountService _accountService = new AccountService();
    
            // GET: Manage/Account
            /// <summary>
            /// 登入视图跳转
            /// </summary>
            /// <returns></returns>
            public ActionResult Login()
            {
                return View();
            }
            /// <summary>
            /// 用户登入
            /// </summary>
            /// <param name="sysAdmin"></param>
            /// <returns></returns>
            [HttpPost]
            public ActionResult Login(SysAdmin sysAdmin)
            {
               DataResult<SysAdmin> resultAdmin= _accountService.AdminLogin(sysAdmin);
                if (resultAdmin.IsSuccess)
                {
                    FormsAuthentication.SetAuthCookie(resultAdmin.Data.LoginName,true);
                }
                return Json(resultAdmin);
            }
    
            /// <summary>
            /// 退出登入
            /// </summary>
            /// <returns></returns>
            public ActionResult LoginOut()
            {
                FormsAuthentication.SignOut();
                return RedirectToAction("Login");
            }
        }
    }
    View Code

    Login.cshtml

    @model CreateTest.DataEntity.SysAdmin
    <div class="layadmin-user-login layadmin-user-display-show" id="LAY-user-login">
        <div class="layadmin-user-login-main">
            <div class="layadmin-user-login-box layadmin-user-login-header">
                <h2>管理系统</h2>
                <p>后台管理系统</p>
            </div>
            @using (Ajax.BeginForm("Login", "Account", FormMethod.Post, new AjaxOptions()
            {
                OnBegin = "OnAjaxBegin",
                OnFailure = "OnAjaxFailure",
                OnSuccess = "OnAjaxSuccess",
                OnComplete = "OnLoginComplete",
            }))
            {
                <div class="layadmin-user-login-box layadmin-user-login-body layui-form">
                    <div class="layui-form-item">
                        <label class="layadmin-user-login-icon layui-icon layui-icon-username" for="LoginId"></label>
                        @Html.TextBoxFor(a => a.LoginId, new Dictionary<string, object>()
                        {
                            { "class","layui-input"},
                            { "autocomplete","off"},
                            { "lay-verify","required"},
                            { "placeholder","请输入账号"}
                        })
                    </div>
                    <div class="layui-form-item">
                        <label class="layadmin-user-login-icon layui-icon layui-icon-password" for="LoginPwd"></label>
                        @Html.PasswordFor(a => a.LoginPwd, new Dictionary<string, object>()
                        {
                            { "class","layui-input"},
                            { "autocomplete","off"},
                            { "lay-verify","required"},
                            { "placeholder","请输入密码"}
                        })
                    </div>
                    <div class="layui-form-item">
                        <button class="layui-btn layui-btn-fluid" lay-submit>
                            登入
                        </button>
                    </div>
                </div>
            }
        </div>
    </div>
    
    @section Styles
    {
        <link href="~/StaticContent/css/login.css" rel="stylesheet" />
    }
    
    @section Scripts
    {
        <script type="text/javascript">
            layui.use(['form', 'unobtrusive', 'request'], function () {
                var request = layui.request;
                window.OnLoginComplete = function (response) {
                    debugger
                    var res = response.responseJSON;
                    request.handleResult(res, function () {
                        debugger
                        window.location.href = "/Manage/Main";
                    })
                }
            })
        </script>
    }
    View Code

    创建js文件,

    layui.define('layer', function (exports) {
        var layer = self === parent ? layui.layer : top.layui.layer;//判断是否为顶层页面
        var layerIndex;//定义加载层索引,因为加载层不会自动关闭
    
        //请求开始,开启弹窗
        window.OnAjaxBegin = function () {
            layerIndex = layer.load();
        }
    
        //请求失败时,提示错误信息
        window.OnAjaxFailure = function () {
            layer.close(layerIndex);
            layer.alert('请求错误', {
                title: '信息提示',
                icon: 2
            });
        }
    
        //请求完成时,关闭弹窗
        window.OnAjaxSuccess = function () {
            layer.close(layerIndex);
        }
    
        var instance = {
            //处理返回结果
            handleResult: function (res, success) {
                if (!res.IsSuccess) {
                    layer.alert(res.ErrorMessage, {
                        title: '信息提示',
                        icon: 2
                    });
                } else {
                    success && success(res.Data);
                }
            }
        }
    
        exports('request', instance)
    })
    View Code

     写到这里应该已经差不多了, 测试发现登入页面只会返回json数据,登入不成功的模态框无法出现,

    要将自定义的JS模块引入到_Layout.cshtml页面中

     再次测试,

     已经可以成功登入主页面

    本人也 不是太会排版, 附上下载地址:http://1.15.96.17:8011/TestWeb.zip

  • 相关阅读:
    32-数据链路层,PPP协议
    31-NAT
    30-安全技术,ACL
    ensp实验:配置DHCP
    29-应用层,DHCP协议
    ensp实验:配置stp
    28-STP,选举过程、端口状态、计时器、拓扑变化
    27-交换机,STP
    26-交换机,GVRP
    Manually APK Downgrade for split apks
  • 原文地址:https://www.cnblogs.com/victor-huang/p/13439698.html
Copyright © 2020-2023  润新知