• OData WebAPI实践-与ABP vNext集成


    本文属于 OData 系列文章


    ABP 是一个流行的 ASP. NET 开发框架,旧版的的 ABP 已经能够非常好的支持了 OData ,并提供了对应的 OData 包。

    ABP vNext 是一个重新设计的,面向微服务的框架,提供了一些非常有用的特性,包括分页查询等但是它并不能原生支持 OData ,我们需要自行实现。

    本文的实现方式本质上为 side by side 方式,由于 ABP vNext 官方没有对应的设计,所以你依然需要自己编写控制器。

    本文使用 ABP CLI 6.0.3 生成的 ABP vNext 项目、Microsoft.AspNetCore.OData 8.1.2

    原理

    ABP vNext 有自动生成 Controller 的机制,我们的 ApplicationService,它会帮我们自动生成对应的终结点,并对外提供服务。这个过程是由 ABP 控制的,我们能修改的内容非常有限。

    	// TodoAppHttpApiHostModule.cs
        private void ConfigureConventionalControllers()
        {
            Configure(options =>
            {
                options.ConventionalControllers.Create(typeof(TodoAppApplicationModule).Assembly, options =>
                    {
                        //// 移除自动生成的控制器
                        //options.ControllerTypes.Remove(typeof(TodoAppController));
                        //options.RootPath = "abp";
                        //// 添加手动实现的控制器
                        //options.ControllerTypes.Add(typeof(TodoAppImplController));
                    });
            });
        }
    

    它依照惯例生成,我们可以对类型进行增加或者减少,但是不能控制生成的行为。而 OData 的控制器,需要我们从 ODataController 继承,或者使用 [EnableQuery],因此我们需要阻止自动生成控制器,自己实现对应的逻辑。

    有了对应的控制器,就需要在应用程序模块中配置 OData 的路由、EDM 等信息,并且不要和原有的控制器路由冲突。

    实现

    首先禁用自动生成控制器功能。

    	//TodoAppService.cs
        [RemoteService(false)]
        public class TodoAppService : ApplicationService, ITodoAppService
        {
            private readonly IRepository _todoItemRepository;
    
            public TodoAppService(IRepository todoItemRepository)
            {
                _todoItemRepository = todoItemRepository;
            }
    
            public async Task> GetListAsync()
            {
                var items = await _todoItemRepository.GetQueryableAsync();
                return items
            .Select(item => new TodoItemDto
            {
                Id = item.Id,
                Text = item.Text
            })
            }
        }
    

    将应用服务打上 [RemoteService(false)] 标记,服务就不会自动生成控制器。接下来在 HttpApi 项目中新建一个与服务同名的控制器,由于 ABP 项目自动生成了控制器抽象类模板,我们继承并实现它即可。

    /* Inherit your controllers from this class.
     */
    public abstract class TodoAppController : AbpControllerBase
    {
        protected TodoAppController()
        {
            LocalizationResource = typeof(TodoAppResource);
        }
    }
    
    
    public class TodoController : TodoAppController
    {
        private readonly ITodoAppService todoAppService;
    
        public TodoController(ITodoAppService todoAppService)
           :base() 
        {
            this.todoAppService = todoAppService;
        }
    
        [EnableQuery]
        public async Task> GetAsync()
        {
            var result = await todoAppService.GetListAsync();
            return result.AsQueryable();
        }
    }
    
    

    注入对应的服务,实现自己的逻辑,如果需要利用 EF Core 的查询功能,请使用 IQueryable 传递数据到控制器层。然后配置 OData :

    	//TodoAppHttpApiHostModule.cs
        private IEdmModel GetEdmModels()
        {
            var builder = new ODataConventionModelBuilder();
            var device = builder.EntitySet("Todo").EntityType.HasKey(w => w.Id);
    
            return builder.GetEdmModel();
        }
    

    记得在 PreConfigureServices 中加上调用。

    	//TodoAppHttpApiHostModule.cs
        public override void PreConfigureServices(ServiceConfigurationContext context)
        {
            PreConfigure(builder =>
            {
                builder.AddValidation(options =>
                {
                    options.AddAudiences("TodoApp");
                    options.UseLocalServer();
                    options.UseAspNetCore();
                });
            });
            // 加上这个调用
            PreConfigure(builder =>
            {
                builder.AddOData(opt =>
                {
                    opt.RouteOptions.EnablePropertyNameCaseInsensitive = true;
                    opt.RouteOptions.EnableQualifiedOperationCall = false;
                    opt.Expand().Filter().Count().OrderBy().Filter().SetMaxTop(30);
                    opt.AddRouteComponents("api/app/", GetEdmModels());
                });
            });
        }
    
    

    运行后,大功告成:

    image

    总结

    本文实现了 OData 在 ABP vNext 中的使用。请注意,本方案只是一个 Demo,应用到生产前请自行评估风险,期待 ABP 团队在未来正式支持 OData 吧。本文的完整代码在 github,运行前可能需要先执行数据库初始化。

  • 相关阅读:
    在Jupyter-lab中使用RDKit画分子2D图
    JQuery ajax 提交数据提示:Uncaught TypeError:Illegal invocation
    简单漂亮的登录页面
    [数据结构]排序算法的性能比较
    基于Qt 多线程(继承自QThread篇)
    centos 7.9同时安装JDK1.8和openjdk11两个版本
    OpenGL笔记五之VBO与VAO
    ZYNQ之FPGA学习----Vivado功能仿真
    数据库系统>并发控制
    Redis数据库【一文教必备操作】
  • 原文地址:https://www.cnblogs.com/podolski/p/17405018.html