Develop blog project based on abp vNext and. NET Core - perfect and beautify, Swagger comes on stage

Last article( https://www.cnblogs.com/meowv/p/12896898.html )The blog project has been successfully run, so this article is mainly to solve the problems left before. Now the code seems to be confused. There are a lot of unrelated codes in it, which is really zero tolerance for obsessive-compulsive patients.

In the world of programmers, there is always a group of obsessive-compulsive patients who want their code to look as flawless as possible.

Perfection and beautification

Go straight to the theme, first open the project file (. csproj) of each project layer, format it, and add the code without reference to < import project = ".. \.. \ common. Props" / > in fact, this is to take out the public attributes, nothing special.

The code in common.props is also very simple. It is mainly to disable the warnings generated when the output XML is turned on and there is no summary annotation for the code. In fact, these warnings do not need to be tossed about and do not affect the successful operation of the project. If you don't think it's necessary, you can skip this section to the end.

.Application

The. Application layer now only refers to the Volo.Abp.Identity.Application package, and three projects that depend on. Application.Caching,. Application.Contracts,. Domain.Shared.

//Meowv.Blog.Application.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <Import Project="..\..\common.props" />

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Volo.Abp.Identity.Application" Version="2.7.0" />
    
    <ProjectReference Include="..\Meowv.Blog.Application.Caching\Meowv.Blog.Application.Caching.csproj" />
    <ProjectReference Include="..\Meowv.Blog.Application.Contracts\Meowv.Blog.Application.Contracts.csproj" />
    <ProjectReference Include="..\Meowv.Blog.Domain.Shared\Meowv.Blog.Domain.Shared.csproj" />
  </ItemGroup>

</Project>

.Application.Caching

The. Application.Caching layer can be seen from its name. I am going to use it to process the cache. Here, I will use two packages, Volo.Abp.Caching and Microsoft.Extensions.Caching.Redis.

No matter what, a new module class, meowvblogapplicationcacheingmodule.cs, depends on abpcacheingmodule and our MeowvBlogDomainModule (not added at this time)

using Volo.Abp.Caching;
using Volo.Abp.Modularity;

namespace Meowv.Blog.Application.Caching
{
    [DependsOn(
        typeof(AbpCachingModule)
        // ...
    )]
    public class MeowvBlogApplicationCachingModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            base.ConfigureServices(context);
        }
    }
}
//Meowv.Blog.Application.Caching.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <Import Project="..\..\common.props" />

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Caching.Redis" Version="2.2.0" />
    <PackageReference Include="Volo.Abp.Caching" Version="2.7.0" />
    
    <ProjectReference Include="..\Meowv.Blog.Application.Contracts\Meowv.Blog.Application.Contracts.csproj" />
    <ProjectReference Include="..\Meowv.Blog.Domain.Shared\Meowv.Blog.Domain.Shared.csproj" />
    <ProjectReference Include="..\Meowv.Blog.ToolKits\Meowv.Blog.ToolKits.csproj" />
  </ItemGroup>

</Project>

.Application.Contracts

Delete all the files in the. Application.Contracts layer. I'm not going to do the same as abp. In this layer, I just want to put our dto, add the project reference Domain.Shared, and open the output XML file to us. HttpApi.Hosting

Output XML is very simple. In Visual Studio, right-click the project = > attribute = > generate = > output, and then select the XML document file, which is a physical path by default. We change it to the relative path.. \ Meowv.Blog.HttpApi.Hosting\Meowv.Blog.Application.Contracts.xml, and output the XML to the. HttpApi.Hosting layer.

You can also modify the project file directly, as follows

//Meowv.Blog.Application.Contracts.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <Import Project="..\..\common.props" />

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DocumentationFile>..\Meowv.Blog.HttpApi.Hosting\Meowv.Blog.Application.Contracts.xml</DocumentationFile>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\Meowv.Blog.Domain.Shared\Meowv.Blog.Domain.Shared.csproj" />
  </ItemGroup>

</Project>

.Domain

. Domain layer is our entity Domain model. It does not need to refer to other layers. Only add the package Volo.Abp.Identity.Domain. At the same time, output the XML file. The function of the XML file will be used by Swagger later.

