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之Spring(IOC)注解装配Bean详解

    java之Spring(IOC)注解装配Bean详解   在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...

  2. 在Web中获取MAC地址

    很多时候都很难琢磨客户在想什么,也许是自己业务经验不足,也许是客户要显示出他在软件方面也非常的专业.记得以前听过一个故事,说一个富人想娶个媳妇,然后他比较钟意的有三个女人,然后就想从三个女人中选一个, ...

  3. Python黑客泰斗利用aircrack-ng破解 wifi 密码,超详细教程!

    开始前,先连上无线网卡,因为虚拟机中的kali系统不用调用笔记本自带的无线网卡,所以需要一个外接无线网卡,然后接入kali系统. 输入 ifconfig -a 查看网卡,多了个 wlan0,说明网卡已 ...

  4. django自定义用户表

    django中已经给我生成默认的User表,其中的字段已经可以满足我们的日常需求. 但有时候,我们需要更多的字段,我们就可以自定义.来替换django自带的User表. #models.py from ...

  5. HTTP协议简单记录

    http协议的格式 1. 首行 2. 头 3. 空行 4. 体 http请求头 #Referer 请求来自哪里,如果是在http://www.baidu.com上点击链接发出的请求,那么Referer ...

  6. 树莓派配置watchdog

    安装watchdog apt install watchdog 编辑/etc/modules,添加bcm2708_wdog 编辑/etc/watchdog.conf watchdog-device = ...

  7. 花生日记_花生日记APP下载_花生日记邀请码

    花生日记 国内领先的社交电商导购分享平台. 独创社交电商3+模式,社交+电商+社群,上线1个月注册用户超百万.合作商家涵括各个类目以及平台.为数万宝妈提供月收入3000以上兼职收入. 微信扫描下方二维 ...

  8. PAT1129:Recommendation System

    1129. Recommendation System (25) 时间限制 400 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue ...

  9. Oracle数据库查询优化方案(处理上百万级记录如何提高处理查询速度)

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引.2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引 ...

  10. HTTP多线程下载+断点续传(libcurl库)

    目录索引: 一.LibCurl基本编程框架 二.一些基本的函数 三.curl_easy_setopt函数部分选项介绍 四.curl_easy_perform 函数说明(error 状态码) 五.lib ...