ASP.Net Core Razor+AdminLTE 小试牛刀
AdminLTE
一个基于 bootstrap 的轻量级后台模板,这个前端界面个人感觉很清爽,对于一个大后端的我来说,可以减少较多的时间去承担前端的工作但又必须去独立去完成一个后台系统开发的任务,并且,文档还算比较齐全,对着demo可以完成一个基本的前端框架搭建了。大家如有更为好看的又方便后端上手的前端框架,也可以在留言区分享一下呗。
AdminLTE 文档
在线中文Demo:http://adminlte.la998.com/
在线中文文档:http://adminlte.la998.com/documentation/index.html
Github:https://github.com/almasaeed2010/AdminLTE/releases
AdminLTE 布局
AdminLTE依赖于两个主要框架:JQ和Bootstrap,其他插件可以按需增加。
从文档可以知道,使用AdminLTE主要有四个部分:
- 包装
.wrapper
。包裹整个网站的div。 - 主标题
.main-header
。包含徽标和导航栏。 - 边栏
.sidebar-wrapper
。包含用户面板和侧边栏菜单。 - 内容
.content-wrapper
。包含页眉和内容。
在文档中,可以找到下载地址,本文示例是使用最新的版本V2.4.5。
Asp.Net Core Razor
新建项目Asp.net Core Web应用程序,默认就是Razor Pages,然后添加相应的模块,如图:本文使用的SDK版本为:dotNet Core 2.1。
First
在Asp.Net Core项目中,引用AdminLTE,在wwwroot仅添加如图三个文件夹即可:
- bower_components 基本组件。
- dist adminlte的主要文件。
- plugins 其他插件。
Second
在_Layout.cshtml文件中添加引入相关文件:
- <!-- Tell the browser to be responsive to screen width -->
- <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
- <!-- Bootstrap 3.3.7 -->
- <link rel="stylesheet" href="~/adminlte/bower_components/bootstrap/dist/css/bootstrap.min.css">
- <!-- Font Awesome -->
- <link rel="stylesheet" href="~/adminlte/bower_components/font-awesome/css/font-awesome.min.css">
- <!-- Ionicons -->
- <link href="~/adminlte/bower_components/Ionicons/css/ionicons.min.css" rel="stylesheet" />
- <!-- Theme style -->
- <link rel="stylesheet" href="~/adminlte/dist/css/AdminLTE.min.css">
- <!-- AdminLTE Skins. Choose a skin from the css/skins
- folder instead of downloading all of them to reduce the load. -->
- <link rel="stylesheet" href="~/adminlte/dist/css/skins/_all-skins.min.css">
- <!-- Pace style -->
- <link href="~/adminlte/plugins/pace/pace.min.css" rel="stylesheet" />
- <link href="~/css/common.css" rel="stylesheet" />
- <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
- <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
- <!--[if lt IE 9]>
- <script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
- <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
- <![endif]-->
- <!-- Google Font -->
- <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,300italic,400italic,600italic">
在body中,添加js:
- <!-- jQuery 3 -->
- <script src="~/adminlte/bower_components/jquery/dist/jquery.min.js"></script>
- <!-- jQuery UI 1.11.4 -->
- <script src="~/adminlte/bower_components/jquery-ui/jquery-ui.min.js"></script>
- <!-- Resolve conflict in jQuery UI tooltip with Bootstrap tooltip -->
- <script>
- $.widget.bridge('uibutton', $.ui.button);
- </script>
- <!-- Bootstrap 3.3.7 -->
- <script src="~/adminlte/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
- <!-- Slimscroll -->
- <script src="~/adminlte/bower_components/jquery-slimscroll/jquery.slimscroll.min.js"></script>
- <!-- FastClick -->
- <script src="~/adminlte/bower_components/fastclick/lib/fastclick.js"></script>
- <!-- AdminLTE App -->
- <script src="~/adminlte/dist/js/adminlte.min.js"></script>
- <!-- Skin -->
- <script type="text/javascript" src="~/adminlte/dist/js/sidebarskins.js" charset="gbk"></script>
sidebarskins.js是本人汉化的侧边栏皮肤
坑1:一般情况,发现某些功能运行不起来的都是引用不正确导致的,这个要耐心对照好Demo来检查,或者直接用Demo来修改吧。
Third
开始使用AdminLTE,这里直接贴图吧,图上有注释和代码折叠比较直观点,重要的地方在放代码。
最后就可以运行项目来预览一下效果了:
都使用到bootstrap,必须得看看移动端的效果,还不错吧。
坑2:需要注意的是,点击这个小图标可以实现左侧边栏收缩展开的功能,当只有侧边栏可以正常收缩展开但Logo无动于衷的时候,你可能是少了【sidebar-mini】样式和【logo-mini】logo小图的引用
添加一个登陆
登录界面写得比较简约,我比较喜欢这种风格。前端写得不多,所以还得前端的女票指导一二,不然就是后端的设计的界面了,你懂的。
在Pages文件夹中,添加一个Razor界面,并撸好界面代码:
- @page
- @model AdminLTE.Net.Web.Pages.LoginModel
- @{
- Layout = null;
- }
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>登录 - AdminLTE.Net.Web</title>
- <meta name="developer" content="EminemJK">
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet" />
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap-theme.min.css" rel="stylesheet" />
- <link href="~/adminlte/dist/css/AdminLTE.min.css" rel="stylesheet" />
- <link href="~/css/login.css" rel="stylesheet" />
- </head>
- <body>
- <div>
- <div class="row">
- <div class="loginHeader">
- <img class="logo-img" src="~/images/banana_logo.ico" />
- <h1 class="logo-name">Banana</h1>
- <div class="clearfix"></div>
- </div>
- </div>
- <div class="row login-bg">
- <div class="loginInBox">
- @if (!string.IsNullOrEmpty(Model.Message))
- {
- <p class="login-box-msg" style="color:red">@Model.Message</p>
- }
- else
- {
- <p class="login-box-msg">Sign in to start your session</p>
- }
- <form method="post">
- <div class="form-group has-feedback">
- <input type="text" class="form-control" asp-for="Login.UserName">
- <span class="glyphicon glyphicon-user form-control-feedback"></span>
- </div>
- <div class="form-group has-feedback">
- <input type="password" class="form-control" asp-for="Login.Password">
- <span class="glyphicon glyphicon-lock form-control-feedback"></span>
- </div>
- <button type="submit" class="btn btn-primary btn-block btn-flat login-btn">Sign In</button>
- </form>
- </div>
- </div>
- </div>
- <footer class="footer">
- <strong>Copyright © 2018 <a href="http://www.cnblogs.com/EminemJK/">EminemJK</a>.</strong> All rights reserved.
- </footer>
- </body>
- </html>
在Startup中引入Authentication身份验证:
- services.AddAuthentication(CookieService.AuthenticationScheme)
- .AddCookie(CookieService.AuthenticationScheme, o =>
- {
- o.LoginPath = new PathString("/Login");
- });
Configure方法内调用
- app.UseAuthentication();
在Login.cshtml.cs中增加一个OnPostAsync的方法:
- [HttpPost]
- public async Task<IActionResult> OnPostAsync()
- {
- if (!ModelState.IsValid)
- {
- Message = ModelState.Root.Errors[].ErrorMessage;
- }
- else
- {
- var user = userService.Login(Login.UserName, Login.Password);
- if (user != null)
- {
- VUserModel model = new VUserModel()
- {
- Id = user.Id,
- UserName = user.UserName,
- Time = DateTime.Now
- };
- var identity = new ClaimsIdentity(CookieService.AuthenticationScheme);
- identity.AddClaim(new Claim(ClaimTypes.Sid, CookieService.GetDesEncrypt(model)));
- await HttpContext.SignInAsync(CookieService.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties()
- {
- //记住我
- IsPersistent = true,
- //过期时间
- ExpiresUtc = DateTimeOffset.Now.Add(TimeSpan.FromMinutes())
- });
- return RedirectToPage("./Index");
- }
- Message = "登录失败,用户名密码不正确。";
- }
- return Page();
- }
- userService和CookieService都是在业务层定义的,gayhub会在文章末尾。
在.Net Core Razor中,xx.cshtml.cs中默认触发的是Get和Post方法,
- OnGet
- OnPost
- OnGetAsync
- OnPostAsync
如果是需要自定义的,举个栗子,定义为:OnPostLoginAsync,然后在Form表单提交的【按钮】增加asp-page-handler="Login",详细的推荐大家阅读这篇文章:ASP.NET Core - Razor页面之Handlers处理方法。
接着,然后再Index和需要身份验证的地方都加上Authorize特性即可:
- namespace AdminLTE.Net.Web.Pages
- {
- [Authorize(AuthenticationSchemes = CookieService.AuthenticationScheme)]
- public class IndexModel : BasePageModel
- {
- public void OnGet()
- {
- }
- }
- }
踩坑
一、Ajax Post请求, 400 Bad Request
- function uploadfile() {
- var file = $("#input-userimg")[0].files[0];
- var data = new FormData();
- data.append('file', file);
- $.ajax({
- url: "/Account/UserList?handler=Upload",
- type: 'POST',
- data: data,
- contentType: false,
- processData: false,
- success: function (returndata) {
- $("#user-img").attr('src', returndata.path);
- },
- error: function (a, b, c) {
- alert('上传失败')
- }
- });
- };
折腾许久,原因是Razor被设计为可以自动防止跨站请求伪造(CSRF / XSRF)攻击。你不必编写任何其他代码。Razor页面中自动包含防伪令牌生成和验证。这里请求失败,是因为POST没有提交AntiForgeryToken。
解决方法:
1.增加"XSRF-TOKEN"标识到框架中
- //增加了"XSRF-TOKEN"标识,值为表单自动生成的防伪标记
- services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
2.页面*.cshtml头部加上
- @Html.AntiForgeryToken()
3.ajax引入
- function uploadfile() {
- var file = $("#input-userimg")[0].files[0];
- var data = new FormData();
- data.append('file', file);
- $.ajax({
- url: "/Account/UserList?handler=Upload",
- type: 'POST',
- data: data,
- contentType: false,
- processData: false,
- beforeSend: function (xhr) {
- xhr.setRequestHeader("XSRF-TOKEN",
- $('input:hidden[name="__RequestVerificationToken"]').val());
- },
- success: function (returndata) {
- $("#user-img").attr('src', returndata.path);
- },
- error: function (a, b, c) {
- alert('上传失败')
- }
- });
- };
然后既可以正常访问Handler
二、DataTables参数实例加说明
- var table = $('#userListTable').DataTable({
- "processing": true,
- "serverSide": true,
- "ajax": function (data, callback, settings) {
- //data的参数请参考: https://segmentfault.com/a/1190000004478726
- var param = {};
- param.draw = data.draw;
- param.pageNum = (data.start / data.length) + 1;
- param.pageSize = data.length;
- param.sex = $('#select-sex option:selected').val();
- param.phone = $('#input-phone').val();
- param.name = $('#input-name').val();
- $.ajax({
- type: "GET",
- data: param,
- url: "/Account/UserList?handler=UserPage",
- dataType: "json",
- success: function (data) {
- //成功后回调自动渲染
- callback(data);
- }
- });
- },
- 'columns': [
- { 'data': 'id' },
- { 'data': 'name' },
- { 'data': 'userName' },
- { 'data': 'sexString' },
- { 'data': 'phone' },
- { 'data': 'createTime' },
- {
- 'data': 'enableString',
- 'render': function (data, type, row) {
- if (row.enable == 1)
- return '<span style="color:#19be6b" >' + row.enableString + '</span>';
- else
- return '<span style="color:#ed3f14" >' + row.enableString + '</span>';
- }
- },
- {
- 'data': null,
- 'render': function (data, type, row) {
- return '<a id="btn-edit" class="btn btn-success btn-xs" title="编辑" onClick=btn_edit(' + row.id + ')><i class="fa fa-edit"></i>编辑</a> ' +
- '<a id="btn-edit" class="btn btn-danger btn-xs" title="删除" onClick=btn_edit(' + row.id + ')><i class="fa fa-trash " title="删除" style="cursor:pointer"></i>删除</a>';
- }
- },
- ],
- //datatable设置参数 http://www.datatables.club/reference/option/
- 'paging': true, //启用分页
- 'lengthChange': true, //设置每页数量
- 'searching': false,
- 'ordering': false,
- 'info': true,
- 'autoWidth': false,
- //设置中文
- 'language': {
- "sProcessing": "玩命加载中...",
- "sLengthMenu": "每页显示显示 _MENU_",
- "sZeroRecords": "没有匹配结果",
- "sInfo": "显示第 _START_ 至 _END_ 项结果,共 _TOTAL_ 项",
- "sInfoEmpty": "显示第 0 至 0 项结果,共 0 项",
- "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
- "sInfoPostFix": "",
- "sSearch": "搜索:",
- "sUrl": "",
- "sEmptyTable": "表中数据为空",
- "sLoadingRecords": "玩命加载中...",
- "sInfoThousands": ",",
- "oPaginate": {
- "sFirst": "首页",
- "sPrevious": "上页",
- "sNext": "下页",
- "sLast": "末页"
- },
- "oAria": {
- "sSortAscending": ": 以升序排列此列",
- "sSortDescending": ": 以降序排列此列"
- }
- }
- });
Last
附上这些天来的成果,发现,我并不适合写前端,太丑了,哈哈。
最后,Show me the code。
Banana
Demo中会使用到这两个个人封装的组件:
Banana.Uow是基于Dapper封装的工作单元和仓储;
Banana.Utility是常用的工具类,有Redis,加解密,拼音等等;
欢迎大家在Issues中提出意见,大家共同进步。
本文已独家授权给脚本之家(ID:jb51net)公众号发布
ASP.Net Core Razor+AdminLTE 小试牛刀的更多相关文章
- C# -- HttpWebRequest 和 HttpWebResponse 的使用 C#编写扫雷游戏 使用IIS调试ASP.NET网站程序 WCF入门教程 ASP.Net Core开发(踩坑)指南 ASP.Net Core Razor+AdminLTE 小试牛刀 webservice创建、部署和调用 .net接收post请求并把数据转为字典格式
C# -- HttpWebRequest 和 HttpWebResponse 的使用 C# -- HttpWebRequest 和 HttpWebResponse 的使用 结合使用HttpWebReq ...
- ASP.NET Core - Razor 页面简介
简介 随着ASP.NET Core 2 即将来临,最热门的新事物是Razor页面.在之前的一篇文章中,我们简要介绍了ASP.NET Core Razor 页面. Razor页面是ASP.NET Cor ...
- ASP.NET Core - Razor页面之Handlers处理方法
简介 在前一篇文章中,我们讨论了Razor页面.今天我们来谈谈处理方法(Handlers). 我们知道可以将代码和模型放在 .cshtml 文件里面或与 .cshtml 匹配的 .cshtml.cs ...
- ASP.NET Core Razor中处理Ajax请求
如何ASP.NET Core Razor中处理Ajax请求 在ASP.NET Core Razor(以下简称Razor)刚出来的时候,看了一下官方的文档,一直没怎么用过.今天闲来无事,准备用Rozor ...
- ASP.NET Core Razor页面禁用防伪令牌验证
在这篇短文中,我将向您介绍如何ASP.NET Core Razor页面中禁用防伪令牌验证. Razor页面是ASP.NET Core 2.0中增加的一个页面控制器框架,用于构建动态的.数据驱动的网站: ...
- ASP.NET Core Razor 页面使用指南
ASP.NET Core Razor 页面作为 ASP.NET Core 2.0的一部分发布,它是基于页面的全新的Web开发框架.如果您想学习如何使用 ASP.NET Core Razor 页面,可以 ...
- 学习ASP.NET Core Razor 编程系列一
一. 概述 .NET Core 1.0发布的时候就想进行学习的,不过根据微软的以往的发布规律1.0版可以认为是大众测试版,2.0才算稳定.现在2.1都已经发布了预览版,之前对其"不稳定&qu ...
- 学习ASP.NET Core Razor 编程系列二——添加一个实体
在Razor页面应用程序中添加一个实体 在本篇文章中,学习添加用于管理数据库中的书籍的实体类.通过实体框架(EF Core)使用这些类来处理数据库.EF Core是一个对象关系映射(ORM)框架,它简 ...
- 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面
学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...
随机推荐
- (译)WebRTC实战: STUN, TURN, Signaling
http://xiaol.me/2014/08/24/webrtc-stun-turn-signaling/ 原文:WebRTC in the real world: STUN, TURN and s ...
- unity零基础开始学习做游戏(四)biu~biu~biu发射子弹打飞机
-------小基原创,转载请给我一个面子 主角都能移动了,那不得做点什么伸张正义,守护世界和平的事嘛,拿起家伙biu~biu~biu~ 首先得做一个好人和一个坏人 老规矩,Canvas下创建两个Im ...
- linux 系统centOS 7 怎么在线安装mysql
以下操作,注意空格,为避免出错,可以选择直接copy 第一步: 输入命令行 yum list installed | grep mysql 检查是否已经安装mysql 已安装输入 ...
- 利用redis自制幻灯片弹幕
前段时间赶项目,忙结婚,各大技术平台都没时间上,不过还是抽出点时间为自己的婚礼做了一点小玩具,今天我就来给大家分享一下. 先来看一下效果 这个项目是基于微信个人订阅号的,订阅号的开发在此我就不再赘述了 ...
- 基于ASP.NET MVC 微信网页登录授权(scope为snsapi_base) 流程 上 获取OPENID
流程图 我们需要判断是否存在OPENID 首先我们得先定义一个全局的OPENID 类似于普通账号密码登录系统的 当前登录用户ID 因为我是MVC 框架 我这里定义一个控制器基类 BaseCont ...
- Python_FTP通讯软件
ftpServer.py import socket import threading import os import struct #用户账号.密码.主目录 #也可以把这些信息存放到数据库中 us ...
- 二十一、Hadoop学记笔记————kafka的初识
这些场景的共同点就是数据由上层框架产生,需要由下层框架计算,其中间层就需要有一个消息队列传输系统 Apache flume系统,用于日志收集 Apache storm系统,用于实时数据处理 Spark ...
- Activity,Window,View之间是什么关系?
Activity在onCreate之前调用attach方法,在attach方法中会创建window对象.window对象创建时并没有创建 Decor对象对象.用户在Activity中调用setCont ...
- 如何在js或者jquery中操作EL表达式的一个List集合
------------吾亦无他,唯手熟尔,谦卑若愚,好学若饥------------- 先说明此篇博客看明白了可以干嘛: 就是在js或者jquery中操作一个EL表达式的一个list集合或者复杂类型 ...
- binlog——逻辑复制的基础
Ⅰ.binlog定义和作用 1.1 定义 记录每次数据库的逻辑操作(包括表结构变更和表数据修改) 包含:binlog文件和index文件 1.2 作用 复制:从库读取主库binlog,本地回放实现复制 ...