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 小试牛刀的更多相关文章

  1. 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 ...

  2. ASP.NET Core - Razor 页面简介

    简介 随着ASP.NET Core 2 即将来临,最热门的新事物是Razor页面.在之前的一篇文章中,我们简要介绍了ASP.NET Core Razor 页面. Razor页面是ASP.NET Cor ...

  3. ASP.NET Core - Razor页面之Handlers处理方法

    简介 在前一篇文章中,我们讨论了Razor页面.今天我们来谈谈处理方法(Handlers). 我们知道可以将代码和模型放在 .cshtml 文件里面或与 .cshtml 匹配的 .cshtml.cs ...

  4. ASP.NET Core Razor中处理Ajax请求

    如何ASP.NET Core Razor中处理Ajax请求 在ASP.NET Core Razor(以下简称Razor)刚出来的时候,看了一下官方的文档,一直没怎么用过.今天闲来无事,准备用Rozor ...

  5. ASP.NET Core Razor页面禁用防伪令牌验证

    在这篇短文中,我将向您介绍如何ASP.NET Core Razor页面中禁用防伪令牌验证. Razor页面是ASP.NET Core 2.0中增加的一个页面控制器框架,用于构建动态的.数据驱动的网站: ...

  6. ASP.NET Core Razor 页面使用指南

    ASP.NET Core Razor 页面作为 ASP.NET Core 2.0的一部分发布,它是基于页面的全新的Web开发框架.如果您想学习如何使用 ASP.NET Core Razor 页面,可以 ...

  7. 学习ASP.NET Core Razor 编程系列一

    一. 概述 .NET Core 1.0发布的时候就想进行学习的,不过根据微软的以往的发布规律1.0版可以认为是大众测试版,2.0才算稳定.现在2.1都已经发布了预览版,之前对其"不稳定&qu ...

  8. 学习ASP.NET Core Razor 编程系列二——添加一个实体

    在Razor页面应用程序中添加一个实体 在本篇文章中,学习添加用于管理数据库中的书籍的实体类.通过实体框架(EF Core)使用这些类来处理数据库.EF Core是一个对象关系映射(ORM)框架,它简 ...

  9. 学习ASP.NET Core Razor 编程系列四——Asp.Net Core Razor列表模板页面

    学习ASP.NET Core Razor 编程系列目录 学习ASP.NET Core Razor 编程系列一 学习ASP.NET Core Razor 编程系列二——添加一个实体 学习ASP.NET ...

随机推荐

  1. Java 线程同步组件 CountDownLatch 与 CyclicBarrier 原理分析

    1.简介 在分析完AbstractQueuedSynchronizer(以下简称 AQS)和ReentrantLock的原理后,本文将分析 java.util.concurrent 包下的两个线程同步 ...

  2. leetCode刷题(找到两个数组拼接后的中间数)

    There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two ...

  3. 微信小程序-获取地理位置

    近期公司使用微信小程序开发一套应用,涉及到使用小程序的获取地理位置接口,但是在使用测试过程中发现获取的经纬度偏差较大, 之后进行了一番搜索,终于找到了, 原文地址:http://blog.csdn.n ...

  4. Python并发编程之线程中的信息隔离(五)

    大家好,并发编程 进入第三篇. 上班第一天,大家应该比较忙吧.小明也是呢,所以今天的内容也很少.只要几分钟就能学完. 昨天我们说,线程与线程之间要通过消息通信来控制程序的执行. 讲完了消息通信,今天就 ...

  5. 一个基于原生JavaScript开发的、轻量的验证码生成插件

    Vcode.js 一个基于原生JavaScript开发的.轻量的验证码生成插件 V: 1.0.0 DEMO:https://jofunliang.github.io/Vcode.js/example. ...

  6. 敏捷(Agile)——“说三道四”

    可以这么理解:一种以人为本.团队合作.快速响应变化和可工作的软件作为宗旨的开发方法.亦可理解为在一个高度协作的环境中,不断地使用反馈进行自我调整和完善,持续交付用户想要的软件的过程.敏捷开发提倡通过多 ...

  7. jms中activemq事务探讨

    http://blog.csdn.net/dly1580854879/article/details/68945997

  8. Java 精简Jre jar打包成exe

    #开始 最近几天都在忙一个事情,那就是尝试精简jre,我想不明白为什么甲骨文官方不出exe打包工具... 网络上精简jre的文章很多,但是原创的似乎没几个,绝大多数都是转发同一个博客, 这里借鉴了不少 ...

  9. 写给小前端er的nodejs,mongodb后端小攻略~ (windows系统~)

    一.写在前面 迫于学校的压力,研二上准备回学校做实验发论文了,感觉真的没意思,这几天学着搞搞后端,踩了很多坑,整理一下这几天的坑以免以后再犯! 二.本文主要内容(由于是面向前端同学的,所以前端的内容就 ...

  10. 你不知道的JavaScript--Item22 Date对象全解析

    本篇主要介绍 Date 日期和时间对象的操作. 1. 介绍 1.1 说明 Date对象,是操作日期和时间的对象.Date对象对日期和时间的操作只能通过方法. 1.2 属性 无: Date对象对日期和时 ...