//Meowv.Blog.Domain.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <Import Project="..\..\common.props" />

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
    <DocumentationFile>..\Meowv.Blog.HttpApi.Hosting\Meowv.Blog.Domain.xml</DocumentationFile>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Volo.Abp.Identity.Domain" Version="2.7.0" />

    <ProjectReference Include="..\Meowv.Blog.Domain.Shared\Meowv.Blog.Domain.Shared.csproj" />
  </ItemGroup>

</Project>

Delete all files in this layer, and do not forget to add the module class, MeowvBlogDomainModule.cs, which depends on the abpiditydomainmodule module

using Volo.Abp.Identity;
using Volo.Abp.Modularity;

namespace Meowv.Blog.Domain
{
    [DependsOn(typeof(AbpIdentityDomainModule))]
    public class MeowvBlogDomainModule : AbpModule
    {

    }
}

At this time, you can add MeowvBlogDomainModule in Application.Caching above.

//MeowvBlogApplicationCachingModule.cs
...
    [DependsOn(
        typeof(AbpCachingModule),
        typeof(MeowvBlogDomainModule)
    )]
    public class MeowvBlogApplicationCachingModule : AbpModule
    {
        ...
    }
...

.Domain.Shared

. Domain.Shared layer is equivalent to an extension of. Domain. Let's put enumeration and public constants used in the project here. We need to refer to our. Domain project

<Project Sdk="Microsoft.NET.Sdk">

  <Import Project="..\..\common.props" />

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <ProjectReference Include="..\Meowv.Blog.Domain\Meowv.Blog.Domain.csproj" />
  </ItemGroup>

</Project>

Or add a new module class, MeowvBlogDomainSharedModule.cs, which depends on the abpiditydomainsharedmodule module

//MeowvBlogDomainSharedModule.cs
using Volo.Abp.Identity;
using Volo.Abp.Modularity;

namespace Meowv.Blog.Domain
{
    [DependsOn(typeof(AbpIdentityDomainModule))]
    public class MeowvBlogDomainModule : AbpModule
    {
    }
}

.EntityFrameworkCore

. EntityFrameworkCore layer is the same. Delete the default generated file first. It mainly integrates EF Core and custom warehouse. See the abp document for details: https://docs.abp.io/zh-Hans/abp/latest/Repositories

It supports multiple databases such as MySQL, SqlServer, PostgreSql, Sqlite, etc. if you use MongoDB, you need to create a new project and implement it separately. You can see the official documents and share specific methods when you have time, which is not available for this project. https://docs.abp.io/zh-Hans/abp/latest/MongoDB

For your convenience, I integrated the above four mainstream databases into the project, adding packages Volo.Abp.EntityFrameworkCore.MySQL,. PostgreSql,. Sqlite,. SqlServer, and referencing the. Domain.Shared project

//Meowv.Blog.EntityFrameworkCore.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <Import Project="..\..\common.props" />

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>
  
  <ItemGroup>
    <PackageReference Include="Volo.Abp.EntityFrameworkCore.MySQL" Version="2.7.0" />
    <PackageReference Include="Volo.Abp.EntityFrameworkCore.PostgreSql" Version="2.7.0" />
    <PackageReference Include="Volo.Abp.EntityFrameworkCore.Sqlite" Version="2.7.0" />
    <PackageReference Include="Volo.Abp.EntityFrameworkCore.SqlServer" Version="2.7.0" />

    <ProjectReference Include="..\Meowv.Blog.Domain.Shared\Meowv.Blog.Domain.Shared.csproj" />
  </ItemGroup>

</Project>

Create a new module class MeowvBlogFrameworkCoreModule.cs, which depends on MeowvBlogDomainModule and database module

//MeowvBlogFrameworkCoreModule.cs
using Meowv.Blog.Domain;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.EntityFrameworkCore.PostgreSql;
using Volo.Abp.EntityFrameworkCore.Sqlite;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.Modularity;

namespace Meowv.Blog.EntityFrameworkCore
{
    [DependsOn(
        typeof(MeowvBlogDomainModule),
        typeof(AbpEntityFrameworkCoreModule),
        typeof(AbpEntityFrameworkCoreMySQLModule),
        typeof(AbpEntityFrameworkCoreSqlServerModule),
        typeof(AbpEntityFrameworkCorePostgreSqlModule),
        typeof(AbpEntityFrameworkCoreSqliteModule)
    )]
    public class MeowvBlogFrameworkCoreModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {

        }
    }
}

.EntityFrameworkCore.DbMigrations

