Add HAL support for RESTful services in ASP. NET Core Web APIs, restfulhal
HAL (Hyper Text Application Language) is a RESTful API data format style that provides interface specifications for RESTful API design, it also reduces the coupling between the client and the server interface. Many popular RESTful API development frameworks, including Spring REST, also support HAL specifications by default. When a RESTful API is called, the server returns the json content whose ContentType is application/hal + JSON. For example:
{ "_links": { "self": { "href": "http://example.com/api/book/hal-cookbook" } }, "_embedded": { "author": { "_links": "self": { "href": "http://author-example.com" } }, "id": "shahadat", "name": "Shahadat Hossain Khan" } }, "id": "hal-cookbook", "name": "HAL Cookbook"}
Compared with the result of returning only one id and one name, such JSON Response contains more information, such as the API address of the current request and the author information of the book HAL Cookbook, and hypertext links used to access the author's information. After obtaining the response from this server, the client can easily bind the information to the interface without calling multiple APIs to find the associated information. On the other hand, hypertext links contained in the JSON Response can also be dynamic, such as paging navigation links, which makes it very convenient for the client to implement paging functions. This article focuses on how to add HAL support for self-designed RESTful APIs in ASP. NET Core Web APIs.
Apworks framework
Adding HAL support for RESTful services in ASP. NET Core Web APIs is achieved through the Apworks framework and HAL framework. Both frameworks are self-designed and developed open-source frameworks. The former is based on Apache 2.0 open-source, and the latter is based on MIT open-source. Therefore, they can be used for commercial system development. The HAL project provides basic data models and processing logic for Hypertext Application Language. It supports JSON based on the well-known Newtonsoft. json, so the performance can be guaranteed. The convenient and convenient Fluent Interface API programming method makes it easy to build a complete and reasonable HAL object model. HAL project design uses some object structured mode, interested friends can go to Github project home page (https://github.com/daxnet/hal) to learn about.
As for the Apworks framework, its main functions are not just for ASP. NET Core Web API provides HAL support. More importantly, it is based on. NET Core's microservice rapid development framework not only provides basic construction elements (aggregation, entity, warehouse, factory, etc.) for the domain-oriented drive (DDD ), it also integrates the microservice architecture function modules such as message queue, message distribution and subscription, message processing, query service, and event storage, it is implemented based on basic services such as MongoDB, Entity Framework, RabbitMQ, PostgreSQL, and SQL Server. At present, the entire framework is still in the development and improvement phase. If you are interested, you can go to the Apworks Examples case project to view the case code of the Apworks framework. The case code is also being updated at the same time. After all the case code is developed, I will release a relatively stable version of The Apworks framework.
It is worth mentioning that Apworks. Integration. AspNetCore Package in the Apworks framework provides the development and extension of ASP. NET Core Web API, and HAL support is also part of the Package. OK. The Apworks framework and HAL framework are not the focus of this article. Next, let's take a look at how to quickly implement HAL support in ASP. NET Core Web API.
Simplest case
In fact. NET Core uses Apworks to develop data services: Support for HAL. In this article, I have introduced how to quickly build data services in Apworks and provide the HAL JSON data format. At that time, the case was to meet the data service development model. For example, the warehouse instance needs to be injected, and the Controller needs to provide GET, POST, PUT, and DELETE operations by default. This is too heavy for general Web API Controller that only needs to implement certain functions. So let's start with the simplest case.
- Open Visual Studio 2017 and create an ASP. NET Core Web API ,.. NET Framework is recommended. NET Core/ASP. NET Core 2.0. Select Web API as the project template. A default ASP is generated.. NET Core 2.0 Web API application. Docker support can be temporarily disabled
- Directly start the ASP. NET Core Web API application. By default, value1 and value2 values are output in the browser:
Public void ConfigureServices (IServiceCollection services) {services. addMvc (); var halBuildConfiguration = new HalBuildConfiguration (new HalBuildConfigurationItem [] {new HalBuildConfigurationItem ("Values. get ", context => new ResourceBuilder (). withState (null ). addSelfLink (). withLinkItem (context. httpContext. request. getDisplayUrl ()). addEmbedded ("values "). resource (new ResourceBuilder (). withState (context. state)}); services. addApworks (). withHalSupport (halBuildConfiguration ). configure ();}
- Double-click the ValuesController. cs file and add the SupportsHal feature to the Get () method:
[HttpGet][SupportsHal]public IEnumerable<string> Get(){ return new string[] { "value1", "value2" };}
- Run the command again. The returned result is in hal json format and the Content-Type is application/hal + json:
[HttpGet] [SupportsHal] public IActionResult Get (int page = 1, int size = 5) {var values = new [] {"a", "B", "c ", "d", "e", "f", "g", "h", "I", "j", "k", "l", "m ", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w ", "x", "y", "z"}; var skip = (page-1) * size; var take = size; var records = values. length; var pages = (records + size-1)/size; return OK (new PagedResult (values. skip (skip ). take (take), page, size, records, pages ));}
- Modify Startup. cs file, change the ConfigureServices Method to the following code. Note that the first parameter of HalBuildConfigurationItem has become Values. get (int, int) indicates the Get method that matches two int type parameters in ValuesController:
public void ConfigureServices(IServiceCollection services){ services.AddMvc(); services.AddApworks() .WithHalSupport(new PagedResultHalBuildConfiguration("Values.Get(int, int)")) .Configure();}
- Ctrl + F5 run the Web API application directly and output the following in the browser:
[HttpGet] [SupportsHal] public IActionResult Get ([PageNumber] int p = 1, int size = 5) {var values = new [] {"a", "B ", "c", "d", "e", "f", "g", "h", "I", "j", "k", "l ", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v ", "w", "x", "y", "z"}; var skip = (p-1) * size; var take = size; var records = values. length; var pages = (records + size-1)/size; return OK (new PagedResult (values. skip (skip ). take (take), p, size, records, pages ));}We use PageNumberAttribute to specify the parameter p as the paging parameter. when accessing data on a specific page, you can use http: // localhost: 52566/api/values? P = 2:
// LettersResponse. tsexport class LettersResponse {public first: string; public prev: string; public next: string; public last: string; public values: string [];} // my-letters-service.service.ts @ Injectable () export class MyLettersServiceService {constructor (private http: Http) {} getLetters (url: string): Promise <LettersResponse> {return this. http. get (url ). toPromise (). then (response => {const js On = response. json (); return {first: json. _ links. first? Json. _ links. first. href: null, last: json. _ links. last? Json. _ links. last. href: null, prev: json. _ links. prev? Json. _ links. prev. href: null, next: json. _ links. next? Json. _ links. next. href: null, values: json. _ embedded. values };}) ;}// app. component. ts @ Component ({selector: 'app-root', templateUrl :'. /app.component.html ', styleUrls :['. /app.component.css '], providers: [MyLettersServiceService]}) export class AppComponent implements OnInit {response: LettersResponse; constructor. service. get Letters (environment. serviceUrl ). then (res => this. response = res);} onLinkClicked (url: string): void {console. log (url); this. service. getLetters (url ). then (res => this. response = res) ;}}// app.component.html <div * ngIf = "response"> <ul> <li * ngFor = "let c of response. values ">
Run NgCLI on the command line to start the client program and then access http: // localhost: 4200. The result is as follows:
SummaryThis article describes how to use Apworks to extend ASP. NET Core to provide HAL support for RESTful APIs. The article uses two cases to demonstrate ASP. NET Core Web API is very simple and convenient to support HAL, and the custom function is very powerful. The second server paging case introduces Angular and TypeScript, by implementing a simple client page, you can more detail the convenience of RESTful APIs with HAL features. As mentioned above, HAL support is only part of ASP. NET Core extension in the Apworks framework. The Apworks framework focuses more on providing solutions for rapid development of microservices. In future articles, I will introduce more about Apworks's support for microservices.