这是一个基于最新的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. Elasticsearch的配置学习笔记

    文/朱季谦 Elasticsearch是一个基于Lucene的搜索服务器.它提供一个分布式多用户能力的全文搜索引擎,基于RESTful web接口,Elasticsearch是用Java语言开发的. ...

  2. 通过css实现幻灯片效果

    html: css: .box { border: 0px solid white; width: 1520px; height: 480px; margin: 0 auto; position: a ...

  3. Docker:虚拟机挂起后,再启动docker容器连接失败

    问题描述 当我们使用VMware15 Pro 创建虚拟机并运行Linux搭建的Docker时,挂起虚拟机后再次运行发现访问Docker容器失败. 解决方式  我们正常的挂起其实是:挂起客户机,博主尝试 ...

  4. shell中的特殊变量IFS

    shell中特殊变量IFS的使用 IFS是内部字段分隔符(internal field separator).默认情况下,bash shell会将空格.制表符.换行符 当做字段分隔符. IFS=$'\ ...

  5. Macbook(M1版)的用户看过来,.net 6 Preview 6支持Apple Silicon for macOS

    本文由葡萄城技术团队翻译 转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 我们很高兴发布.NET6预览的第6版,本次预览是倒数第二次预览了.在本次预览发布之 ...

  6. TestNG基础001

    一.什么是TestNG TestNG是一个强大的测试框架,NG是指Next Generation ,被视为是Junit的升级版本 二.TestNG适用范围 Java单元测试 接口测试 web自动化测试 ...

  7. IE浏览器查看星号密码

    用CHROME打开保存密码的网页,F12,右击"密码框"检查,编辑属性:password改为passw(只要不是password即可)即可显示密码

  8. asp.net c#整理所有本地的图片一次性保存到SQL表中

    string sql1 = "select distinct tx from tiku where tx is not null"; //检索tx表中所有的不重复的tx值 stri ...

  9. vue+canvas实现炫酷时钟效果的倒计时插件(已发布到npm的vue2插件,开箱即用)

    前言: 此事例是在vue组件中,使用canvas实现倒计时动画的效果.其实,实现效果的逻辑跟vue没有关系,只要读懂canvas如何实现效果的这部分逻辑就可以了 canvas动画的原理:利用定时器,给 ...

  10. glibc库和glib库

    http://ftp.acc.umu.se/pub/GNOME/sources/ ubuntu16上glib的安装包的名是libglibXX  XX是版本号 ubuntu上查看glibc的方法 ldd ...