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的开发支持。首先我们回顾一下这段代码:

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格式的了:

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

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

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了:

开发人员在开发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:

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参数,代码如下:

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命令,看看结果如何:

可以看到,我们已经在返回的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。敬请期待。

在ASP.NET Core中使用Apworks开发数据服务:对HAL的支持的更多相关文章

  1. 在 asp.net core 中使用类似 Application 的服务

    在 asp.net core 中使用类似 Application 的服务 Intro 在 asp.net 中,我们可以借助 Application 来保存一些服务器端全局变量,比如说服务器端同时在线的 ...

  2. [.NET Core]ASP.NET Core中如何解决接收表单时的不支持的媒体类型(HTTP 415 Unsupported Media Type)错误呢?

    [.NET Core]ASP.NET Core中如何解决接收表单时的不支持的媒体类型(HTTP 415 Unsupported Media Type)错误呢? 在ASP.NET Core应用程序中,接 ...

  3. 在ASP.NET Core中使用Apworks快速开发数据服务

    不少关注我博客的朋友都知道我在2009年左右开发过一个名为Apworks的企业级应用程序开发框架,旨在为分布式企业系统软件开发提供面向领域驱动(DDD)的框架级别的解决方案,并对多种系统架构风格提供支 ...

  4. 【半译】在ASP.NET Core中创建内部使用作用域服务的Quartz.NET宿主服务

    在我的上一篇文章中,我展示了如何使用ASP.NET Core创建Quartz.NET托管服务并使用它来按计划运行后台任务.不幸的是,由于Quartz.NET API的工作方式,在Quartz作业中使用 ...

  5. asp.net core中遇到需要自定义数据包解密方法的时候

    最近将公司的项目用.netcore重写, 服务的http外部接口部分收发消息是DES加解密的, 那么在asp.net core mvc的action处理之前需要加入解密这个步骤. 我第一想到的是用fi ...

  6. NET Core中使用Apworks

    NET Core中使用Apworks HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单.统一的形式,在API中引入超链接特性,使得AP ...

  7. 在Asp.Net Core中使用中间件保护非公开文件

    在企业开发中,我们经常会遇到由用户上传文件的场景,比如某OA系统中,由用户填写某表单并上传身份证,由身份管理员审查,超级管理员可以查看. 就这样一个场景,用户上传的文件只能有三种人看得见(能够访问) ...

  8. 如何在 ASP.NET Core 中构建轻量级服务

    在 ASP.NET Core 中处理 Web 应用程序时,我们可能经常希望构建轻量级服务,也就是没有模板或控制器类的服务. 轻量级服务可以降低资源消耗,而且能够提高性能.我们可以在 Startup 或 ...

  9. 项目开发中的一些注意事项以及技巧总结 基于Repository模式设计项目架构—你可以参考的项目架构设计 Asp.Net Core中使用RSA加密 EF Core中的多对多映射如何实现? asp.net core下的如何给网站做安全设置 获取服务端https证书 Js异常捕获

    项目开发中的一些注意事项以及技巧总结   1.jquery采用ajax向后端请求时,MVC框架并不能返回View的数据,也就是一般我们使用View().PartialView()等,只能返回json以 ...

随机推荐

  1. 【JSON学习之道】js操作JSON

    JSON (JavaScript Object Notation)一种简单的数据格式,比xml更轻巧. JSON 是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON ...

  2. 1. Two Sum★

    题目内容:Given an array of integers, return indices of the two numbers such that they add up to a specif ...

  3. jQuery_小测试

    1.在div元素中,包含了一个<span>元素,通过has选择器获取<div>元素中的<span>元素的语法是? 提示使用has() 2.在<ul>元素 ...

  4. Unbutu14.04 启用 root 并禁用guest

    系统环境: Ubuntu14.04 x64 问题描述: Ubuntu14.04的64位系统默认禁用 root 账号登录 解决方式:            1. 为root设置密码 sudo passw ...

  5. 在.NET项目中使用PostSharp,实现AOP面向切面编程处理

    PostSharp是一种Aspect Oriented Programming 面向切面(或面向方面)的组件框架,适用在.NET开发中,本篇主要介绍Postsharp在.NET开发中的相关知识,以及一 ...

  6. vue关于class和样式的使用

    这篇文章主要为大家详细介绍了Vue.js的Class与样式绑定,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 数据绑定一个常见需求是操作元素的 class 列表和它的内联样式.因为它们都是 att ...

  7. 用Jquery做一个时间日期选择器

    今天我们就用Jquery做一个时间日期选择器,当打开网页时,文本框里面显示的是当前的日期,点击文本框可以出现年.月.日的下拉菜单,并且可以选择,会根据年份的选择判断是否是闰年,从而改变二月的天数,闰年 ...

  8. java构造函数使用方法总结

    使用构造器时需要记住: 1.构造器必须与类同名(如果一个源文件中有多个类,那么构造器必须与公共类同名) 2.每个类可以有一个以上的构造器 3.构造器可以有0个.1个或1个以上的参数 4.构造器没有返回 ...

  9. 在Ubuntu Linux下制作Windows 启动安装 USB盘

    最近想 ,在Ubuntu上刻录个windows的安装U盘,在网上看了些资料,不过好多都说的很模糊,于是乎,我走了不少弯路.这里记录下来,希望了帮到大家. 首先你的有个USB吧,这里我们假定USB在ub ...

  10. Jmeter 正则提取器

    背景: 用户购买商品,为防止CSRF攻击,在购买请求参数中要携带token参数,token的值是随机加密处理的,每次登录值都会刷新 场景: 用户登录站点,访问商品列表,购买商品 脚本设计: 1.登录 ...