[基于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已经内置的文章和页面其实是两个模块,可以移除和新增其他模块,因 ...
随机推荐
- Tornado用户指引(一)-----------异步和非阻塞I/O
摘要:异步和非阻塞I/O实时WEB的特性是经常需要为每个用户端维持一个长时间存活但是大部分时候空闲的连接.在传统的同步式web服务器中,这主要通过为每个用户创建一个线程来实现,这样的代价是十分昂贵的. ...
- Spark在实际项目中分配更多资源
Spark在实际项目中分配更多资源 Spark在实际项目中分配更多资源 性能调优概述 分配更多资源 性能调优问题 解决思路 为什么调节了资源以后,性能可以提升? 性能调优概述 分配更多资源 性能调优的 ...
- SpringBoot 解决ModelAndView强转Json问题
最近一直在做SpringBoot升级的项目,碰到了一个很蛋疼的问题. 我们项目和前端的AngularJs通过Json来传递信息,但是我们有一块的代码在Controller返回的是ModelAndVIe ...
- 数据库 MySQL part4
存储引擎 什么是存储引擎? mysql中建的库是文件夹,建的表是文件.文件有不同的类型,数据库中的表也有不同的类型,表的类型不同,会对应mysql不同的存取机制,表类型又称为存储引擎. 存储引擎说白了 ...
- 北京Uber优步司机奖励政策(1月9日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- day 4 __all__ 包 __init__.py
1.__all__的作用 如果一个文件中有__all__变量,那么也就意味着这个变量中的元素,不会被from xxx import *时导入 __all__ = ["test1", ...
- spring源码-增强容器xml解析-3.1
一.ApplicationContext的xml解析工作是通过ClassPathXmlApplicationContext来实现的,其实看过ClassPathXmlApplicationContext ...
- PLSQL集合类型
PLSQL集合类型 --联合数组(索引表) /* 用于存储某个数据类型的数据集合类型 .通过索引获得联合数组中得值 如下例子: */ DECLARE CURSOR cur_chars IS SEL ...
- 通过 zxing 生成二维码
二维码现在随处可见,在日常的开发中,也会经常涉及到二维码的生成,特别是开发一些活动或者推广方面的功能时,二维码甚至成为必备功能点.本文介绍通过 google 的 zxing 包生成带 logo 的二维 ...
- Qt 独立运行时伴随CMD命令窗口
用Qt写了一个小软件,在把程序release后,打包分装后,发现程序运行的时候会伴随cmd命令窗口,可把我愁怀了 不过功夫不负有心人,在老师和我网友的帮助下,终于搞完了 CONFIG:指定工程配置和编 ...