码迷,mamicode.com
首页 > 其他好文 > 详细

精简版Abp开发教程 - 第三章: 创建应用程序

时间:2020-10-12 20:35:51      阅读:29      评论:0      收藏:0      [点我收藏+]

标签:startup   file   end   ocs   bpm   解决   contract   精简   生成   

我们基于官方教程并结合下列教程,继续。

创建Book Dto

Acme.BookStore.Application.Contracts中添加BookDto.csCreateUpdateBookDto.cs

namespace Acme.BookStore.Application.Contracts.Dtos
{
    public class BookDto : AuditedEntityDto<Guid>
    {
        public string Name { get; set; }

        public BookType Type { get; set; }

        public DateTime PublishDate { get; set; }

        public float Price { get; set; }
    }
}
namespace Acme.BookStore.Application.Contracts.Dtos
{
    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; }
    }
}

创建AutoMapper配置

Acme.BookStore.Application中添加BookStoreApplicationAutoMapperProfile.cs

namespace Acme.BookStore.Application
{
    public class BookStoreApplicationAutoMapperProfile : Profile
    {
        public BookStoreApplicationAutoMapperProfile()
        {
            CreateMap<Book, BookDto>();
            CreateMap<CreateUpdateBookDto, Book>();
        }
    }
}

创建服务接口

Acme.BookStore.Application.Contracts中添加IBookAppService.cs

namespace Acme.BookStore.Application.Contracts.IServices
{
    public interface IBookAppService :
        ICrudAppService< //定义CRUD方法
            BookDto, //用于展示
            Guid, //实体主键类型
            PagedAndSortedResultRequestDto, //用于分页
            CreateUpdateBookDto> //用于新增或修改
    {

    }
}

创建服务实现

Acme.BookStore.Application中添加BookAppService.cs

namespace Acme.BookStore.Application.Services
{
    public class BookAppService :
        CrudAppService<
            Book, //Book实体
            BookDto, //用于展示
            Guid, //实体主键类型
            PagedAndSortedResultRequestDto, //用于分页
            CreateUpdateBookDto>, //用于新增或修改
        IBookAppService //实现IBookAppService
    {
        public BookAppService(IRepository<Book, Guid> repository)
            : base(repository)
        {

        }
    }
}

创建Swagger API

改造Startup类

Acme.BookStore.WebApi中修改Startup.cs

namespace Acme.BookStore.WebApi
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplication<BookStoreWebApiModule>();//添加Application
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            app.InitializeApplication();//初始化Application
        }
    }
}

在Abp中,原本在Startup中的配置,全部搬到BookStoreWebApiModule中进行配置。
所以Startup最终就剩这几句代码。

编辑BookStoreWebApiModule类

Acme.BookStore.WebApi中添加BookStoreWebApiModule.cs

namespace Acme.BookStore.WebApi
{
    public class BookStoreWebApiModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            var hostingEnvironment = context.Services.GetHostingEnvironment();
            var configuration = context.Services.GetConfiguration();

            ConfigureAutoApiControllers();
            ConfigureSwaggerServices(context.Services);
        }

        public override void OnApplicationInitialization(ApplicationInitializationContext context)
        {
            var app = context.GetApplicationBuilder();
            var env = context.GetEnvironment();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseSwagger();
            app.UseSwaggerUI(options =>
            {
                options.SwaggerEndpoint("/swagger/v1/swagger.json", "Acme.BookStore.WebApi");
            });

            app.UseRouting();
            app.UseConfiguredEndpoints();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    context.Response.Redirect("/swagger");
                });
            });
        }


        private void ConfigureAutoApiControllers()
        {
            Configure<AbpAspNetCoreMvcOptions>(options =>
            {
                //自动创建Controller
                options.ConventionalControllers.Create(typeof(BookStoreApplicationModule).Assembly);
            });
        }


        private void ConfigureSwaggerServices(IServiceCollection services)
        {
            services.AddSwaggerGen(
                options =>
                {
                    options.SwaggerDoc("v1", new OpenApiInfo
                    { Title = "Acme.BookStore.WebApi", Version = "v1.0" });
                    options.DocInclusionPredicate((docName, description) => true);
                    options.CustomSchemaIds(type => type.FullName);
                }
            );
        }
    }
}

