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. AngularJS - 使用RequireJS还是Browserify?

    http://www.html-js.com/article/2126 AngularJS - 使用RequireJS还是Browserify? AngularJS之所以吸引了很多开发者的关注,很大一 ...

  2. .net core使用orm操作mysql数据库

    Mysql数据库由于其体积小.速度快.总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了MySQL作为网站数据库.MySQL是一个多用户.多线程的关系型数据库管理系 ...

  3. R贡献文件中文

    贡献文件 注意: 贡献文件的CRAN区域被冻结,不再被主动维护. 英文 --- 其他语言 手册,教程等由R用户提供.R核心团队对内容不承担任何责任,但我们非常感谢您的努力,并鼓励大家为此列表做出贡献! ...

  4. Pycharm安装教程

    1.下载PyQt 官方网站:http://www.riverbankcomputing.com/software/pyqt/download5 我的操作系统是64位的,安装的是Python3.4.3, ...

  5. (四)SpringBoot2.0基础篇- 多数据源,JdbcTemplate和JpaRepository

    在日常开发中,经常会遇到多个数据源的问题,而SpringBoot也有相关API:Configure Two DataSources:https://docs.spring.io/spring-boot ...

  6. 程序员快递请查收,来自Python黑客大佬的一份DDOS攻击说明书!

    DDoS攻击没有我们想象中的那么简单,并不是什么Python程序员都能够做到的. 若要知晓黑客利用DDOS攻击原理那么我们必须要知道是实行DDoS攻击比较难的原因是什么? 很简单的一句话概括:&quo ...

  7. servlet什么时候被实例化?【转】

    如果没有设置loadOnStartup,则第一次请求的时候实例化 分三种情况:loadOnStartup < 0 即负数的情况下,web容器启动的时候不做实例化处理,servlet首次被调用时做 ...

  8. cocos2d-x 开发常见问题:

    更改Andriod项目的显示横屏还是竖屏问题: 打开项目中的proj.android/AndroidManifest.xml文件中,更改screenOrientation配置信息: screenOri ...

  9. 深入理解SpringBoot之自动装配

    SpringBoot的自动装配是拆箱即用的基础,也是微服务化的前提.其实它并不那么神秘,我在这之前已经写过最基本的实现了,大家可以参考这篇文章.这次主要的议题是,来看看它是怎么样实现的,我们透过源代码 ...

  10. 爬虫之ssh证书警告错误

    错误信息: 错误信息如下: requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'tls_proce ...