[基于NetCore的简单博客系统]-登录
0-项目背景
一个基于.NET CORE RAZOR PAGES的简单博客系统 技术栈全部采用微软官方实现方式,目的是熟悉新技术
PS:因为是练手,所以UI界面就比较丑咯
1-框架结构(参考ABP框架:因为是练手,所以没有使用ABP基础类,只是参考了他的架子)

1.1)后台用经典的MVC方式实现
1.2)前台打算使用.NetCore RazorPage页面实现
2-表结构

2.1)User - 后台用户
2.2)Member -前台用户
2.3)MemberBlogTagRelationship - 前台用户博文标签表
2.4)Blog -博文
2.5)BlogCategroy -博文分类
2.6)BlogPost- 博文评论
2.7) BlogTag-博文标签(前台用户添加)
2.8)BlogTagRelationship - 博文-博文标签关联表
2.9)添加Entity 基类 参考 ABP 的实体基类,所有实体都是派生自 entity
3-生成数据库(基于EF code-first 模式)
3.1)添加实体与数据库表映射关系



3.2)数据上下文中添加配置

3.3)生成数据库方式参考https://docs.microsoft.com/en-us/ef/core/ 和以前的EF差不多
3.4)SetOneToManyCascadeDeleteConvertion 和 AddEntityTypeConfigruations 都是自定义的扩展方法
public static class ModelBuilderExtensions
{
/// <summary>
/// 关掉所有主外键关系的级联删除
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="deleteBehavior"></param>
public static void SetOneToManyCascadeDeleteConvention(this ModelBuilder modelBuilder, DeleteBehavior deleteBehavior = DeleteBehavior.Restrict)
{
foreach (var relationship in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetForeignKeys()))
{
relationship.DeleteBehavior = deleteBehavior;
}
} /// <summary>
/// 自动映射实体与表
/// </summary>
/// <param name="modelBuilder"></param>
/// <param name="executingAssembly"></param>
public static void AddEntityTypeConfigurations(this ModelBuilder modelBuilder, Assembly executingAssembly)
{
var types = executingAssembly.GetTypes();
var filterTypes = types.Where(x => !string.IsNullOrEmpty(x.Namespace));
var result = filterTypes.Where(x => !x.IsAbstract && x.GetInterfaces()
.Any(y => y.GetTypeInfo()
.IsGenericType && y.GetGenericTypeDefinition() == typeof(IEntityTypeConfiguration<>))); foreach (var configurationInstance in result.Select(Activator.CreateInstance))
{
modelBuilder.ApplyConfiguration((dynamic)configurationInstance);
}
}
}
SetOneToManyCascadeDeleteConvertion 和 AddEntityTypeConfigruations 都是自定义的扩展方法
4-注册依赖 (IOC:data,application)
4.1)ApplicationServiceCollectionExtensions:application类库中IOC相关注册扩展类
public static class ApplicationServiceCollectionExtensions
{
public static void ApplicationRegister(this IServiceCollection services)
{
services.AddScoped<IUserService, UserService>();
services.AddScoped<IMemberService, MemberService>();
services.AddScoped<IBlogService, BlogService>();
services.AddScoped<IBlogCategoryService, BlogCategoryService>();
}
}
ApplicationServiceCollectionExtensions
4.2)EfCoreServiceCollectionExtensions :data类库中IOC相关注册扩展类
public static class EfCoreServiceCollectionExtensions
{
/// <summary>
/// 注册数据库上下文
/// </summary>
/// <typeparam name="TDbContext"></typeparam>
/// <param name="services"></param>
/// <param name="connectionString"></param>
public static void AddDbContext<TDbContext>(this IServiceCollection services, string connectionString)
where TDbContext : DbContext
{
//UseRowNumberForPaging() 用于分页 ms sql server版本低于2012 需要使用
services.AddDbContext<TDbContext>(options => options.UseSqlServer(connectionString, b => b.UseRowNumberForPaging()));//
} /// <summary>
/// 接口注册
/// </summary>
/// <param name="services"></param>
public static void RegisterRepository(this IServiceCollection services)
{
services.AddScoped(typeof(IRepository<,>), typeof(RepositoryBase<,>));
}
}
EfCoreServiceCollectionExtensions
5-登录
5.1)添加IUserService 接口,UserService类,添加UserDto GetData(string userName, string password); 函数
5.2)添加 UserDto Model 类,实现GetData方法

