Asp.net Zero 应用实战-官方示例PhoneBook学习1_修改1版
适用Zero版本:ASP.NET Core & Angular 2+ (aspnet-zero-core-3.1.0)。
该版本官方有两个solution文件夹:Angular(前端) 和 aspnet-core(后台服务)。
在开始以下步骤之前需要能够成功发布程序,对于后台服务只要能运行即可,如有报错可根据提示安装需要的插件。Angular 则比较麻烦,装的东西较多,官方建议用yarn,这个要下载,顺藤摸瓜都安装完即可。
我没有改解决方案名称,仍用的默认solution的名称MyCompanyName.AbpZeroTemplate,所以下面有的文件名跟官网的phonebook示例文档有区别。
修改1版将aspnet-core后台服务project和Angular前端project的步骤分类,这样不需要跳跃性的操作,阅读操作效率更高。本文仅谈实操,不详细解释理论性的东西,因为本文观点认为,实操没问题了,初学者的信心就有了,理解仅仅是时间问题。
一、aspnet-core后台Project步骤如下:
1、 src/***.core/***CoreModule.cs文件中临时禁用多租户。
- [DependsOn(typeof(AbpZeroCoreModule))]
- public class PhoneBookCoreModule : AbpModule
- {
- public override void PreInitialize()
- {
- //some other code...
- //Enable this line to create a multi-tenant application.
- Configuration.MultiTenancy.IsEnabled = false;
- //some other code...
- }
- }
2、src/***.core/Localization/AbpZeroTemplate/AbpZeroTemplate.xml (默认的英文字体)中加入代码。如有对应中文,可在对应的中文文件中加入中文名称。其他语言中没加的都默认用英文的。
- <text name="PhoneBook">Phone Book</text>
3、创建实体类person。在.Core内新建文件夹People,然后在People文件夹内新建如下Person.cs类。
- using System.ComponentModel.DataAnnotations;
- using System.ComponentModel.DataAnnotations.Schema;
- using Abp.Domain.Entities.Auditing;
- namespace Acme.PhoneBook.People
- {
- [Table("PbPersons")]
- public class Person : FullAuditedEntity
- {
- public const int MaxNameLength = 32;
- public const int MaxSurnameLength = 32;
- public const int MaxEmailAddressLength = 255;
- [Required]
- [MaxLength(MaxNameLength)]
- public virtual string Name { get; set; }
- [Required]
- [MaxLength(MaxSurnameLength)]
- public virtual string Surname { get; set; }
- [MaxLength(MaxEmailAddressLength)]
- public virtual string EmailAddress { get; set; }
- }
- }
4、在.EntityFramework内的****DbContext.cs文件增加如下黄色标记代码。
- public class ******DbContext : AbpZeroDbContext<Tenant, Role, User>
- {
- public virtual IDbSet<Person> Persons { get; set; }
- //...other code
- }
5、用EntityFramework的code first迁移功能更新数据库创建PdPersons表。
在windows command prompt 命令行工具定位到.EntityFramework文件夹。输入:“dotnet ef migrations add "Added_Persons_Table”并回车。
这会在Migrations文件夹中增加一个***Added_Persons_Table.cs类。然后在命令行中输入:“dotnet ef database update”命令,即可在数据库中生成新表。
我在执行这步的时候报错了。提示C:\Program Files\dotnet\shared\Microsoft.NETCore.App 目录里没有1.1.0版本的。原来是我没安装command line版的
.net core 1.1 sdk.官网直接下载即可下载地址:https://www.microsoft.com/net/core#windowscmd 。安装好即可成功更新数据库。
6、为新创建的PdPersons表造点初始数据。
在.EntityFramework空间内的Migrations/seed/host 内新建InitialPeopleCreator.cs类
类代码:
- using System.Linq;
- using Acme.PhoneBook.EntityFramework;
- using Acme.PhoneBook.People;
- namespace Acme.PhoneBook.Migrations.Seed.Host
- {
- public class InitialPeopleCreator
- {
- private readonly PhoneBookDbContext _context;
- public InitialPeopleCreator(PhoneBookDbContext context)
- {
- _context = context;
- }
- public void Create()
- {
- var douglas = _context.Persons.FirstOrDefault(p => p.EmailAddress == "douglas.adams@fortytwo.com");
- if (douglas == null)
- {
- _context.Persons.Add(
- new Person
- {
- Name = "Douglas",
- Surname = "Adams",
- EmailAddress = "douglas.adams@fortytwo.com"
- });
- }
- var asimov = _context.Persons.FirstOrDefault(p => p.EmailAddress == "isaac.asimov@foundation.org");
- if (asimov == null)
- {
- _context.Persons.Add(
- new Person
- {
- Name = "Isaac",
- Surname = "Asimov",
- EmailAddress = "isaac.asimov@foundation.org"
- });
- }
- }
- }
- }
7、在.EntityFramework空间内的Migrations/seed/host 内的InitialHostDbBuilder.cs类里新增如下黄色标记代码。
- public class InitialHostDbBuilder
- {
- //existing codes...
- public void Create()
- {
- //existing code...
- new InitialPeopleCreator(_context).Create();
- _context.SaveChanges();
- }
- }
然后在命令行中执行代码:“dotnet ef database update ” 即可。查看PdPersons表里已有数据。
8、创建person应用程序服务-----------新建一个接口类。
应用程序服务对应.Application空间,在MyCompanyName.AbpZeroTemplate.Application下面建立文件夹People。
然后在People文件夹中新建IPersonAppService.cs接口类.代码如下:
- using Abp.Application.Services;
- using Abp.Application.Services.Dto;
- namespace Acme.PhoneBook.People
- {
- public interface IPersonAppService : IApplicationService
- {
- ListResultDto<PersonListDto> GetPeople(GetPeopleInput input);
- }
- }
9、在People文件夹下面再建立一个文件夹Dto,然后在此新建PersonListDto.cs文件。代码如下:
- using Abp.Application.Services.Dto;
- using Abp.AutoMapper;
- namespace MyCompanyName.AbpZeroTemplate.People.Dto
- {
- [AutoMapFrom(typeof(Person))]
- public class PersonListDto : FullAuditedEntityDto
- {
- public string Name { get; set; }
- public string Surname { get; set; }
- public string EmailAddress { get; set; }
- }
- public class GetPeopleInput
- {
- public string Filter { get; set; }
- }
- }
10、在Pepole文件夹下再建立一个PersonAppService.cs文件。代码如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading.Tasks;
- using Abp.Application.Services.Dto;
- using Abp.AutoMapper;
- using Abp.Domain.Repositories;
- using Abp.Extensions;
- using Abp.Linq.Extensions;
- using MyCompanyName.AbpZeroTemplate.People.Dto;
- namespace MyCompanyName.AbpZeroTemplate.People
- {
- public class PersonAppService:AbpZeroTemplateAppServiceBase,IPersonAppService
- {
- private readonly IRepository<Person> _personRepository;
- public PersonAppService(IRepository<Person> personRepository)
- {
- _personRepository = personRepository;
- }
- public async Task CreatePerson(CreatePersonInput input)
- {
- var person = input.MapTo<Person>();
- await _personRepository.InsertAsync(person);
- }
- public ListResultDto<PersonListDto> GetPeople(GetPeopleInput input)
- {
- var persons = _personRepository
- .GetAll()
- .WhereIf(
- !input.Filter.IsNullOrEmpty(),
- p => p.Name.Contains(input.Filter) ||
- p.Surname.Contains(input.Filter) ||
- p.EmailAddress.Contains(input.Filter)
- )
- .OrderBy(p => p.Name)
- .ThenBy(p => p.Surname)
- .ToList();
- return new ListResultDto<PersonListDto>(persons.MapTo<List<PersonListDto>>());
- }
- }
- }
11、增加Person。
首先再IpersonAppService.cs文件里新增如下代码:
- Task CreatePerson(CreatePersonInput input);
然后在Dto文件内新增类CreatePersonInput.cs类,代码如下:
- using Abp.AutoMapper;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using System.Linq;
- using System.Threading.Tasks;
- namespace MyCompanyName.AbpZeroTemplate.People.Dto
- {
- [AutoMapTo(typeof(Person))]
- public class CreatePersonInput
- {
- [Required]
- [MaxLength(Person.MaxNameLength)]
- public string Name { get; set; }
- [Required]
- [MaxLength(Person.MaxSurnameLength)]
- public string Surname { get; set; }
- [EmailAddress]
- [MaxLength(Person.MaxEmailAddressLength)]
- public string EmailAddress { get; set; }
- }
- }
12、允许创建person对象的授权。
首先加入允许进入phonebook页的授权。在src/***.core/Authorization/AppPermissions.cs文件中加入常量定义:
- public const string Pages_Tenant_PhoneBook = "Pages.Tenant.PhoneBook";
在src/MyCompanyName.AbpZeroTemplate.Application/People里的PersonAppService.cs里加入如下黄色标记代码:
- [AbpAuthorize(AppPermissions.Pages_Tenant_PhoneBook)]
- public class PersonAppService : PhoneBookAppServiceBase, IPersonAppService
- {
- //...
- }
在src/***.core/Authorization/AppAuthorizationProvider.cs类中定义许可,代码如下:
- var phoneBook = pages.CreateChildPermission(AppPermissions.Pages_Tenant_PhoneBook, L("PhoneBook"), multiTenancySides: MultiTenancySides.Tenant);
- phoneBook.CreateChildPermission(AppPermissions.Pages_Tenant_PhoneBook_CreatePerson, L("CreateNewPerson"), multiTenancySides: MultiTenancySides.Tenant);
在同目录下的AppPermissions.cs文件中加入常量定义:
- public const string Pages_Tenant_PhoneBook_CreatePerson = "Pages.Tenant.PhoneBook.CreatePerson";
13、增加ABP授权属性。
在src/MyCompanyName.AbpZeroTemplate.Application/People里的PersonAppService.cs文件中增加属性标记代码如下
- [AbpAuthorize(AppPermissions.Pages_Tenant_PhoneBook_CreatePerson)]
- public async Task CreatePerson(CreatePersonInput input)
- {
- //...
- }
14、删除person实体对象。
在IPersonAppService.cs文件中增加代码:
- Task DeletePerson(EntityDto input);
在PersonAppService.cs文件中增加代码:
- [AbpAuthorize(AppPermissions.Pages_Tenant_PhoneBook_DeletePerson)]
- public async Task DeletePerson(EntityDto input)
- {
- await _personRepository.DeleteAsync(input.Id);
- }
另外提醒一下, 要跟创建person的权限设置一样在AppPermissions.cs文件中定义常量Pages_Tenant_PhoneBook_DeletePerson,
且在src/***.core/Authorization/AppAuthorizationProvider.cs类中定义许可,代码如下:
- phoneBook.DeleteChildPermission(AppPermissions.Pages_Tenant_PhoneBook_DeletePerson, L("DeletePerson"), multiTenancySides: MultiTenancySides.Tenant);
以后这类增删查改不再赘述权限功能的实现。
15、创建Phone 实体。
在src/*******.core下创建Phone.cs类代码如下
- [Table("PbPhones")]
- public class Phone : CreationAuditedEntity<long>
- {
- public const int MaxNumberLength = ;
- [ForeignKey("PersonId")]
- public virtual Person Person { get; set; }
- public virtual int PersonId { get; set; }
- [Required]
- public virtual PhoneType Type { get; set; }
- [Required]
- [MaxLength(MaxNumberLength)]
- public virtual string Number { get; set; }
- }
16、在Person.cs中增加phones字段。
- [Table("PbPersons")]
- public class Person : FullAuditedEntity
- {
- //...other properties
- public virtual ICollection<Phone> Phones { get; set; }
- }
17、在.core下增加PhoneType.cs类
- public enum PhoneType : byte
- {
- Mobile,
- Home,
- Business
- }
18、在Entity Framework下的AbpZeroTemplateDbContext.cs增加代码
- public virtual IDbSet<Phone> Phones { get; set; }
且用命令行命令:dotnet ef migrations add "Added_Phone" 增加数据库phone表的迁移类。
然后更新数据库,该部分类似操作在上文已有介绍,不赘述。
- 该部分未完成待续。。。
19、
20、
二、Angular前端Project步骤如下:
- 1、增加一个新的菜单项。app\shared\layout\side-bar.component.ts (展开side-bar.component.html文件)在dashboard下面加入如下代码
- new SideBarMenuItem("PhoneBook", null, "icon-notebook", "/app/main/phonebook")
2、app\main\main-routing.module.ts 文件中加路由
{ path: 'dashboard', component: DashboardComponent, data: { permission: 'Pages.Tenant.Dashboard' } },
{ path: 'phonebook', component: PhoneBookComponent }
此时phoneBookComponent报错,先忽略不管。
3、在app/main中新建一个phonebook文件夹并创建phonebook.component.ts文件,代码如下:
- import { Component, Injector } from '@angular/core';
- import { AppComponentBase } from '@shared/common/app-component-base';
- import { appModuleAnimation } from '@shared/animations/routerTransition';
- @Component({
- templateUrl: './phonebook.component.html',
- animations: [appModuleAnimation()]
- })
- export class PhoneBookComponent extends AppComponentBase {
- constructor(
- injector: Injector
- ) {
- super(injector);
- }
- }
4、解决第2步的报错问题。在main-routing.module.ts加入import代码:
- import { PhoneBookComponent } from './phonebook/phonebook.component';
5、在app/main/phonebook中新建 phonebook.component.html文件,代码如下:
- <div [@routerTransition]>
- <div class="row margin-bottom-5">
- <div class="col-xs-12">
- <div class="page-head">
- <div class="page-title">
- <h1>
- <span>{{l("PhoneBook")}}</span>
- </h1>
- </div>
- </div>
- </div>
- </div>
- <div class="portlet light margin-bottom-0">
- <div class="portlet-body">
- <p>PHONE BOOK CONTENT COMES HERE!</p>
- </div>
- </div>
- </div>
6、在app/main/main.module.ts文件中添加下面有黄色标记的代码。
- import { NgModule } from '@angular/core';
- import { CommonModule } from '@angular/common';
- import { BrowserModule } from '@angular/platform-browser';
- import { FormsModule } from '@angular/forms';
- import { ModalModule, TabsModule, TooltipModule } from 'ng2-bootstrap';
- import { UtilsModule } from '@shared/utils/utils.module'
- import { AppCommonModule } from '@app/shared/common/app-common.module'
- import { MainRoutingModule } from './main-routing.module'
- import { MainComponent } from './main.component'
- import { DashboardComponent } from './dashboard/dashboard.component';
- import { PhoneBookComponent } from './phonebook/phonebook.component';
- @NgModule({
- imports: [
- BrowserModule,
- CommonModule,
- FormsModule,
- ModalModule.forRoot(),
- TabsModule.forRoot(),
- TooltipModule.forRoot(),
- UtilsModule,
- AppCommonModule,
- MainRoutingModule
- ],
- declarations: [
- MainComponent,
- DashboardComponent,
- PhoneBookComponent
- ]
- })
- export class MainModule { }
保存后刷新前端页面点击phone book后可出来如下页面。
7、更新服务端后台服务(后台新增功能代码时执行)。 在dos命令行工具里先定位到angular所在目录路径,然后输入命令:nswag/refresh.bat 执行更新命令。
8、获取person列表。
首先在 shared/service-proxies/service-proxy.module.ts文件中的对应地方加入如下代码:
- ApiServiceProxies.PersonServiceProxy
修改phonebook.component.ts里的代码如下面的黄色标记处所示:
- import { Component, Injector, OnInit } from '@angular/core';
- import { AppComponentBase } from '@shared/common/app-component-base';
- import { appModuleAnimation } from '@shared/animations/routerTransition';
- import { PersonServiceProxy, PersonListDto, ListResultDtoOfPersonListDto } from '@shared/service-proxies/service-proxies';
- @Component({
- templateUrl: './phonebook.component.html',
- animations: [appModuleAnimation()]
- })
- export class PhoneBookComponent extends AppComponentBase implements OnInit {
- people: PersonListDto[] = [];
- filter: string = '';
- constructor(
- injector: Injector,
- private _personService: PersonServiceProxy
- ) {
- super(injector);
- }
- ngOnInit(): void {
- this.getPeople();
- }
- getPeople(): void {
- this._personService.getPeople(this.filter).subscribe((result) => {
- this.people = result.items;
- });
- }
- }
再替换phonebook.component.html的 <p>PHONE BOOK CONTENT COMES HERE!</p>代码为下面的黄色标记代码:
- <div [@routerTransition]>
- <div class="row margin-bottom-5">
- <div class="col-xs-12">
- <div class="page-head">
- <div class="page-title">
- <h1>
- <span>{{l("PhoneBook")}}</span>
- </h1>
- </div>
- </div>
- </div>
- </div>
- <div class="portlet light margin-bottom-0">
- <div class="portlet-body">
- <h3>{{l("AllPeople")}}</h3>
- <div class="list-group">
- <a *ngFor="let person of people" href="javascript:;" class="list-group-item">
- <h4 class="list-group-item-heading">
- {{person.name + ' ' + person.surname}}
- </h4>
- <p class="list-group-item-text">
- {{person.emailAddress}}
- </p>
- </a>
- </div>
- </div>
- </div>
- </div>
刷新页面
9、新建一个person对象。
首先在phonebook文件夹内创建一个组件create-person-modal.component.ts文件。代码如下:
- import { Component, ViewChild, Injector, ElementRef, Output, EventEmitter } from '@angular/core';
- import { ModalDirective } from 'ng2-bootstrap';
- import { PersonServiceProxy, CreatePersonInput } from '@shared/service-proxies/service-proxies';
- import { AppComponentBase } from '@shared/common/app-component-base';
- @Component({
- selector: 'createPersonModal',
- templateUrl: './create-person-modal.component.html'
- })
- export class CreatePersonModalComponent extends AppComponentBase {
- @Output() modalSave: EventEmitter<any> = new EventEmitter<any>();
- @ViewChild('modal') modal: ModalDirective;
- @ViewChild('nameInput') nameInput: ElementRef;
- person: CreatePersonInput;
- active: boolean = false;
- saving: boolean = false;
- constructor(
- injector: Injector,
- private _personService: PersonServiceProxy
- ) {
- super(injector);
- }
- show(): void {
- this.active = true;
- this.person = new CreatePersonInput();
- this.modal.show();
- }
- onShown(): void {
- $(this.nameInput.nativeElement).focus();
- }
- save(): void {
- this.saving = true;
- this._personService.createPerson(this.person)
- .finally(() => this.saving = false)
- .subscribe(() => {
- this.notify.info(this.l('SavedSuccessfully'));
- this.close();
- this.modalSave.emit(this.person);
- });
- }
- close(): void {
- this.modal.hide();
- this.active = false;
- }
- }
然后创建同名的html文件 create-person-modal.component.html,代码如下:
- <div bsModal #modal="bs-modal" (onShown)="onShown()" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="modal" aria-hidden="true" [config]="{backdrop: 'static'}">
- <div class="modal-dialog">
- <div class="modal-content">
- <form *ngIf="active" #personForm="ngForm" novalidate (ngSubmit)="save()">
- <div class="modal-header">
- <button type="button" class="close" (click)="close()" aria-label="Close">
- <span aria-hidden="true">×</span>
- </button>
- <h4 class="modal-title">
- <span>{{l("CreateNewPerson")}}</span>
- </h4>
- </div>
- <div class="modal-body">
- <div class="form-group form-md-line-input form-md-floating-label no-hint">
- <input #nameInput class="form-control" type="text" name="name" [(ngModel)]="person.name" required maxlength="32">
- <label>{{l("Name")}}</label>
- </div>
- <div class="form-group form-md-line-input form-md-floating-label no-hint">
- <input class="form-control" type="email" name="surname" [(ngModel)]="person.surname" required maxlength="32">
- <label>{{l("Surname")}}</label>
- </div>
- <div class="form-group form-md-line-input form-md-floating-label no-hint">
- <input class="form-control" type="email" name="emailAddress" [(ngModel)]="person.emailAddress" required maxlength="255" pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{1,})+$"> <label>{{l("EmailAddress")}}</label>
- </div>
- </div>
- <div class="modal-footer">
- <button [disabled]="saving" type="button" class="btn btn-default" (click)="close()">{{l("Cancel")}}</button>
- <button type="submit" class="btn btn-primary blue" [disabled]="!personForm.form.valid" [buttonBusy]="saving" [busyText]="l('SavingWithThreeDot')"><i class="fa fa-save"></i> <span>{{l("Save")}}</span></button>
- </div>
- </form>
- </div>
- </div>
- </div>
接着在main.module.ts类里加入如下黄色标记代码:
- ...previous imports
- import { CreatePersonModalComponent } from './phonebook/create-person-modal.component';
- @NgModule({
- imports: [
- ...existing module imports...
- ],
- declarations: [
- MainComponent,
- DashboardComponent,
- PhoneBookComponent,
- CreatePersonModalComponent
- ]
- })
- export class MainModule { }
最后,在phonebook.component.html文件里加入如下黄色标记代码:
- <div [@routerTransition]>
- <div class="row margin-bottom-5">
- <div class="col-xs-6">
- <div class="page-head">
- <div class="page-title">
- <h1>
- <span>{{l("PhoneBook")}}</span>
- </h1>
- </div>
- </div>
- </div>
- <div class="col-xs-6 text-right">
- <button class="btn btn-primary blue" (click)="createPersonModal.show()"><i class="fa fa-plus"></i> {{l("CreateNewPerson")}}</button>
- </div>
- </div>
- <div class="portlet light margin-bottom-0">
- <div class="portlet-body">
- <h3>{{l("AllPeople")}}</h3>
- <div class="list-group">
- <a *ngFor="let person of people" href="javascript:;" class="list-group-item">
- <h4 class="list-group-item-heading">
- {{person.name + ' ' + person.surname}}
- </h4>
- <p class="list-group-item-text">
- {{person.emailAddress}}
- </p>
- </a>
- </div>
- </div>
- </div>
- <createPersonModal #createPersonModal (modalSave)="getPeople()"></createPersonModal>
- </div>
10、隐藏未授权的button按钮。
打开phonebook.component.html文件。在button处加入下面的黄色标记代码:
- <button *ngIf="isGranted('Pages.Tenant.PhoneBook.CreatePerson')" class="btn btn-primary blue" (click)="createPersonModal.show()"><i class="fa fa-plus"></i> {{l("CreateNewPerson")}}</button>
11、删除peson对象。
修改phonebook.component.html文件,增加如下黄色标记处代码:
- ...
- <h3>{{l("AllPeople")}}</h3>
- <div class="list-group">
- <a *ngFor="let person of people" href="javascript:;" class="list-group-item">
- <h4 class="list-group-item-heading">
- {{person.name + ' ' + person.surname}}
- <button (click)="deletePerson(person)" title="{{l('Delete')}}" class="btn btn-circle btn-icon-only red delete-person" href="javascript:;">
- <i class="icon-trash"></i>
- </button>
- </h4>
- <p class="list-group-item-text">
- {{person.emailAddress}}
- </p>
- </a>
- </div>
- ...
12、使用LESS样式将按钮移至右边。
在phonebook文件夹下创建phonebook.component.less样式文件,代码如下:
- .list-group-item-heading {
- button.delete-person {
- float: right;
- }
- }
在 phonebook.component.ts 文件中引入样式文件,代码如黄色标记:
- @Component({
- templateUrl: './phonebook.component.html',
- styleUrls: ['./phonebook.component.less'],
- animations: [appModuleAnimation()]
- })
13、在phonebook.component.ts内添加删除功能代码:
- deletePerson(person: PersonListDto): void {
- this.message.confirm(
- this.l('AreYouSureToDeleteThePerson', person.name),
- isConfirmed => {
- if (isConfirmed) {
- this._personService.deletePerson(person.id).subscribe(() => {
- this.notify.info(this.l('SuccessfullyDeleted'));
- _.remove(this.people, person);
- });
- }
- }
- );
- }
并且在@Component标记前增加引入代码:
- import * as _ from 'lodash';
14、
15、
16、
未完待续。。。
Asp.net Zero 应用实战-官方示例PhoneBook学习1_修改1版的更多相关文章
- Asp.net Zero 应用实战-官方示例PhoneBook学习1
适用Zero版本:ASP.NET Core & Angular 2+ (aspnet-zero-core-3.1.0). 该版本官方有两个solution文件夹:Angular(前端) 和 a ...
- gRPC官方快速上手学习笔记(c#版)
上手前准备工作 支持操作系统:windows.OS X.Linux.实例采用.net..net core sdk. The .NET Core SDK command line tools. The ...
- Asp.Net Core 项目实战之权限管理系统(0) 无中生有
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- Asp.Net Core 项目实战之权限管理系统(6) 功能管理
0 Asp.Net Core 项目实战之权限管理系统(0) 无中生有 1 Asp.Net Core 项目实战之权限管理系统(1) 使用AdminLTE搭建前端 2 Asp.Net Core 项目实战之 ...
- 【无私分享:ASP.NET CORE 项目实战(第十四章)】图形验证码的实现
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 很长时间没有来更新博客了,一是,最近有些忙,二是,Core也是一直在摸索中,其实已经完成了一个框架了,并且正在准备在生产环境中 ...
- 【无私分享:ASP.NET CORE 项目实战(第十三章)】Asp.net Core 使用MyCat分布式数据库,实现读写分离
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 MyCat2.0版本很快就发布了,关于MyCat的动态和一些问题,大家可以加一下MyCat的官方QQ群:106088787.我 ...
- 【无私分享:ASP.NET CORE 项目实战(第十二章)】添加对SqlServer、MySql、Oracle的支持
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 增加对多数据库的支持,并不是意味着同时对多种数据库操作,当然,后面,我们会尝试同时对多种数据库操作,这可能需要多个上下文,暂且 ...
- 【无私分享:ASP.NET CORE 项目实战(第十一章)】Asp.net Core 缓存 MemoryCache 和 Redis
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 经过 N 久反复的尝试,翻阅了网上无数的资料,GitHub上下载了十几个源码参考, Memory 和 Redis 终于写出一个 ...
- 【无私分享:ASP.NET CORE 项目实战(第七章)】文件操作 FileHelper
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 在程序设计中,我们很多情况下,会用到对文件的操作,在 上一个系列 中,我们有很多文件基本操作的示例,在Core中有一些改变,主 ...
随机推荐
- URL 传递问题
工作日记: ----更正:如下做改成%26是不行的.正在寻求解决方法 在K2邮件发送正文中我拼接了URL如:http://shisupportqa:8090/WorkflowPages/SendFil ...
- drf框架之分页器的用法
1. 分页器分为:简单分页器与偏移分页器和加密分页器 2.实现一个简单的分页器的用法: # 简单分页 # 第一步,导入分页类 # from rest_framework.pagination impo ...
- DEDECMS 多站用一个站图片
function replaceurl($newurl) { $newurl=str_replace('src="/uploads/allimg/','src="xxx.com/u ...
- html:input的type=number的时候maxlength失效问题
<input type="text" maxlength="5" /> 效果ok,当 <input type="number& ...
- VirtualBox安装Ubuntu16.04过程
1. 软件版本 Windows: Win7/Win10 VirtualBox: VirtualBox-6.0.24-108355-Win Ubuntu: ubuntu-16.04-desktop-am ...
- xmlns 啥意思
参考:https://blog.csdn.net/zhch152/article/details/8191377 前提科普:DTD 文档类型定义(Document Type Definition) 问 ...
- Java开发中的23种设计模式(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- python之全局变量与局部变量
全局变量: - 在书写中顶格开始: - 一旦定义完毕在整个文件生效: - 在函数内如果定义了同名全局变量名,会“覆盖”掉全局变量: - 在函数中同名的变量,当在函数退出后消失,全局的同 ...
- contains用法
判断List<UserInfoDto>里是否有重复的UserInfoDto,不能使用contains 例: List<UserInfoDto> list = new Array ...
- Java成员变量与局部变量的区别
从语法形式上看,成员变量是属于类的,而局部变量是在方法中定义的变量或是方法的参数:成员变量可以被public,private,static等修饰符所修饰,而局部变量不能被访问控制修饰符及static所 ...