<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ASP.NET Core 輕量級開源項目(遵循CleanArchitecture原則)

          共 21626字,需瀏覽 44分鐘

           ·

          2022-08-01 05:21


          前言


          這是一個基于最新的ASP.NET Core 5.0 創(chuàng)建Razor Page應(yīng)用程序解決方案模板。遵循Clean Architecture的原則,以最求簡潔的代碼風(fēng)格和實現(xiàn)快速開發(fā)小型的Web業(yè)務(wù)系統(tǒng)的目標(biāo),并且從沒停止過更新。

          該項目從最早的ASP.NET Web Form,ASP.NET MVC 5 到 ASP.NET Core 3.1再到現(xiàn)在最新的ASP.NET Core 5.0 Razor Page,從簡單三層結(jié)構(gòu)到N層結(jié)構(gòu)再到現(xiàn)在流行的CQRS模式,一遍一遍的再重構(gòu),在這過程中體會到系統(tǒng)架構(gòu)的重要性和在優(yōu)秀的框架下開發(fā)系統(tǒng)是一件多么愉快的事情。

          做這樣的項目純粹是為了興趣和能和很多Github上優(yōu)秀的程序員一起交流和學(xué)習(xí)。

          介紹

          1、Github https://github.com/neozhu/RazorPageCleanArchitecture

          2、Demo http://razor.i247365.net/

          3、For Asp.net Core MVC https://github.com/neozhu/smartadmin.core.urf

          Technologies

          • ASP.NET Core 5:https://devblogs.microsoft.com/aspnet/announcing-asp-net-core-in-net-5/
          • Entity Framework Core 5:https://docs.microsoft.com/en-us/ef/core/
          • SmartAdmin - Responsive WebApp:https://wrapbootstrap.com/theme/smartadmin-responsive-webapp-WB0573SK0/
          • Razor Pages:https://docs.microsoft.com/en-us/aspnet/core/razor-pages/?view=aspnetcore-5.0&tabs=visual-studio
          • Jquery EasyUI:https://www.jeasyui.com/
          • MediatR:https://github.com/jbogard/MediatR
          • AutoMapper:https://automapper.org/
          • FluentValidation:https://fluentvalidation.net/
          • NUnit:https://nunit.org/
          • FluentAssertions:https://fluentassertions.com/
          • Moq:https://github.com/moq
          • Respawn:https://github.com/jbogard/Respawn
          • Docker:https://www.docker.com/

          特點

          • 遵循Clean Architecture原則

            什么是Clean Architecture:https://www.youtube.com/watch?v=dK4Yb6-LxAk

          • 非常漂亮的用戶界面

            SmartAdmin - Responsive WebApp:https://wrapbootstrap.com/theme/smartadmin-responsive-webapp-WB0573SK0/

          • 遵循CQRS模式極簡的代碼風(fēng)格

            什么是CQRS:https://zhuanlan.zhihu.com/p/115685384

          • 實現(xiàn)了基本的CRUD功能

          • 實現(xiàn)了基本的認(rèn)證和授權(quán)功能

          • 支持多語言切換

          項目結(jié)構(gòu)

          • 項目結(jié)構(gòu)參考

          jasontaylordev:https://github.com/jasontaylordev

          CleanArchitecture:https://github.com/jasontaylordev/CleanArchitecture

          基本功能預(yù)覽

          • 新增
          • 修改
          • 刪除
          • 查詢
          • 導(dǎo)入Excel
          • 下載模板
          • 導(dǎo)出Excel

          用戶管理

          • 新增
          • 修改
          • 刪除
          • 查詢
          • 導(dǎo)入Excel
          • 下載模板
          • 導(dǎo)出Excel
          • 重置密碼
          • 角色管理

          角色管理

          • 新增
          • 修改
          • 刪除
          • 查詢
          • 導(dǎo)入Excel
          • 下載模板
          • 導(dǎo)出Excel
          • 授權(quán)管理

          如何開始

          在Domain project中新增一個Entity,比如Customer客戶信息

           public partial class Customer : AuditableEntityIHasDomainEvent
              {
                  public int Id { getset; }
                  public string Name { getset; }
                  public string NameOfEnglish { getset; }
                  public string GroupName { getset; }
                  public PartnerType PartnerType { getset; }
                  public string Region { getset; }
                  public string Sales { getset; }
                  public string RegionSalesDirector { getset; }
                  public string Address { getset; }
                  public string AddressOfEnglish { getset; }
                  public string Contract { getset; }
                  public string Email { getset; }
                  public string PhoneNumber { getset; }
                  public string Fax { getset; }
                  public string Comments { getset; }
                  public List<DomainEvent> DomainEvents { getset; } = new();
              }

          在Application project中實現(xiàn)具體的功能請遵循CQRS模式

          • Command
            • AddEdit
            • Delete
            • Import
          • DTOs
          • Eventhandlers
          • Queries
            • Export
            • PaginationQuery

          在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>

          }

          我的項目成果

          網(wǎng)站賬號/密碼截圖
          http://tms.i247365.net/TMS 運輸管理系統(tǒng)[email protected]/123456
          http://manage.i247365.net/ 委托業(yè)務(wù)內(nèi)控管理系統(tǒng)demo/123456
          http://check.i247365.net/ 人臉考勤管理系統(tǒng)demo/123456
          http://supplier.i247365.net/ 供應(yīng)商詢價系統(tǒng)demo/123456
          http://iot.i247365.net/智能水務(wù)綜合管理平臺demo/123456
          http://book.i247365.net/小型圖書管理工具demo/123456

          最后

          keep coding, enjoy coding. 如果你喜歡這個項目,請記得在Github上點贊,謝謝:https://github.com/neozhu/RazorPageCleanArchitecture

          轉(zhuǎn)自:阿新

          鏈接:cnblogs.com/neozhu/p/15149673.html

          瀏覽 69
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩免费色 | 99re视频免费 | 免费一级A毛片 | 日韩一区二区三区四区 | 影音先锋全部av鲁色 |