这是一个基于最新的ASP.net core 5.0创建Razor Page应用程序解决方案模板。遵循Clean Architecture的原则,以最求简洁的代码风格和实现快速开发小型的web业务系统的目标,并且从没停止过更新。该项目从最早的asp.net web form,asp.net mvc5 到 asp.net core 3.1再到现在最新的asp.net core 5.0 Razor Page,从简单三层结构到N层结构再到现在流行的CQRS模式,一遍一遍的再重构,在这过程中体会到系统架构的重要性和在优秀的框架下开发系统是一件多么愉快的事情。做这样的项目纯粹是为了兴趣和能和很多Github上优秀的程序员一起交流和学习。

介绍

Technologies

特点

项目结构

基本功能预览

  • 新增
  • 修改
  • 删除
  • 查询
  • 导入Excel
  • 下载模板
  • 导出Excel

用户管理

  • 新增
  • 修改
  • 删除
  • 查询
  • 导入Excel
  • 下载模板
  • 导出Excel
  • 重置密码
  • 角色管理

角色管理

  • 新增
  • 修改
  • 删除
  • 查询
  • 导入Excel
  • 下载模板
  • 导出Excel
  • 授权管理

如何开始

  1. 在Domain project中新增一个Entity,比如Customer客户信息
 public partial class Customer : AuditableEntity, IHasDomainEvent
{
public int Id { get; set; }
public string Name { get; set; }
public string NameOfEnglish { get; set; }
public string GroupName { get; set; }
public PartnerType PartnerType { get; set; }
public string Region { get; set; }
public string Sales { get; set; }
public string RegionSalesDirector { get; set; }
public string Address { get; set; }
public string AddressOfEnglish { get; set; }
public string Contract { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public string Fax { get; set; }
public string Comments { get; set; }
public List<DomainEvent> DomainEvents { get; set; } = new();
}
  1. 在Application project中实现具体的功能请遵循CQRS模式

  • Command