The. EntityFrameworkCore.DbMigrations layer is mainly used for database migration. It creates database tables in code first mode. First, delete the files generated by default, which are not used at present. Later, I will talk about it.

.ToolKits

The tools layer is a project that we created manually. I mainly use it to wrap some extension methods, public tool classes.

Swagger on stage

Do. net core development, I believe that everyone should be familiar with the use of Swagger, do not do too much introduction, today only use it to see the effect.

I created a new project Meowv.Blog.Swagger for Swagger. In fact, it's unnecessary to write it directly in. Httpapi. Housing.

Add Volo.Abp.AspNetCore and swashblock.aspnetcore packages, referring to entity layer. Domain.

//Meowv.Blog.Swagger.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <Import Project="..\..\common.props" />

  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Volo.Abp.AspNetCore" Version="2.7.0" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.4.1" />

    <ProjectReference Include="..\Meowv.Blog.Domain\Meowv.Blog.Domain.csproj" />
  </ItemGroup>

</Project>

Add the module class MeowvBlogSwaggerModule.cs, rely on the MeowvBlogDomainModule module, and override the ConfigureServices and OnApplicationInitialization methods. Do not know what this is. See the document: https://docs.abp.io/zh-Hans/abp/latest/Module-Development-Basics

Then create a new extension class, MeowvBlogSwaggerExtensions.cs, and write two extension methods, AddSwagger and UseSwaggerUI.

Refer to our XML file in AddSwagger method, configure the name version and description information of the interface, and use SwaggerUI in UseSwaggerUI method. The code is as follows:

//MeowvBlogSwaggerExtensions.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using System;
using System.IO;

namespace Meowv.Blog.Swagger
{
    public static class MeowvBlogSwaggerExtensions
    {
        public static IServiceCollection AddSwagger(this IServiceCollection services)
        {
            return services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo
                {
                    Version = "1.0.0",
                    Title = "My interface",
                    Description = "Interface description"
                });

                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Meowv.Blog.HttpApi.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Meowv.Blog.Domain.xml"));
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, "Meowv.Blog.Application.Contracts.xml"));
            });
        }

        public static void UseSwaggerUI(this IApplicationBuilder app)
        {
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint($"/swagger/v1/swagger.json", "Default interface");
            });
        }
    }
}

You can then reference it in the module MeowvBlogDomainModule

//MeowvBlogSwaggerModule.cs
using Meowv.Blog.Domain;
using Microsoft.AspNetCore.Builder;
using Volo.Abp;
using Volo.Abp.Modularity;

namespace Meowv.Blog.Swagger
{
    [DependsOn(typeof(MeowvBlogDomainModule))]
    public class MeowvBlogSwaggerModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddSwagger();
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            context.GetApplicationBuilder().UseSwagger().UseSwaggerUI();
        }
    }
}

Finally, it is referenced in the startup module of the. HttpApi.Hosting layer.

//MeowvBlogHttpApiHostingModule.cs
...
    [DependsOn(
       typeof(AbpAspNetCoreMvcModule),
       typeof(AbpAutofacModule),
       typeof(MeowvBlogHttpApiModule),
       typeof(MeowvBlogSwaggerModule),
       typeof(MeowvBlogFrameworkCoreModule)
    )]
    public class MeowvBlogHttpApiHostingModule : AbpModule
    {
        ...
    }
...

Ctrl + Shift + B generates the solution. Open Ctrl+F5... / swagger/index.html to see the effect. There is a hole on it that is not filled. I don't know if you find it. Meowv.Blog.HttpApi.xml is not generated. If you start it, you will report an error. You can generate XML by yourself according to the previous method.

Great! Expectations have been met. The reason why Swagger wants to create a project by itself is that it also involves many contents, such as interface grouping, JWT authorization, and Filter for Swagger document description information.

There is still a. BackgroundJobs layer left in the project that hasn't been processed. This layer is ready to integrate Hangfire for a scheduled task processing. It will be used later.

Now, looking back, is the project very refreshing? There is nothing messy, there is only what we need.

The hierarchical directory at this time is for reference.

There may be many unreasonable places in the project. Please refer to them as appropriate. Because the big guys are not willing to share, so we can only do this. If there is any mistake, please correct it. Thank you.

Open source address: https://github.com/Meowv/Blog/tree/blog_tutorial

Tags: xml SDK MySQL PostgreSQL

Posted on Mon, 18 May 2020 19:13:37 -0700 by suresh_nsnguys