5.3)添加 UserExtensions 扩展类
public static class UserExtensions
{
public static UserDto ToDto(this User user)
{
if (user == null)
return null;
return new UserDto
{
Id = user.Id,
IsActived = user.IsActived,
UserName = user.UserName
};
} public static User ToEntity(this UserDto user)
{
if (user == null)
return null;
return new User
{
Id = user.Id,
IsActived = user.IsActived,
UserName = user.UserName,
CreatedOn = DateTime.Now
};
}
}
UserExtensions
5.4) 添加 Account Controller
using System;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using GR.Blogs.AspNetCore.Security;
using GR.Blogs.AspNetCore.Users;
using GR.Blogs.AspNetCore.Dto;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using GR.Blogs.AspNetCore.Users.Dto; namespace GR.Blogs.AspNetCore.Web.Mvc.Controllers
{
[Authorize]
public class AccountController : Controller
{
private readonly IUserService _userService; public AccountController(IUserService userService)
{
_userService = userService;
} [AllowAnonymous]
public IActionResult Login(string ReturnUrl = null)
{
var model = new LoginViewModel();
return View(model);
} [AllowAnonymous]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(string ReturnUrl, /*[Bind("UserName,Password")]*/ LoginViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = _userService.GetData(model.UserName, MD5EncryptHelper.MD5Encrypt(model.Password));
if (user == null)
{
ModelState.AddModelError("", "用户名或密码错误");
return View(model);
} await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, GetUserClaimsPrincipal(user));
if (ReturnUrl == null)
return RedirectToAction("index", "home");
else
return Redirect(ReturnUrl);
} private ClaimsPrincipal GetUserClaimsPrincipal(UserDto user)
{
var claims = new List<Claim>();
claims.Add(new Claim(ClaimTypes.Name, user.UserName, ClaimValueTypes.String));
claims.Add(new Claim(ClaimTypes.UserData, user.Id.ToString(), ClaimValueTypes.String));
//这里写死了,正式的话,角色需要通过获取数据库角色,写入的
//claims.Add(new Claim(ClaimTypes.Role, "Administrator", ClaimValueTypes.String));
//
var userIdentity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
userIdentity.AddClaims(claims);
var userPrincipal = new ClaimsPrincipal(userIdentity);
return userPrincipal;
} public async Task<IActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return RedirectToAction("index", "home");
}
}
}
AccountController
5.5) Startup 中配置 Cookie 验证 ,注册IOC

5.6)添加Login页面布局,样式是基于flatUI
@model GR.Blogs.AspNetCore.Dto.LoginViewModel
@{
Layout = null;
} <!DOCTYPE html> <html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=1000, initial-scale=1.0, maximum-scale=1.0">
<title>登录 - GR博客系统</title>
<link href="~/lib/bootstrap/dist/css/bootstrap.css" rel="stylesheet" />
<link href="~/lib/flatUI/dist/css/flat-ui.css" rel="stylesheet" />
<link href="~/lib/flatUI/docs/assets/css/demo.css" rel="stylesheet" />
<!-- HTML5 shim, for IE6-8 support of HTML5 elements. All other JS at the end of file. -->
<!--[if lt IE 9]>
<script src="~/lib/flatUI/dist/js/vendor/html5shiv.js"></script>
<script src="~/lib/flatUI/dist/js/vendor/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="login" style="margin-top:100px;">
<div class="login-screen">
<div class="login-icon">
<img src="~/lib/flatUI/dist/img/icons/png/Mail.png" alt="Welcome to Mail App" />
<h4>Welcome to <small>Mail App</small></h4>
</div> <form class="login-form" method="post">
@Html.AntiForgeryToken()
<div class="form-group">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
</div>
<div class="form-group">
<input type="text" asp-for="UserName" class="form-control login-field" value="" placeholder="用户名">
<label class="login-field-icon fui-user"></label>
<span asp-validation-for="UserName" class="text-danger"></span>
</div> <div class="form-group">
<input type="password" asp-for="Password" class="form-control login-field" value="" placeholder="密码">
<label class="login-field-icon fui-lock"></label>
<span asp-validation-for="Password" class="text-danger"></span>
</div> <input type="submit" class="btn btn-primary btn-lg btn-block" value="登录">
<a class="login-link" href="#">忘记密码?</a>
</form>
</div>
</div>
</div>
@*<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.2.0.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-K+ctZQ+LL8q6tP7I94W+qzQsfRV2a+AfHIi9k8z8l9ggpc8X+Ytst4yBo/hH+8Fk">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
</environment>
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}*@ </body>
</html>
Login