    • AddEdit
    • Delete
    • Import
  • DTOs
  • Eventhandlers
  • Queries
    • Export
    • PaginationQuery
  1. 在SmartAdmin.WebUI中添加UI页面
@page
@using CleanArchitecture.Razor.Domain.Enums
@using CleanArchitecture.Razor.Infrastructure.Constants.Permission
@model SmartAdmin.WebUI.Pages.Customers.IndexModel
@inject Microsoft.Extensions.Localization.IStringLocalizer<IndexModel> _localizer
@inject Microsoft.AspNetCore.Authorization.IAuthorizationService _authorizationService
@{
ViewData["Title"] = _localizer["Customers"].Value;
ViewData["PageName"] = "customers_index";
ViewData["Category1"] = _localizer["Customers"].Value;
ViewData["Heading"] = _localizer["Customers"].Value;
ViewData["PageDescription"] = _localizer["See all available options"].Value;
ViewData["PreemptiveClass"] = "Default";
var _canCreate = await _authorizationService.AuthorizeAsync(User, null, Permissions.Customers.Create);
var _canEdit = await _authorizationService.AuthorizeAsync(User, null, Permissions.Customers.Edit);
var _canDelete = await _authorizationService.AuthorizeAsync(User, null, Permissions.Customers.Delete);
var _canSearch = await _authorizationService.AuthorizeAsync(User, null, Permissions.Customers.Search);
var _canImport = await _authorizationService.AuthorizeAsync(User, null, Permissions.Customers.Import);
var _canExport = await _authorizationService.AuthorizeAsync(User, null, Permissions.Customers.Export); }
@section HeadBlock { <link rel="stylesheet" media="screen, print" href="~/css/formplugins/bootstrap-daterangepicker/bootstrap-daterangepicker.css">
<link rel="stylesheet" media="screen, print" href="~/css/fa-solid.css">
<link rel="stylesheet" media="screen, print" href="~/css/theme-demo.css">
<link rel="stylesheet" media="screen,print" href="~/lib/easyui/themes/insdep/easyui.css">
<style> .customer_dg_datagrid-cell-c1-_action {
overflow: visible !important
}
</style>
}
<div id="js-page-content-demopanels" class="card mb-g">
<div class="card-header bg-white d-flex align-items-center">
<h4 class="m-0">
@_localizer["Customers"]
<small>@_localizer["See all available options"]</small>
</h4>
<div class="ml-auto">
@if (_canCreate.Succeeded)
{
<button class="btn btn-sm btn-outline-primary " id="addbutton">
<span class="@(Settings.Theme.IconPrefix) fa-plus mr-1"></span>
@_localizer["Add"]
</button>
}
@if (_canDelete.Succeeded)
{
<button class="btn btn-sm btn-outline-danger" disabled id="deletebutton">
<span class="@(Settings.Theme.IconPrefix) fa-trash-alt mr-1"></span>
@_localizer["Delete"]
</button>
}
@if (_canSearch.Succeeded)
{
<button class="btn btn-sm btn-outline-primary " id="searchbutton">
<span class="@(Settings.Theme.IconPrefix) fa-search mr-1"></span>
@_localizer["Search"]
</button>
}
@if (_canImport.Succeeded)
{
<div class="btn-group" role="group">
<button id="importbutton" type="button" class="btn btn-sm btn-outline-primary waves-effect waves-themed">
<span class="@(Settings.Theme.IconPrefix) fa-upload mr-1"></span> @_localizer["Import Excel"]
</button>
<button type="button" class="btn btn-sm btn-outline-primary dropdown-toggle dropdown-toggle-split waves-effect waves-themed" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="sr-only">Toggle Dropdown</span>
</button>
<div class="dropdown-menu" aria-labelledby="importbutton">
<button id="gettemplatebutton" class="dropdown-item">@_localizer["Download Template"]</button>
</div>
</div>
}
@if (_canExport.Succeeded)
{
<button class="btn btn-sm btn-outline-primary " id="exportbutton">
<span class="@(Settings.Theme.IconPrefix) fa-download mr-1"></span>
@_localizer["Export Excel"]
</button>
}
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-md-12">
<table id="customer_dg">
</table>
</div>
</div>
</div>
</div>
<div class="modal fade" id="customer_modal" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true"><i class="@(Settings.Theme.IconPrefix) fa-times"></i></span>
</button>
</div>
<form id="customer_form" class="needs-validation" novalidate="novalidate">
...
</form>
</div>
</div>
</div>
@await Component.InvokeAsync("ImportExcel", new { importUri = Url.Page("/Customers/Index") + "?handler=Import",
getTemplateUri = @Url.Page("/Customers/Index") + "?handler=CreateTemplate",
onImportedSucceeded = "reload()" })
@section ScriptsBlock {
<partial name="_ValidationScriptsPartial" /> <script type="text/javascript" src="~/lib/easyui/jquery.easyui.min.js" asp-append-version="true"></script>
<script type="text/javascript" src="~/lib/easyui/jquery.easyui.component.js" asp-append-version="true"></script>
<script type="text/javascript" src="~/lib/easyui/plugins/datagrid-filter.js" asp-append-version="true"></script>
<script>jQuery.fn.tooltip = bootstrapTooltip;</script>
<script src="~/lib/axios/dist/axios.js"></script>
<script src="~/lib/jquery-form/jquery.jsonToForm.js"></script> <script type="text/javascript">
$('#searchbutton').click(function () {
reload();
});
$('#addbutton').click(function () {
popupmodal(null);
});
$('#deletebutton').click(function () {
onDeleteChecked();
});
$('#exportbutton').click(function () {
onExport();
});
$('#importbutton').click(function () {
showImportModal();
});
$('#gettemplatebutton').click(function () {
onGetTemplate();
});
$('#customer_form :submit').click(function (e) {
...
event.preventDefault();
event.stopPropagation();
})
var $dg={};
var initdatagrid = () => {
$dg = $('#customer_dg').datagrid({
... } var reload = () => {
$dg.datagrid('load', '@Url.Page("/Customers/Index")?handler=Data');
} $(() => {
initdatagrid();
})
var popupmodal = (customer) => {
...
} var onEdit = (index) => {
var customer = $dg.datagrid('getRows')[index];
popupmodal(customer);
}
var onDelete = (id) => {
...
}
var onDeleteChecked = () => {
...
}
var onExport = () => {
...
} </script>
}

我的项目成果

网站 账号/密码 截图
http://tms.i247365.net/ TMS 运输管理系统 demo@email.com/123456
http://manage.i247365.net/ 委托业务内控管理系统 demo/123456
http://check.i247365.net/ 人脸考勤管理系统 demo/123456
http://supplier.i247365.net/ 供应商询价系统 demo/123456
http://iot.i247365.net/ 智能水务综合管理平台 demo/123456
http://book.i247365.net/ 小型图书管理工具 demo/123456

最后

keep coding, enjoy coding.

如果你喜欢这个项目,请记得在Github上点赞,谢谢

https://github.com/neozhu/RazorPageCleanArchitecture

一个遵循CleanArchitecture原则的Asp.net core轻量级开源项目的更多相关文章

  1. Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架

    Asp.Net Core 2.0 项目实战(1) NCMVC开源下载了 Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架 Asp.Ne ...

  2. 从零开始一个个人博客 by asp.net core and angular(一)

    这是一个个人叙述自己建设博客的帖子,既然是第一篇那肯定是不牵扯代码了,主要讲一下大体的东西,微软最新的web框架应该就数asp.net core 3.1了这是一个长期支持版,而且是跨平台又开源版本,所 ...

  3. [Asp.Net Core轻量级Aop解决方案]AspectCore Project 介绍

    AspectCore Project 介绍 什么是AspectCore Project ? AspectCore Project 是适用于Asp.Net Core 平台的轻量级 Aop(Aspect- ...

  4. Asp.Net Core轻量级Aop解决方案:AspectCore

    什么是AspectCore Project ? AspectCore Project 是适用于Asp.Net Core 平台的轻量级 Aop(Aspect-oriented programming) ...

  5. Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员、后台管理员同时登录

    1.登录的实现 登录功能实现起来有哪些常用的方式,大家首先想到的肯定是cookie或session或cookie+session,当然还有其他模式,今天主要探讨一下在Asp.net core 2.0下 ...

  6. Asp.Net Core 2.0 项目实战(11) 基于OnActionExecuting全局过滤器,页面操作权限过滤控制到按钮级

    1.权限管理 权限管理的基本定义:百度百科. 基于<Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员.后台管理员同时登录>我们做过了登录认证, ...

  7. Asp.Net Core 2.0 项目实战(9) 日志记录,基于Nlog或Microsoft.Extensions.Logging的实现及调用实例

    本文目录 1. Net下日志记录 2. NLog的使用     2.1 添加nuget引用NLog.Web.AspNetCore     2.2 配置文件设置     2.3 依赖配置及调用     ...

  8. Asp.Net Core 2.0 项目实战(8)Core下缓存操作、序列化操作、JSON操作等Helper集合类

    本文目录 1.  前沿 2.CacheHelper基于Microsoft.Extensions.Caching.Memory封装 3.XmlHelper快速操作xml文档 4.Serializatio ...

  9. Asp.Net Core 2.0 项目实战(7)MD5加密、AES&DES对称加解密

    本文目录 1. 摘要 2. MD5加密封装 3. AES的加密.解密 4. DES加密/解密 5. 总结 1.  摘要 C#中常用的一些加密和解密方案,如:md5加密.RSA加密与解密和DES加密等, ...

随机推荐

  1. hdu 3306 Another kind of Fibonacci 矩阵快速幂

    参考了某大佬的 我们可以根据(s[n-2], a[n-1]^2, a[n-1]*a[n-2], a[n-2]^2) * A = (s[n-1], a[n]^2, a[n]*a[n-1], a[n-1] ...

  2. ROS2学习之旅(1)——初识ROS2

    本系列用来记录ROS2的学习过程,有错误或者不合理的地方请大家指正.由于博主具有ROS1的学习经历,会添加一些与ROS1的一些对比,当然这对于ROS2本身的学习内容没有丝毫影响,欢迎大家积极与我在评论 ...

  3. 玩Aarch64最方便的方法

    译至:http://d.hatena.ne.jp/embedded/20140819/p1 虽然Aarch64(ARM64)的板子还很难到手.但通过使用qemu就能执行Aarch64的用户空间程序.利 ...

  4. XCTF getit

    一.查壳 是linux的文件.没加壳 二.拖入ida 分析一下逻辑,发现就是t的值就是flag. 写个exp就出来了. 三.exp分享 s='c61b68366edeb7bdce3c6820314b7 ...

  5. Linux groupadd and groupmod

    groupadd [选项] group 三个参数: -g,--gid 指定组gid,除非使用-o,否则gid必须时唯一的 -o,--non-unique 允许创建有重复gid的组 -r, --syst ...

  6. C语言:逻辑运算符||

    #include <stdio.h> //逻辑运算符||特点:左右两边的表达式先做左边,如果左边为1则右边不用执行,整个结果为1:如果左边为0,再执行右边: main() { int x= ...

  7. SpringBoot 整合 MybatisPlus 3.0

      CRUD是指在做计算处理时的增加(Create).读取查询(Retrieve).更新(Update)和删除(Delete)几个单词的首字母简写.主要被用在描述软件系统中DataBase或者持久层的 ...

  8. [刘阳Java]_酷炫视频播放器制作_界面篇

    今天开始分享一篇酷炫播放器制作,包括界面+JS.整个案例非常类似腾讯视频,优酷视频,爱奇艺视频.我们先看一下效果图,然后这篇文章主要界面篇 是不是效果比较酷炫,那么我接着来给大家说一下这个界面设计思路 ...

  9. Leetcode No.14 Longest Common Prefix最长公共前缀(c++实现)

    1. 题目 1.1 英文题目 Write a function to find the longest common prefix string amongst an array of strings ...

  10. PAT乙级:1090危险品装箱(25分)

    PAT乙级:1090危险品装箱(25分) 题干 集装箱运输货物时,我们必须特别小心,不能把不相容的货物装在一只箱子里.比如氧化剂绝对不能跟易燃液体同箱,否则很容易造成爆炸. 本题给定一张不相容物品的清 ...