这里我们主要是重载2个方法ConfigureServicesOnApplicationInitialization方法。基本可以理解对应Startup的ConfigureServicesConfigure

Acme.BookStore.WebApi中编辑appsettings.json,添加数据库连接

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "AllowedHosts": "*",
    "ConnectionStrings": {
        "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=Acme.BookStore;Trusted_Connection=True;MultipleActiveResultSets=true"
    }
}

有问题?

如果这时候我们运行Acme.BookStore.WebApi,发现报错了!我们该引用的都引用了,为什么还报错?
因为Abp是以Module来定义模块的。解决方案里各个项目层不都是创建了Module类并继承AbpModule吗?
如果你自己写的模块需要使用其他模块(依赖注入),那么须在Module类上添加DependsOn特性代码。不然基本会报错:Some services are not able to be constructed


namespace Acme.BookStore.WebApi
{
    [DependsOn(typeof(AbpAspNetCoreMvcModule),//用到Abp自动生成自动创建Controller方法
        typeof(BookStoreApplicationModule),//用到了Application层,提供服务
        typeof(BookStoreEntityFrameworkCoreModule))]//用到了数据库实现
    public class BookStoreWebApiModule : AbpModule
    {
       ...
    }
}

同理,其他项目中Module类是不是也应该添加DependsOn特性!
Acme.BookStore.Application中编辑BookStoreApplicationModule.cs

namespace Acme.BookStore.Application
{
    [DependsOn(typeof(AbpAutoMapperModule),
        typeof(BookStoreDomainModule),
        typeof(BookStoreApplicationContractsModule))]
    public class BookStoreApplicationModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            Configure<AbpAutoMapperOptions>(options =>
            {
                options.AddMaps<BookStoreApplicationModule>();
            });
        }
    }
}

除了添加DependsOn外,我们还得添加Map配置。options.AddMaps<BookStoreApplicationModule>();会去加载继承Profile的类。

Acme.BookStore.EntityFrameworkCore中编辑BookStoreEntityFrameworkCoreModule.cs

namespace Acme.BookStore.EntityFrameworkCore
{
    [DependsOn(typeof(BookStoreDomainModule),
        typeof(AbpEntityFrameworkCoreSqlServerModule))]
    public class BookStoreEntityFrameworkCoreModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddAbpDbContext<BookStoreDbContext>(options =>
            {
                options.AddDefaultRepositories();//添加Abp默认Repositories实现
            });

            Configure<AbpDbContextOptions>(options =>
            {
                options.UseSqlServer();//使用SqlServer数据库
            });
        }
    }
}

除了添加DependsOn外,我们还得配置数据库及数据仓库。

这时,再运行!发现swagger可以正常浏览了。我们测试一下Book添加方法(post /api/app/book)。先点Try it out按钮,再直接点击Execute按钮。
咦?报错了An internal error occurred during your request!
经过不停错误查找,原来是Acme.BookStore.ApplicationBookAppService所继承的CrudAppService中的ObjectMapper属性报错了。
CrudAppService自带的CreateAsync方法中代码使用ObjectMapper.Map<Book,BookDto>(input)
几经周折,发现需要使用Autofac才行。于是乎,在Acme.BookStore.WebApiProgram.cs添加UseAutofac(),代码如下:

namespace Acme.BookStore.WebApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                })
                .UseAutofac();
    }
}

这里添加完后,我们还得在Acme.BookStore.WebApiBookStoreWebApiModule添加AbpAutofacModule的依赖。

[DependsOn(typeof(AbpAutofacModule), 
        typeof(AbpAspNetCoreMvcModule),//用到Abp自动生成自动创建Controller方法
        typeof(BookStoreApplicationModule),//用到了Application层,提供服务
        typeof(BookStoreEntityFrameworkCoreModule))]//用到了数据库实现
    public class BookStoreWebApiModule : AbpModule
    {
        ...
    }

这时,再运行!发现swagger可以正常浏览了。我们测试一下Book添加方法(post /api/app/book)。先点Try it out按钮,再直接点击Execute按钮。
成功了!再试试其他方法,都返回正确结果。


至此Book应用程序创建成功。

精简版Abp开发教程 - 第三章: 创建应用程序

标签:startup   file   end   ocs   bpm   解决   contract   精简   生成   

原文地址:https://www.cnblogs.com/HUGO_CM/p/13803508.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!