5-结束了
文笔不行,不知道该怎么组织语言,所以就以流水账形式记录了
[基于NetCore的简单博客系统]-登录的更多相关文章
- 26种基于PHP的开源博客系统
26种基于PHP的开源博客系统 来源:本站原创 PHP学习笔记 以下列举的PHP开源Blog系统中,除了我们熟知的WordPress之外,大多都没有使用过,其中一些已经被淘汰,或者有人还在使用.除了做 ...
- Docker——基于Docker安装Drupal博客系统
Docker--基于Docker安装Drupal博客系统 向脚本文件追加内容 cat << EOF > build.sh #设置主机名 hostnamectl set-hostnam ...
- Java基于SSM的个人博客系统(源码 包含前后台)
@ 目录 系统简介 系统运行截图 核心代码 写在最后 系统简介 技术点:Java.JSP.SSM框架,实现了个人博客系统 用户角色分为:普通用户.管理员.系统管理员 功能:发博客.博客分类.博客删除. ...
- 基于开源博客系统(mblog)搭建网站
基于开源博客系统(mblog)搭建网站 上一章讲了基于jpress部署的博客系统,这一章了解一下 mblog这个开源的基于springboot的博客系统,相比与jpress 的热度fork数量要少一些 ...
- 欢迎阅读daxnet的新博客:一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为"希赛网" ...
- 一个基于Microsoft Azure、ASP.NET Core和Docker的博客系统
2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客.当然,我写博客也不是从2008年才开始的,在更早时候,也在CSDN和系统分析员协会(之后名为“希赛网”)个人空间发布过一些 ...
- 基于Microsoft Azure、ASP.NET Core和Docker的博客系统
欢迎阅读daxnet的新博客:一个基于Microsoft Azure.ASP.NET Core和Docker的博客系统 2008年11月,我在博客园开通了个人帐号,并在博客园发表了自己的第一篇博客 ...
- Essay3.0发布,基于JavaScript的前后端同构博客系统
前言 转眼间距离我开源这个项目已经两年了,最初是奔着学习的目的开发了这个项目,后来一直记录自己的学习笔记.随着时间的增长,发现之前写的代码简直不忍直视,于是就有了重构的想法.这个过程有些漫长,竟然用了 ...
- 基于开源博客系统(jpress)搭建网站
基于开源博客系统(jpress)搭建网站 JPress 使用 Java8 开发,基于流行的JFinal和Jboot框架. 目前JPress已经内置的文章和页面其实是两个模块,可以移除和新增其他模块,因 ...
随机推荐
- Redis(三):Redis数据类型
Redis数据类型目录导航: Redis五大数据类型 哪里去获取Redis常见数据类型操作命令 Redis键(Key) Redis字符串(String) Redis列表(List) Redis集合(S ...
- 导入/导出excel和PHPExcel基本使用
* PHPExcel基本使用 * PS:文章如果有误,请及时指出,给予修改 * 项目中导入PHPExcel * 可以去网上下载 github composer 都可以 * 为了方便下载,我将压缩包添加 ...
- Window10 Electron 开发环境搭建及打包exe程序
1.安装 Electron 首先要安装Node.js (安装方法:https://www.cnblogs.com/inkwhite/p/9685520.html) 我这里已经安装好了. 2:安 ...
- django路由基本使用-6
路由定义位置 django的路由是定义在 urls.py 文件下的 urlpatterns 列表中的. urls.py 文件是路由解析的入口. from django.conf.urls import ...
- Python学习5——基本格式化输出
整数的格式化输出 十进制.八进制.十六进制 num01 = 100 print("十进制输出:%d"%num01) print("八进制输出:%o"%num01 ...
- python教程(二)·数据类型
数据类型,顾名思义就是数据的类型,数据到底有哪些类型呢?在python中,最基本的数据类型有好几种,让我来逐个介绍. 整数类型(int) python中只有一种整数类型,就是int类型,在程序中的写法 ...
- pylearn2报错缺少theano.compat.six
按照官网的顺序下载 会出现缺少theano.compat.six的报错 纠结了一天,各种查,最后终于找到解决方法,theano安装有问题 不能安装最新版本,即pip的时候theano==0.7.0,然 ...
- MongoDB入门---文档查询操作之条件查询&and查询&or查询
经过前几天的学习之路,今天终于到了重头戏了.那就是文档查询操作.话不多说哈,直接看下语法: db.collection.find(query, projection) query :可选,使用查询操作 ...
- 20145209 2016-2017-2 《Java程序设计》第9周学习总结
20145209 2016-2017-2 <Java程序设计>第9周学习总结 教材学习内容总结 JDBC简介 撰写应用程序是利用通信协议对数据库进行指令交换,以进行数据的增删查找 JDBC ...
- 优步UBER司机全国各地奖励政策汇总 (2月22日-2月28日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...