• NET Core中使用Apworks


    NET Core中使用Apworks

    HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单、统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable)更强,并具有自描述的特点。使用了HAL的API会更容易地被第三方开源库所调用,并且使用起来也很方便,开发者可以像处理普通JSON数据那样去处理API数据。有关HAL的更多信息,可以参考官方网站:http://stateless.co/hal_specification.html。目前,很多RESTful服务开发框架都支持HAL的Response格式(Content-Type为application/hal+json),比如大名鼎鼎的Spring Data,默认就支持HAL。现在,使用全新的Apworks Core(今后简称Apworks)开发数据服务时,默认也提供对HAL的支持。

    HAL的启用和禁用

    上一篇快速开发文章中,演练部分通过修改Startup.cs文件中的ConfigureServices方法以在ASP.NET Core Web API中启用Apworks以及Data Service的开发支持。首先我们回顾一下这段代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();
     
        services.AddApworks()
            .WithDataServiceSupport(new DataServiceConfigurationOptions
                (new MongoRepositoryContext
                    (new MongoRepositorySettings("localhost", "customer-service"))))
            .Configure();
    }

    默认情况下,HAL的支持是启用的。也就是说,当你运行Data Service时,直接发起HTTP GET请求,返回的Response已经是application/hal+json格式的了:

    image

    注意:由于返回的数据量并没有超出一页的分页尺寸,所以在_links下仅显示了一个self的链接。如果存在多个分页,那么_links部分也会出现prev、next、first、last等链接。

    如果希望禁用HAL的功能,其实非常简单,在上面的代码中,在构造DataServiceConfigurationOptions时直接指定useHalSupport参数为false即可:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();
     
        services.AddApworks()
            .WithDataServiceSupport(new DataServiceConfigurationOptions
                (new MongoRepositoryContext
                    (new MongoRepositorySettings("localhost", "customer-service")), useHalSupport: false))
            .Configure();
    }

    于是,得到的返回内容就不再是application/hal+json,而是application/json了:

    image

    开发人员在开发Data Service的时候,可以根据自己的需求启用或者禁用HAL的支持。

    自定义HAL的返回内容

    在ASP.NET Core Web API中使用Apworks开发数据服务时,对于HAL的返回内容是可以自定义的。当然,这并不会改变HTTP Response的Content-Type,而是针对Response Body,其Json内容是可以被自定义的。例如,在上面的例子中,HTTP GET的Response Body中不仅包含所请求的数据对象数组(customers),而且还包含分页信息,以及一个含有分页链接的_links的对象。在实现Data Service的时候,如果这些返回内容不能满足需求,开发人员完全可以自定义。

    举个例子,假设我们希望在返回内容中包含当前的服务器时间,其开发过程如下。

    首先,新建一个继承于Apworks.Integration.AspNetCore.DataServices.DataServiceHalBuildConfiguration的类型,取名为ServerTimeHalBuildConfiguration

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    using Apworks.Integration.AspNetCore.DataServices;
    using Hal.Builders;
    using Microsoft.AspNetCore.Http.Extensions;
    using System;
     
    namespace CustomerService
    {
        public class ServerTimeHalBuildConfiguration : DataServiceHalBuildConfiguration
        {
            protected override void RegisterHalBuilderFactoryForGetAll()
            {
                this.RegisterHalBuilderFactory("*.Get(int, int)", context =>
                    new ResourceBuilder()
                        .WithState(new { ServerTime = DateTime.UtcNow })
                        .AddSelfLink().WithLinkItem(context.HttpContext.Request.GetEncodedUrl())
                        .AddEmbedded(context.ControllerAction.ControllerName.ToLower())
                            .Resource(new ResourceBuilder().WithState(context.State))
                );
            }
        }
    }

    然后,回到Startup.cs文件中的ConfigureServices方法,在DataServiceConfigurationOptions的构造函数参数中,指定halBuildConfigurationFactory参数,代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();
     
        services.AddApworks()
            .WithDataServiceSupport(new DataServiceConfigurationOptions
                (new MongoRepositoryContext
                    (new MongoRepositorySettings("localhost", "customer-service")),
                    halBuildConfigurationFactory: _ => new ServerTimeHalBuildConfiguration()))
            .Configure();
    }

    OK,任务完成,测试一下。打开MINGW,执行curl http://localhost:2238/api/customers -i命令,看看结果如何:

    image

    可以看到,我们已经在返回的HAL结果中加入了服务器的UTC时间,同时,还是保留了_self的链接。不过,分页的链接没有包含在内,这是因为我们通过override重写了RegisterHalBuilderFactoryForGetAll方法。你可以参考Apworks框架源代码中的Apworks.Integration.AspNetCore.DataServices.DataServiceHalBuildConfiguration类来了解如何将分页的链接加入到HAL的返回结果中。

    大致对上面的代码做一些介绍:

    1. DataServiceHalBuildConfiguration及其子类主要负责对HAL Resource BuilderBuilder模式,[GoF95])的定义和注册,它能将某一个HAL的资源构造器(Resource Builder)关联到某一个ASP.NET Core Web API的控制器上
    2. RegisterHalBuilderFactory方法会根据其第一个参数(ControllerActionSignature)确定一个ASP.NET Core Web API的Controller Action方法,并将第二个参数所指定的HAL Resource Builder工厂方法委托(Delegate)注册到由ControllerActionSignature指定的Controller Action方法上
    3. HalResultFilterAttribute类中,当Controller Action执行完成时,会根据所注册的Hal Resource Builder Factory来获取最终的HAL内容(通过调用ResourceBuilder的Build方法),然后将产生的HAL以application/hal+json格式返回
    4. SupportsHalAttribute类中会根据是否存在一个IHalBuildConfiguration的Service注册,来确定是否使用HAL的返回内容
    5. DataServiceController类已经使用了SupportsHalAttribute,因此,它具有使用HAL功能的能力,那么继承于它的控制器都会被应用SupportsHalAttribute特性,因此,你开发的数据服务控制器(Data Service Controller)无需关注HAL的功能
    6. 最后,在DataServiceConfigurationOptions类的构造函数中,通过指定useHalSupport以及halBuildConfigurationFactory两个参数,来决定是否需要HAL的支持,以及如何产生HAL的结果

    事实上,如果你不打算使用DataServiceController来快速开发数据服务,而是希望使用传统的方式自己开发自己的RESTful服务,你完全可以使用Apworks.Integration.AspNetCore.Hal命名空间下的类型来使得你的RESTful服务也支持流行的HAL,而且开发过程非常方便。由此可见,Apworks.Integration.AspNetCore中对HAL的支持并不是专为框架本身的数据服务开发而设计的,它能够应用于普通的RESTful服务的开发,数据服务只不过是HAL的一个客户而已。

    总结

    本文介绍了Apworks数据服务开发中对HAL的支持,可以看到,Apworks框架的设计是:

    1. 灵活的:通过不同的配置信息来干预数据服务的执行过程,同时还支持自定义扩展来定制自己的数据服务
    2. 通用的:组件的设计尽可能达到通用性,比如HAL的机制,它不仅仅是Apworks数据服务的“特供”,它可以被应用在任何由ASP.NET Core Web API所开发的RESTful服务上
    3. 开发体验友好的:简单的API定义使得应用程序快速开发成为可能,Fluent Interface API(流畅接口)的设计,使得开发者能够用更为自然的语言来完成所需要的功能操作,大大提升开发生产率。在Apworks的整个框架中,会更多地引入流畅接口以便保持较好的开发者体验

    就HAL这部分来说,它利用了ASP.NET Core中的ResultFilter以及Filter Factory,建议大家可以了解一下HAL以及Data Service的相关代码,来熟悉ASP.NET Core中Filter的相关内容。

    值得一提的是,Apworks中对HAL的支持使用的正是我自己开发的HAL库,这套库也是开源的,开源地址是:https://github.com/daxnet/hal,它是为数较少的完整实现HAL规范,并支持.NET Core的HAL开发库,同样,它支持流畅接口。

    下一讲打算介绍一下如何在Apworks数据服务中使用Entity Framework Core。敬请期待。

  • 相关阅读:
    2019年春季学期第三周作业
    2019年春季学期第二周作业
    7-2 求最大值及其下标 (20 分)
    7-1 查找整数 (10 分)
    人生中最重要的三位老师
    自我介绍
    学期总结
    编程作业 抓老鼠啊~亏了还是赚了?
    作业——10
    作业——9
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/6703902.html
Copyright © 2020-2023  润新知