75 changed files with 7649 additions and 21 deletions
File diff suppressed because it is too large
@ -0,0 +1,95 @@ |
|||||
|
using System; |
||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||
|
|
||||
|
#nullable disable |
||||
|
|
||||
|
namespace LY.MicroService.Applications.Single.EntityFrameworkCore.Migrations |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
public partial class AddDemoModule : Migration |
||||
|
{ |
||||
|
/// <inheritdoc />
|
||||
|
protected override void Up(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "Demo_Authors", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
Name = table.Column<string>(type: "varchar(64)", maxLength: 64, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
BirthDate = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
||||
|
ShortBio = table.Column<string>(type: "longtext", nullable: true) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ExtraProperties = table.Column<string>(type: "longtext", nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
||||
|
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
IsDeleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false), |
||||
|
DeleterId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
DeletionTime = table.Column<DateTime>(type: "datetime(6)", nullable: true) |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_Demo_Authors", x => x.Id); |
||||
|
}) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
|
||||
|
migrationBuilder.CreateTable( |
||||
|
name: "Demo_Books", |
||||
|
columns: table => new |
||||
|
{ |
||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
Name = table.Column<string>(type: "varchar(128)", maxLength: 128, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
Type = table.Column<int>(type: "int", nullable: false), |
||||
|
PublishDate = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
||||
|
Price = table.Column<float>(type: "float", nullable: false), |
||||
|
AuthorId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"), |
||||
|
ExtraProperties = table.Column<string>(type: "longtext", nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: false) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"), |
||||
|
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false), |
||||
|
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"), |
||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true), |
||||
|
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci") |
||||
|
}, |
||||
|
constraints: table => |
||||
|
{ |
||||
|
table.PrimaryKey("PK_Demo_Books", x => x.Id); |
||||
|
table.ForeignKey( |
||||
|
name: "FK_Demo_Books_Demo_Authors_AuthorId", |
||||
|
column: x => x.AuthorId, |
||||
|
principalTable: "Demo_Authors", |
||||
|
principalColumn: "Id", |
||||
|
onDelete: ReferentialAction.Cascade); |
||||
|
}) |
||||
|
.Annotation("MySql:CharSet", "utf8mb4"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_Demo_Authors_Name", |
||||
|
table: "Demo_Authors", |
||||
|
column: "Name"); |
||||
|
|
||||
|
migrationBuilder.CreateIndex( |
||||
|
name: "IX_Demo_Books_AuthorId", |
||||
|
table: "Demo_Books", |
||||
|
column: "AuthorId"); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc />
|
||||
|
protected override void Down(MigrationBuilder migrationBuilder) |
||||
|
{ |
||||
|
migrationBuilder.DropTable( |
||||
|
name: "Demo_Books"); |
||||
|
|
||||
|
migrationBuilder.DropTable( |
||||
|
name: "Demo_Authors"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,27 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Authorization.Abstractions" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application.Contracts" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\framework\exporter\LINGYUN.Abp.Exporter.Application.Contracts\LINGYUN.Abp.Exporter.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Demo.Domain.Shared\LINGYUN.Abp.Demo.Domain.Shared.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,15 @@ |
|||||
|
using LINGYUN.Abp.Exporter; |
||||
|
using Volo.Abp.Application; |
||||
|
using Volo.Abp.Authorization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpExporterApplicationContractsModule), |
||||
|
typeof(AbpAuthorizationAbstractionsModule), |
||||
|
typeof(AbpDddApplicationContractsModule), |
||||
|
typeof(AbpDemoDomainSharedModule))] |
||||
|
public class AbpDemoApplicationContractsModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public class AuthorDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public DateTime BirthDate { get; set; } |
||||
|
|
||||
|
public string? ShortBio { get; set; } |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public class CreateAuthorDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(AuthorConsts.MaxNameLength)] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
public DateTime BirthDate { get; set; } |
||||
|
|
||||
|
public string? ShortBio { get; set; } |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public class GetAuthorListDto : PagedAndSortedResultRequestDto |
||||
|
{ |
||||
|
public string? Filter { get; set; } |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public interface IAuthorAppService : IApplicationService |
||||
|
{ |
||||
|
Task<AuthorDto> GetAsync(Guid id); |
||||
|
|
||||
|
Task<PagedResultDto<AuthorDto>> GetListAsync(GetAuthorListDto input); |
||||
|
|
||||
|
Task<AuthorDto> CreateAsync(CreateAuthorDto input); |
||||
|
|
||||
|
Task UpdateAsync(Guid id, UpdateAuthorDto input); |
||||
|
|
||||
|
Task DeleteAsync(Guid id); |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public class UpdateAuthorDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(AuthorConsts.MaxNameLength)] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
public DateTime BirthDate { get; set; } |
||||
|
|
||||
|
public string ShortBio { get; set; } |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public class AuthorLookupDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public class BookDto : AuditedEntityDto<Guid> |
||||
|
{ |
||||
|
[DisplayName("名称")] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
[DisplayName("类型")] |
||||
|
public BookType Type { get; set; } |
||||
|
|
||||
|
[DisplayName("出版日期")] |
||||
|
public DateTime PublishDate { get; set; } |
||||
|
|
||||
|
[DisplayName("价格")] |
||||
|
public float Price { get; set; } |
||||
|
|
||||
|
public Guid AuthorId { get; set; } |
||||
|
|
||||
|
[DisplayName("作者")] |
||||
|
public string AuthorName { get; set; } |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public class BookExportListInput : LimitedResultRequestDto, ISortedResultRequest |
||||
|
{ |
||||
|
[Required] |
||||
|
public string FileName { get; set; } |
||||
|
public string? Filterr { get; set; } |
||||
|
public string? Sorting { get; set; } |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public class BookImportDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(128)] |
||||
|
[DisplayName("名称")] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
[DisplayName("类型")] |
||||
|
public BookType Type { get; set; } = BookType.Undefined; |
||||
|
|
||||
|
[Required] |
||||
|
[DataType(DataType.Date)] |
||||
|
[DisplayName("出版日期")] |
||||
|
public DateTime PublishDate { get; set; } = DateTime.Now; |
||||
|
|
||||
|
[Required] |
||||
|
[DisplayName("价格")] |
||||
|
public float Price { get; set; } |
||||
|
|
||||
|
public Guid AuthorId { get; set; } |
||||
|
|
||||
|
[DisplayName("作者")] |
||||
|
public string AuthorName { get; set; } |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
using Volo.Abp.Content; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public class BookImportInput |
||||
|
{ |
||||
|
[Required] |
||||
|
public IRemoteStreamContent Content { get; set; } |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using System; |
||||
|
using System.ComponentModel.DataAnnotations; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public class CreateUpdateBookDto |
||||
|
{ |
||||
|
[Required] |
||||
|
[StringLength(128)] |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
[Required] |
||||
|
public BookType Type { get; set; } = BookType.Undefined; |
||||
|
|
||||
|
[Required] |
||||
|
[DataType(DataType.Date)] |
||||
|
public DateTime PublishDate { get; set; } = DateTime.Now; |
||||
|
|
||||
|
[Required] |
||||
|
public float Price { get; set; } |
||||
|
|
||||
|
public Guid AuthorId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using LINGYUN.Abp.Exporter; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public interface IBookAppService : |
||||
|
ICrudAppService< //Defines CRUD methods
|
||||
|
BookDto, //Used to show books
|
||||
|
Guid, //Primary key of the book entity
|
||||
|
PagedAndSortedResultRequestDto, //Used for paging/sorting
|
||||
|
CreateUpdateBookDto>, //Used to create/update a book
|
||||
|
IExporterAppService<BookDto, BookExportListInput>, |
||||
|
IImporterAppService<BookImportInput> |
||||
|
{ |
||||
|
Task<ListResultDto<AuthorLookupDto>> GetAuthorLookupAsync(); |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
public static class DemoRemoteServiceConsts |
||||
|
{ |
||||
|
public const string RemoteServiceName = "Demo"; |
||||
|
public const string ModuleName = "demo"; |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using LINGYUN.Abp.Demo.Localization; |
||||
|
using Volo.Abp.Authorization.Permissions; |
||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Permissions; |
||||
|
public class DemoPermissionDefinitionProvider : PermissionDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(IPermissionDefinitionContext context) |
||||
|
{ |
||||
|
var demoGroup = context.AddGroup(DemoPermissions.GroupName, L("Permission:Demo")); |
||||
|
|
||||
|
var booksPermission = demoGroup.AddPermission(DemoPermissions.Books.Default, L("Permission:Books")); |
||||
|
booksPermission.AddChild(DemoPermissions.Books.Create, L("Permission:Books.Create")); |
||||
|
booksPermission.AddChild(DemoPermissions.Books.Edit, L("Permission:Books.Edit")); |
||||
|
booksPermission.AddChild(DemoPermissions.Books.Delete, L("Permission:Books.Delete")); |
||||
|
booksPermission.AddChild(DemoPermissions.Books.Export, L("Permission:Books.Export")); |
||||
|
booksPermission.AddChild(DemoPermissions.Books.Import, L("Permission:Books.Import")); |
||||
|
|
||||
|
var authorsPermission = demoGroup.AddPermission( |
||||
|
DemoPermissions.Authors.Default, L("Permission:Authors")); |
||||
|
authorsPermission.AddChild( |
||||
|
DemoPermissions.Authors.Create, L("Permission:Authors.Create")); |
||||
|
authorsPermission.AddChild( |
||||
|
DemoPermissions.Authors.Edit, L("Permission:Authors.Edit")); |
||||
|
authorsPermission.AddChild( |
||||
|
DemoPermissions.Authors.Delete, L("Permission:Authors.Delete")); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
private static LocalizableString L(string name) |
||||
|
{ |
||||
|
return LocalizableString.Create<DemoResource>(name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
namespace LINGYUN.Abp.Demo.Permissions; |
||||
|
public static class DemoPermissions |
||||
|
{ |
||||
|
public const string GroupName = "Demo"; |
||||
|
|
||||
|
public static class Books |
||||
|
{ |
||||
|
public const string Default = GroupName + ".Books"; |
||||
|
public const string Create = Default + ".Create"; |
||||
|
public const string Edit = Default + ".Edit"; |
||||
|
public const string Delete = Default + ".Delete"; |
||||
|
|
||||
|
public const string Export = Default + ".Export"; |
||||
|
public const string Import = Default + ".Import"; |
||||
|
} |
||||
|
|
||||
|
// *** ADDED a NEW NESTED CLASS ***
|
||||
|
public static class Authors |
||||
|
{ |
||||
|
public const string Default = GroupName + ".Authors"; |
||||
|
public const string Create = Default + ".Create"; |
||||
|
public const string Edit = Default + ".Edit"; |
||||
|
public const string Delete = Default + ".Delete"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Application" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\framework\exporter\LINGYUN.Abp.Exporter.Application\LINGYUN.Abp.Exporter.Application.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Demo.Application.Contracts\LINGYUN.Abp.Demo.Application.Contracts.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Demo.Domain\LINGYUN.Abp.Demo.Domain.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,25 @@ |
|||||
|
using LINGYUN.Abp.Exporter; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Application; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpDddApplicationModule), |
||||
|
typeof(AbpDemoDomainModule), |
||||
|
typeof(AbpExporterApplicationModule), |
||||
|
typeof(AbpDemoApplicationContractsModule))] |
||||
|
public class AbpDemoApplicationModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddAutoMapperObjectMapper<AbpDemoApplicationModule>(); |
||||
|
|
||||
|
Configure<AbpAutoMapperOptions>(options => |
||||
|
{ |
||||
|
options.AddProfile<DemoApplicationMapperProfile>(validate: true); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,89 @@ |
|||||
|
using LINGYUN.Abp.Demo.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
|
||||
|
[Authorize(DemoPermissions.Authors.Default)] |
||||
|
public class AuthorAppService : DemoApplicationServiceBase, IAuthorAppService |
||||
|
{ |
||||
|
private readonly IAuthorRepository _authorRepository; |
||||
|
private readonly AuthorManager _authorManager; |
||||
|
|
||||
|
public AuthorAppService( |
||||
|
IAuthorRepository authorRepository, |
||||
|
AuthorManager authorManager) |
||||
|
{ |
||||
|
_authorRepository = authorRepository; |
||||
|
_authorManager = authorManager; |
||||
|
} |
||||
|
|
||||
|
public async Task<AuthorDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var author = await _authorRepository.GetAsync(id); |
||||
|
return ObjectMapper.Map<Author, AuthorDto>(author); |
||||
|
} |
||||
|
|
||||
|
public async Task<PagedResultDto<AuthorDto>> GetListAsync(GetAuthorListDto input) |
||||
|
{ |
||||
|
if (input.Sorting.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
input.Sorting = nameof(Author.Name); |
||||
|
} |
||||
|
|
||||
|
var authors = await _authorRepository.GetListAsync( |
||||
|
input.SkipCount, |
||||
|
input.MaxResultCount, |
||||
|
input.Sorting, |
||||
|
input.Filter |
||||
|
); |
||||
|
|
||||
|
var totalCount = input.Filter == null |
||||
|
? await _authorRepository.CountAsync() |
||||
|
: await _authorRepository.CountAsync( |
||||
|
author => author.Name.Contains(input.Filter)); |
||||
|
|
||||
|
return new PagedResultDto<AuthorDto>( |
||||
|
totalCount, |
||||
|
ObjectMapper.Map<List<Author>, List<AuthorDto>>(authors) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
[Authorize(DemoPermissions.Authors.Create)] |
||||
|
public async Task<AuthorDto> CreateAsync(CreateAuthorDto input) |
||||
|
{ |
||||
|
var author = await _authorManager.CreateAsync( |
||||
|
input.Name, |
||||
|
input.BirthDate, |
||||
|
input.ShortBio |
||||
|
); |
||||
|
|
||||
|
await _authorRepository.InsertAsync(author); |
||||
|
|
||||
|
return ObjectMapper.Map<Author, AuthorDto>(author); |
||||
|
} |
||||
|
|
||||
|
[Authorize(DemoPermissions.Authors.Edit)] |
||||
|
public async Task UpdateAsync(Guid id, UpdateAuthorDto input) |
||||
|
{ |
||||
|
var author = await _authorRepository.GetAsync(id); |
||||
|
|
||||
|
if (author.Name != input.Name) |
||||
|
{ |
||||
|
await _authorManager.ChangeNameAsync(author, input.Name); |
||||
|
} |
||||
|
|
||||
|
author.BirthDate = input.BirthDate; |
||||
|
author.ShortBio = input.ShortBio; |
||||
|
|
||||
|
await _authorRepository.UpdateAsync(author); |
||||
|
} |
||||
|
|
||||
|
[Authorize(DemoPermissions.Authors.Delete)] |
||||
|
public async Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await _authorRepository.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,206 @@ |
|||||
|
using LINGYUN.Abp.Demo.Authors; |
||||
|
using LINGYUN.Abp.Demo.Permissions; |
||||
|
using LINGYUN.Abp.Exporter; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
using Volo.Abp.Content; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
|
||||
|
[Authorize(DemoPermissions.Books.Default)] |
||||
|
public class BookAppService : |
||||
|
CrudAppService< |
||||
|
Book, //The Book entity
|
||||
|
BookDto, //Used to show books
|
||||
|
Guid, //Primary key of the book entity
|
||||
|
PagedAndSortedResultRequestDto, //Used for paging/sorting
|
||||
|
CreateUpdateBookDto>, //Used to create/update a book
|
||||
|
IBookAppService //implement the IBookAppService
|
||||
|
{ |
||||
|
private readonly IAuthorRepository _authorRepository; |
||||
|
private readonly AuthorManager _authorManager; |
||||
|
|
||||
|
private readonly IExporterProvider _exporterProvider; |
||||
|
private readonly IImporterProvider _importerProvider; |
||||
|
|
||||
|
public BookAppService( |
||||
|
IExporterProvider exporterProvider, |
||||
|
IImporterProvider importerProvider, |
||||
|
IBookRepository bookRepository, |
||||
|
AuthorManager authorManager, |
||||
|
IAuthorRepository authorRepository) |
||||
|
: base(bookRepository) |
||||
|
{ |
||||
|
_exporterProvider = exporterProvider; |
||||
|
_importerProvider = importerProvider; |
||||
|
_authorManager = authorManager; |
||||
|
_authorRepository = authorRepository; |
||||
|
GetPolicyName = DemoPermissions.Books.Default; |
||||
|
GetListPolicyName = DemoPermissions.Books.Default; |
||||
|
CreatePolicyName = DemoPermissions.Books.Create; |
||||
|
UpdatePolicyName = DemoPermissions.Books.Edit; |
||||
|
DeletePolicyName = DemoPermissions.Books.Delete; |
||||
|
} |
||||
|
|
||||
|
public async virtual Task ImportAsync(BookImportInput input) |
||||
|
{ |
||||
|
await CheckCreatePolicyAsync(); |
||||
|
await CheckPolicyAsync(DemoPermissions.Books.Import); |
||||
|
|
||||
|
var stream = input.Content.GetStream(); |
||||
|
var createAuthors = new List<Author>(); |
||||
|
var existsAuthors = new List<Author>(); |
||||
|
var createManyDtos = await _importerProvider.ImportAsync<BookImportDto>(stream); |
||||
|
|
||||
|
foreach (var book in createManyDtos) |
||||
|
{ |
||||
|
var author = existsAuthors.Find(x => x.Name == book.AuthorName) ?? |
||||
|
await _authorRepository.FindByNameAsync(book.AuthorName); |
||||
|
if (author == null) |
||||
|
{ |
||||
|
author = await _authorManager.CreateAsync(book.AuthorName, Clock.Now); |
||||
|
createAuthors.Add(author); |
||||
|
} |
||||
|
if (!existsAuthors.Any(x => x.Name == author.Name)) |
||||
|
{ |
||||
|
existsAuthors.Add(author); |
||||
|
} |
||||
|
book.AuthorId = author.Id; |
||||
|
} |
||||
|
|
||||
|
var createManyBooks = createManyDtos.Select(dto => |
||||
|
{ |
||||
|
var book = ObjectMapper.Map<BookImportDto, Book>(dto); |
||||
|
|
||||
|
TryToSetTenantId(book); |
||||
|
|
||||
|
return book; |
||||
|
}); |
||||
|
|
||||
|
if (createAuthors.Count > 0) |
||||
|
{ |
||||
|
await _authorRepository.InsertManyAsync(createAuthors, autoSave: true); |
||||
|
} |
||||
|
|
||||
|
await Repository.InsertManyAsync(createManyBooks, autoSave: true); |
||||
|
} |
||||
|
|
||||
|
public async virtual Task<IRemoteStreamContent> ExportAsync(BookExportListInput input) |
||||
|
{ |
||||
|
await CheckPolicyAsync(DemoPermissions.Books.Export); |
||||
|
|
||||
|
var bookSet = await Repository.GetQueryableAsync(); |
||||
|
var authorSet = await _authorRepository.GetQueryableAsync(); |
||||
|
|
||||
|
var query = from book in bookSet |
||||
|
join author in authorSet on book.AuthorId equals author.Id |
||||
|
select new { book, author }; |
||||
|
|
||||
|
query = query |
||||
|
.OrderBy(NormalizeSorting(input.Sorting)) |
||||
|
.Take(input.MaxResultCount); |
||||
|
|
||||
|
var queryResult = await AsyncExecuter.ToListAsync(query); |
||||
|
|
||||
|
var bookDtos = queryResult.Select(x => |
||||
|
{ |
||||
|
var bookDto = ObjectMapper.Map<Book, BookDto>(x.book); |
||||
|
bookDto.AuthorName = x.author.Name; |
||||
|
return bookDto; |
||||
|
}).ToList(); |
||||
|
|
||||
|
var stream = await _exporterProvider.ExportAsync(bookDtos); |
||||
|
|
||||
|
return new RemoteStreamContent(stream, input.FileName); |
||||
|
} |
||||
|
|
||||
|
public override async Task<BookDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
//Get the IQueryable<Book> from the repository
|
||||
|
var queryable = await Repository.GetQueryableAsync(); |
||||
|
|
||||
|
//Prepare a query to join books and authors
|
||||
|
var query = from book in queryable |
||||
|
join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id |
||||
|
where book.Id == id |
||||
|
select new { book, author }; |
||||
|
|
||||
|
//Execute the query and get the book with author
|
||||
|
var queryResult = await AsyncExecuter.FirstOrDefaultAsync(query); |
||||
|
if (queryResult == null) |
||||
|
{ |
||||
|
throw new EntityNotFoundException(typeof(Book), id); |
||||
|
} |
||||
|
|
||||
|
var bookDto = ObjectMapper.Map<Book, BookDto>(queryResult.book); |
||||
|
bookDto.AuthorName = queryResult.author.Name; |
||||
|
return bookDto; |
||||
|
} |
||||
|
|
||||
|
public override async Task<PagedResultDto<BookDto>> GetListAsync(PagedAndSortedResultRequestDto input) |
||||
|
{ |
||||
|
//Get the IQueryable<Book> from the repository
|
||||
|
var queryable = await Repository.GetQueryableAsync(); |
||||
|
|
||||
|
//Prepare a query to join books and authors
|
||||
|
var query = from book in queryable |
||||
|
join author in await _authorRepository.GetQueryableAsync() on book.AuthorId equals author.Id |
||||
|
select new { book, author }; |
||||
|
|
||||
|
//Paging
|
||||
|
query = query |
||||
|
.OrderBy(NormalizeSorting(input.Sorting)) |
||||
|
.Skip(input.SkipCount) |
||||
|
.Take(input.MaxResultCount); |
||||
|
|
||||
|
//Execute the query and get a list
|
||||
|
var queryResult = await AsyncExecuter.ToListAsync(query); |
||||
|
|
||||
|
//Convert the query result to a list of BookDto objects
|
||||
|
var bookDtos = queryResult.Select(x => |
||||
|
{ |
||||
|
var bookDto = ObjectMapper.Map<Book, BookDto>(x.book); |
||||
|
bookDto.AuthorName = x.author.Name; |
||||
|
return bookDto; |
||||
|
}).ToList(); |
||||
|
|
||||
|
//Get the total count with another query
|
||||
|
var totalCount = await Repository.GetCountAsync(); |
||||
|
|
||||
|
return new PagedResultDto<BookDto>( |
||||
|
totalCount, |
||||
|
bookDtos |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public async Task<ListResultDto<AuthorLookupDto>> GetAuthorLookupAsync() |
||||
|
{ |
||||
|
var authors = await _authorRepository.GetListAsync(); |
||||
|
|
||||
|
return new ListResultDto<AuthorLookupDto>( |
||||
|
ObjectMapper.Map<List<Author>, List<AuthorLookupDto>>(authors) |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
private static string NormalizeSorting(string? sorting) |
||||
|
{ |
||||
|
if (sorting.IsNullOrEmpty()) |
||||
|
{ |
||||
|
return $"book.{nameof(Book.Name)}"; |
||||
|
} |
||||
|
|
||||
|
if (sorting.Contains("authorName", StringComparison.OrdinalIgnoreCase)) |
||||
|
{ |
||||
|
return sorting.Replace( |
||||
|
"authorName", |
||||
|
"author.Name", |
||||
|
StringComparison.OrdinalIgnoreCase |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
return $"book.{sorting}"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
using AutoMapper; |
||||
|
using LINGYUN.Abp.Demo.Authors; |
||||
|
using LINGYUN.Abp.Demo.Books; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
public class DemoApplicationMapperProfile : Profile |
||||
|
{ |
||||
|
public DemoApplicationMapperProfile() |
||||
|
{ |
||||
|
CreateMap<Book, BookDto>() |
||||
|
.Ignore(dto => dto.AuthorName); |
||||
|
CreateMap<BookImportDto, Book>() |
||||
|
.IgnoreAuditedObjectProperties() |
||||
|
.Ignore(dto => dto.Id) |
||||
|
.Ignore(dto => dto.ExtraProperties) |
||||
|
.Ignore(dto => dto.ConcurrencyStamp); |
||||
|
CreateMap<CreateUpdateBookDto, Book>() |
||||
|
.IgnoreAuditedObjectProperties() |
||||
|
.Ignore(dto => dto.Id) |
||||
|
.Ignore(dto => dto.ExtraProperties) |
||||
|
.Ignore(dto => dto.ConcurrencyStamp); |
||||
|
CreateMap<Author, AuthorDto>(); |
||||
|
CreateMap<Author, AuthorLookupDto>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
public abstract class DemoApplicationServiceBase : ApplicationService |
||||
|
{ |
||||
|
protected DemoApplicationServiceBase() |
||||
|
{ |
||||
|
LocalizationResource = typeof(AbpDemoApplicationModule); |
||||
|
ObjectMapperContext = typeof(AbpDemoApplicationModule); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<None Remove="LINGYUN\Abp\Demo\Localization\Resources\en.json" /> |
||||
|
<None Remove="LINGYUN\Abp\Demo\Localization\Resources\zh-Hans.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<EmbeddedResource Include="LINGYUN\Abp\Demo\Localization\Resources\en.json" /> |
||||
|
<EmbeddedResource Include="LINGYUN\Abp\Demo\Localization\Resources\zh-Hans.json" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Domain.Shared" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,31 @@ |
|||||
|
using LINGYUN.Abp.Demo.Localization; |
||||
|
using Volo.Abp.Domain; |
||||
|
using Volo.Abp.Localization; |
||||
|
using Volo.Abp.Localization.ExceptionHandling; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.VirtualFileSystem; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
|
||||
|
[DependsOn(typeof(AbpDddDomainSharedModule))] |
||||
|
public class AbpDemoDomainSharedModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
Configure<AbpVirtualFileSystemOptions>(options => |
||||
|
{ |
||||
|
options.FileSets.AddEmbedded<AbpDemoDomainSharedModule>(); |
||||
|
}); |
||||
|
|
||||
|
Configure<AbpLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.Resources |
||||
|
.Add<DemoResource>("en") |
||||
|
.AddVirtualJson("/LINGYUN/Abp/Demo/Localization/Resources"); |
||||
|
}); |
||||
|
Configure<AbpExceptionLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.MapCodeNamespace(DemoErrorCodes.Namespace, typeof(DemoResource)); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public static class AuthorConsts |
||||
|
{ |
||||
|
public const int MaxNameLength = 64; |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public enum BookType |
||||
|
{ |
||||
|
Undefined, |
||||
|
Adventure, |
||||
|
Biography, |
||||
|
Dystopia, |
||||
|
Fantastic, |
||||
|
Horror, |
||||
|
Science, |
||||
|
ScienceFiction, |
||||
|
Poetry |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
public static class DemoErrorCodes |
||||
|
{ |
||||
|
public const string Namespace = "Demo"; |
||||
|
|
||||
|
public static class Author |
||||
|
{ |
||||
|
public const string Prefix = Namespace + ":00"; |
||||
|
/// <summary>
|
||||
|
/// 作者 {Name} 已经存在!
|
||||
|
/// </summary>
|
||||
|
public const string AuthorAlreadyExists = Prefix + "001"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using Volo.Abp.Localization; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Localization; |
||||
|
|
||||
|
[LocalizationResourceName("Demo")] |
||||
|
public class DemoResource |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
{ |
||||
|
"culture": "en", |
||||
|
"texts": { |
||||
|
"Permission:Books": "Books", |
||||
|
"Permission:Books.Create": "Create Books", |
||||
|
"Permission:Books.Edit": "Edit Books", |
||||
|
"Permission:Books.Delete": "Delete Books", |
||||
|
"Permission:Books.Export": "Export Books", |
||||
|
"Permission:Books.Import": "Import Books", |
||||
|
"Permission:Authors": "Authors", |
||||
|
"Permission:Authors.Create": "Create Authors", |
||||
|
"Permission:Authors.Edit": "Edit Authors", |
||||
|
"Permission:Authors.Delete": "Delete Authors", |
||||
|
"Demo:00001": "Author {Name} already exists!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
{ |
||||
|
"culture": "zh-Hans", |
||||
|
"texts": { |
||||
|
"Permission:Books": "书籍管理", |
||||
|
"Permission:Books.Create": "新增书籍", |
||||
|
"Permission:Books.Edit": "编辑书籍", |
||||
|
"Permission:Books.Delete": "删除书籍", |
||||
|
"Permission:Books.Export": "导出书籍", |
||||
|
"Permission:Books.Import": "导入书籍", |
||||
|
"Permission:Authors": "作者管理", |
||||
|
"Permission:Authors.Create": "新增作者", |
||||
|
"Permission:Authors.Edit": "编辑作者", |
||||
|
"Permission:Authors.Delete": "删除作者", |
||||
|
"Demo:00001": "作者 {Name} 已经存在!" |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,28 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AutoMapper" /> |
||||
|
<PackageReference Include="Volo.Abp.Ddd.Domain" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\framework\data-protection\LINGYUN.Abp.DataProtection\LINGYUN.Abp.DataProtection.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Demo.Domain.Shared\LINGYUN.Abp.Demo.Domain.Shared.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,37 @@ |
|||||
|
using LINGYUN.Abp.DataProtection; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.AutoMapper; |
||||
|
using Volo.Abp.Domain; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpAutoMapperModule), |
||||
|
typeof(AbpDddDomainModule), |
||||
|
typeof(AbpDataProtectionModule), |
||||
|
typeof(AbpDemoDomainSharedModule))] |
||||
|
public class AbpDemoDomainModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddAutoMapperObjectMapper<AbpDemoDomainModule>(); |
||||
|
|
||||
|
Configure<AbpAutoMapperOptions>(options => |
||||
|
{ |
||||
|
options.AddProfile<DemoDomainMapperProfile>(validate: true); |
||||
|
}); |
||||
|
|
||||
|
//Configure<AbpLocalizationPersistenceOptions>(options =>
|
||||
|
//{
|
||||
|
// options.AddPersistenceResource<DemoResource>();
|
||||
|
//});
|
||||
|
|
||||
|
// 分布式事件
|
||||
|
//Configure<AbpDistributedEntityEventOptions>(options =>
|
||||
|
//{
|
||||
|
// options.AutoEventSelectors.Add<Text>();
|
||||
|
// options.EtoMappings.Add<Text, TextEto>();
|
||||
|
//});
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public class Author : FullAuditedAggregateRoot<Guid> |
||||
|
{ |
||||
|
public string Name { get; private set; } |
||||
|
public DateTime BirthDate { get; set; } |
||||
|
public string? ShortBio { get; set; } |
||||
|
|
||||
|
private Author() |
||||
|
{ |
||||
|
/* This constructor is for deserialization / ORM purpose */ |
||||
|
} |
||||
|
|
||||
|
internal Author( |
||||
|
Guid id, |
||||
|
[NotNull] string name, |
||||
|
DateTime birthDate, |
||||
|
[CanBeNull] string? shortBio = null) |
||||
|
: base(id) |
||||
|
{ |
||||
|
SetName(name); |
||||
|
BirthDate = birthDate; |
||||
|
ShortBio = shortBio; |
||||
|
} |
||||
|
|
||||
|
internal Author ChangeName([NotNull] string name) |
||||
|
{ |
||||
|
SetName(name); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
private void SetName([NotNull] string name) |
||||
|
{ |
||||
|
Name = Check.NotNullOrWhiteSpace( |
||||
|
name, |
||||
|
nameof(name), |
||||
|
maxLength: AuthorConsts.MaxNameLength |
||||
|
); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public class AuthorAlreadyExistsException : BusinessException |
||||
|
{ |
||||
|
public AuthorAlreadyExistsException(string name) |
||||
|
: base(DemoErrorCodes.Author.AuthorAlreadyExists) |
||||
|
{ |
||||
|
WithData("Name", name); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,51 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public class AuthorManager : DomainService |
||||
|
{ |
||||
|
private readonly IAuthorRepository _authorRepository; |
||||
|
|
||||
|
public AuthorManager(IAuthorRepository authorRepository) |
||||
|
{ |
||||
|
_authorRepository = authorRepository; |
||||
|
} |
||||
|
|
||||
|
public async Task<Author> CreateAsync( |
||||
|
[NotNull] string name, |
||||
|
DateTime birthDate, |
||||
|
[CanBeNull] string? shortBio = null) |
||||
|
{ |
||||
|
Check.NotNullOrWhiteSpace(name, nameof(name)); |
||||
|
|
||||
|
var existingAuthor = await _authorRepository.FindByNameAsync(name); |
||||
|
if (existingAuthor != null) |
||||
|
{ |
||||
|
throw new AuthorAlreadyExistsException(name); |
||||
|
} |
||||
|
|
||||
|
return new Author( |
||||
|
GuidGenerator.Create(), |
||||
|
name, |
||||
|
birthDate, |
||||
|
shortBio |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public async Task ChangeNameAsync( |
||||
|
[NotNull] Author author, |
||||
|
[NotNull] string newName) |
||||
|
{ |
||||
|
Check.NotNull(author, nameof(author)); |
||||
|
Check.NotNullOrWhiteSpace(newName, nameof(newName)); |
||||
|
|
||||
|
var existingAuthor = await _authorRepository.FindByNameAsync(newName); |
||||
|
if (existingAuthor != null && existingAuthor.Id != author.Id) |
||||
|
{ |
||||
|
throw new AuthorAlreadyExistsException(newName); |
||||
|
} |
||||
|
|
||||
|
author.ChangeName(newName); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public interface IAuthorRepository : IRepository<Author, Guid> |
||||
|
{ |
||||
|
Task<Author?> FindByNameAsync(string name); |
||||
|
|
||||
|
Task<List<Author>> GetListAsync( |
||||
|
int skipCount, |
||||
|
int maxResultCount, |
||||
|
string sorting, |
||||
|
string? filter = null |
||||
|
); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using LINGYUN.Abp.DataProtection; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public class Book : AuditedAggregateRoot<Guid>, IDataProtected |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
|
||||
|
public BookType Type { get; set; } |
||||
|
|
||||
|
public DateTime PublishDate { get; set; } |
||||
|
|
||||
|
public float Price { get; set; } |
||||
|
|
||||
|
public Guid AuthorId { get; set; } |
||||
|
} |
||||
@ -0,0 +1,6 @@ |
|||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public interface IBookRepository : IRepository<Book, Guid> |
||||
|
{ |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
public static class DemoDbProterties |
||||
|
{ |
||||
|
public static string DbTablePrefix { get; set; } = "Demo_"; |
||||
|
|
||||
|
public static string? DbSchema { get; set; } = null; |
||||
|
|
||||
|
|
||||
|
public const string ConnectionStringName = "Demo"; |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using AutoMapper; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
public class DemoDomainMapperProfile : Profile |
||||
|
{ |
||||
|
public DemoDomainMapperProfile() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,23 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\..\framework\data-protection\LINGYUN.Abp.DataProtection.EntityFrameworkCore\LINGYUN.Abp.DataProtection.EntityFrameworkCore.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Demo.Domain\LINGYUN.Abp.Demo.Domain.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,41 @@ |
|||||
|
using LINGYUN.Abp.Demo.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using System.Linq.Dynamic.Core; |
||||
|
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
public class EfCoreAuthorRepository |
||||
|
: EfCoreRepository<DemoDbContext, Author, Guid>, |
||||
|
IAuthorRepository |
||||
|
{ |
||||
|
public EfCoreAuthorRepository( |
||||
|
IDbContextProvider<DemoDbContext> dbContextProvider) |
||||
|
: base(dbContextProvider) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
public async Task<Author?> FindByNameAsync(string name) |
||||
|
{ |
||||
|
var dbSet = await GetDbSetAsync(); |
||||
|
return await dbSet.FirstOrDefaultAsync(author => author.Name == name); |
||||
|
} |
||||
|
|
||||
|
public async Task<List<Author>> GetListAsync( |
||||
|
int skipCount, |
||||
|
int maxResultCount, |
||||
|
string sorting, |
||||
|
string? filter = null) |
||||
|
{ |
||||
|
var dbSet = await GetDbSetAsync(); |
||||
|
return await dbSet |
||||
|
.WhereIf( |
||||
|
!filter.IsNullOrWhiteSpace(), |
||||
|
author => author.Name.Contains(filter!) |
||||
|
) |
||||
|
.OrderBy(sorting) |
||||
|
.Skip(skipCount) |
||||
|
.Take(maxResultCount) |
||||
|
.ToListAsync(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,17 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using LINGYUN.Abp.DataProtection; |
||||
|
using LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
|
using LINGYUN.Abp.Demo.EntityFrameworkCore; |
||||
|
using Volo.Abp.EntityFrameworkCore; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
public class EfCoreBookRepository : EfCoreDataProtectionRepository<DemoDbContext, Book, Guid>, IBookRepository |
||||
|
{ |
||||
|
public EfCoreBookRepository( |
||||
|
[NotNull] IDbContextProvider<DemoDbContext> dbContextProvider, |
||||
|
[NotNull] IDataAuthorizationService dataAuthorizationService, |
||||
|
[NotNull] IEntityTypeFilterBuilder entityTypeFilterBuilder) |
||||
|
: base(dbContextProvider, dataAuthorizationService, entityTypeFilterBuilder) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
|
using LINGYUN.Abp.Demo.Authors; |
||||
|
using LINGYUN.Abp.Demo.Books; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.EntityFrameworkCore; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpDemoDomainModule), |
||||
|
typeof(AbpDataProtectionEntityFrameworkCoreModule))] |
||||
|
public class AbpDemoEntityFrameworkCoreModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddAbpDbContext<DemoDbContext>(options => |
||||
|
{ |
||||
|
//
|
||||
|
options.AddRepository<Author, EfCoreAuthorRepository>(); |
||||
|
options.AddRepository<Book, EfCoreBookRepository>(); |
||||
|
|
||||
|
options.AddDefaultRepositories(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using LINGYUN.Abp.DataProtection.EntityFrameworkCore; |
||||
|
using LINGYUN.Abp.Demo.Authors; |
||||
|
using LINGYUN.Abp.Demo.Books; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.EntityFrameworkCore; |
||||
|
public class DemoDbContext : AbpDataProtectionDbContext<DemoDbContext> |
||||
|
{ |
||||
|
public DbSet<Book> Books { get; set; } |
||||
|
|
||||
|
public DbSet<Author> Authors { get; set; } |
||||
|
|
||||
|
|
||||
|
public DemoDbContext(DbContextOptions<DemoDbContext> options) : base(options) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
protected override void OnModelCreating(ModelBuilder modelBuilder) |
||||
|
{ |
||||
|
base.OnModelCreating(modelBuilder); |
||||
|
|
||||
|
modelBuilder.ConfigureDemo(); ; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
using LINGYUN.Abp.Demo.Authors; |
||||
|
using LINGYUN.Abp.Demo.Books; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.EntityFrameworkCore.Modeling; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.EntityFrameworkCore; |
||||
|
public static class DemoDbContextModelCreatingExtensions |
||||
|
{ |
||||
|
public static void ConfigureDemo( |
||||
|
this ModelBuilder builder, |
||||
|
Action<DemoModelBuilderConfigurationOptions>? optionsAction = null) |
||||
|
{ |
||||
|
Check.NotNull(builder, nameof(builder)); |
||||
|
|
||||
|
var options = new DemoModelBuilderConfigurationOptions( |
||||
|
DemoDbProterties.DbTablePrefix, |
||||
|
DemoDbProterties.DbSchema |
||||
|
); |
||||
|
optionsAction?.Invoke(options); |
||||
|
|
||||
|
builder.Entity<Book>(b => |
||||
|
{ |
||||
|
b.ToTable(options.TablePrefix + "Books", options.Schema); |
||||
|
b.ConfigureByConvention(); //auto configure for the base class props
|
||||
|
b.Property(x => x.Name).IsRequired().HasMaxLength(128); |
||||
|
|
||||
|
// ADD THE MAPPING FOR THE RELATION
|
||||
|
b.HasOne<Author>().WithMany().HasForeignKey(x => x.AuthorId).IsRequired(); |
||||
|
}); |
||||
|
|
||||
|
builder.Entity<Author>(b => |
||||
|
{ |
||||
|
b.ToTable(options.TablePrefix + "Authors", options.Schema); |
||||
|
|
||||
|
b.ConfigureByConvention(); |
||||
|
|
||||
|
b.Property(x => x.Name) |
||||
|
.IsRequired() |
||||
|
.HasMaxLength(AuthorConsts.MaxNameLength); |
||||
|
|
||||
|
b.HasIndex(x => x.Name); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.EntityFrameworkCore.Modeling; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.EntityFrameworkCore; |
||||
|
public class DemoModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions |
||||
|
{ |
||||
|
public DemoModelBuilderConfigurationOptions( |
||||
|
[NotNull] string tablePrefix = "", |
||||
|
[CanBeNull] string? schema = null) |
||||
|
: base( |
||||
|
tablePrefix, |
||||
|
schema) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,26 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>net8.0</TargetFramework> |
||||
|
<ImplicitUsings>enable</ImplicitUsings> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<GeneratePackageOnBuild>false</GeneratePackageOnBuild> |
||||
|
<IsPackable>false</IsPackable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.Demo.Application.Contracts\LINGYUN.Abp.Demo.Application.Contracts.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,28 @@ |
|||||
|
using LINGYUN.Abp.Demo.Localization; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.AspNetCore.Mvc.Localization; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpAspNetCoreMvcModule), |
||||
|
typeof(AbpDemoApplicationContractsModule))] |
||||
|
public class AbpDemoHttpApiModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
PreConfigure<IMvcBuilder>(mvcBuilder => |
||||
|
{ |
||||
|
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpDemoHttpApiModule).Assembly); |
||||
|
}); |
||||
|
|
||||
|
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
||||
|
{ |
||||
|
options.AddAssemblyResource( |
||||
|
typeof(DemoResource), |
||||
|
typeof(AbpDemoApplicationContractsModule).Assembly); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
using LINGYUN.Abp.Demo.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Authors; |
||||
|
|
||||
|
[Controller] |
||||
|
[Authorize(DemoPermissions.Authors.Default)] |
||||
|
[RemoteService(Name = DemoRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area(DemoRemoteServiceConsts.ModuleName)] |
||||
|
[Route($"api/{DemoRemoteServiceConsts.ModuleName}/authors")] |
||||
|
public class AuthorController : AbpControllerBase, IAuthorAppService |
||||
|
{ |
||||
|
private readonly IAuthorAppService _service; |
||||
|
public AuthorController(IAuthorAppService service) |
||||
|
{ |
||||
|
_service = service; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Authorize(DemoPermissions.Authors.Create)] |
||||
|
public virtual Task<AuthorDto> CreateAsync(CreateAuthorDto input) |
||||
|
{ |
||||
|
return _service.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(DemoPermissions.Authors.Delete)] |
||||
|
public virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return _service.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}")] |
||||
|
public virtual Task<AuthorDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return _service.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public virtual Task<PagedResultDto<AuthorDto>> GetListAsync(GetAuthorListDto input) |
||||
|
{ |
||||
|
return _service.GetListAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(DemoPermissions.Authors.Edit)] |
||||
|
public virtual Task UpdateAsync(Guid id, UpdateAuthorDto input) |
||||
|
{ |
||||
|
return _service.UpdateAsync(id, input); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,81 @@ |
|||||
|
using LINGYUN.Abp.Demo.Permissions; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
using Volo.Abp.Content; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Demo.Books; |
||||
|
|
||||
|
[Controller] |
||||
|
[Authorize(DemoPermissions.Books.Default)] |
||||
|
[RemoteService(Name = DemoRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area(DemoRemoteServiceConsts.ModuleName)] |
||||
|
[Route($"api/{DemoRemoteServiceConsts.ModuleName}/books")] |
||||
|
public class BookController : AbpControllerBase, IBookAppService |
||||
|
{ |
||||
|
private readonly IBookAppService _service; |
||||
|
|
||||
|
public BookController(IBookAppService service) |
||||
|
{ |
||||
|
_service = service; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Authorize(DemoPermissions.Books.Create)] |
||||
|
public virtual Task<BookDto> CreateAsync(CreateUpdateBookDto input) |
||||
|
{ |
||||
|
return _service.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(DemoPermissions.Books.Delete)] |
||||
|
public virtual Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
return _service.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("import")] |
||||
|
public virtual Task ImportAsync([FromForm] BookImportInput input) |
||||
|
{ |
||||
|
return _service.ImportAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("export")] |
||||
|
public virtual Task<IRemoteStreamContent> ExportAsync(BookExportListInput input) |
||||
|
{ |
||||
|
return _service.ExportAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}")] |
||||
|
public virtual Task<BookDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return _service.GetAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("lookup")] |
||||
|
public virtual Task<ListResultDto<AuthorLookupDto>> GetAuthorLookupAsync() |
||||
|
{ |
||||
|
return _service.GetAuthorLookupAsync(); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
public virtual Task<PagedResultDto<BookDto>> GetListAsync(PagedAndSortedResultRequestDto input) |
||||
|
{ |
||||
|
return _service.GetListAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpPut] |
||||
|
[Route("{id}")] |
||||
|
[Authorize(DemoPermissions.Books.Edit)] |
||||
|
public virtual Task<BookDto> UpdateAsync(Guid id, CreateUpdateBookDto input) |
||||
|
{ |
||||
|
return _service.UpdateAsync(id, input); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue