A dead simple HATEOAS provider for ASP.NET Core

While doing some research on Hypermedia As The Engine Of Application State (HATEOAS), I came across some great HATEOAS providers for ASP.NET Web API and ASP.NET Core MVC, but they didn't quite fit my need, so I created my own one.

Grab the source code from my GitHub repo here: https://github.com/faniereynders/aspnetcore-hateoas

Getting started

The JSON HATEOAS provider extends the IMvcBuilder and is used like the following:

public void ConfigureServices(IServiceCollection services)  
{
    services
        .AddMvc()
        .AddHateoas(...);

    //other services
}

Making a request to one of the APIs in your application with Accept header set as application/json+hateoas, will return the HATEOAS payload containing the expected resource(s).

Example

Given the following DTO in your application:

public class PersonDto  
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}

With the following Controller:

[Route("api/[controller]")]
public class PeopleController : Controller  
{
    [HttpGet(Name = "get-people")]
    public IActionResult Get() {...}

    [HttpGet("{id}", Name = "get-person")]
    public IActionResult Get(int id) {...}

    [HttpPost(Name = "create-person")]
    public IActionResult Post([FromBody]PersonDto person) {...}

    [HttpPut("{id}", Name = "update-person")]
    public IActionResult Put(int id, [FromBody]PersonDto person) {...}

    [HttpDelete("{id}", Name = "delete-person")]
    public IActionResult Delete(int id) {...}
}

Wire up HATEOAS with the particular links:

public void ConfigureServices(IServiceCollection services)  
{
    services
        .AddMvc()
        .AddHateoas(options =>
        {
            options
               .AddLink<PersonDto>("get-person", p => new { id = p.Id })
               .AddLink<List<PersonDto>>("create-person")
               .AddLink<PersonDto>("update-person", p => new { id = p.Id })
               .AddLink<PersonDto>("delete-person", p => new { id = p.Id });
        });

    //other services
}

And executing this request:

GET /api/people HTTP/1.1  
Accept: application/json+hateoas  

Will result in the following response:

{
    "_links": [
        {
            "href": "http://localhost:52691/api/people",
            "rel": "create-person",
            "method": "POST"
        }
    ],
    "items": [
        {
            "_links": [
                {
                    "href": "http://localhost:52691/api/people/1",
                    "rel": "get-person",
                    "method": "GET"
                },
                {
                    "href": "http://localhost:52691/api/people/1",
                    "rel": "update-person",
                    "method": "PUT"
                },
                {
                    "href": "http://localhost:52691/api/people/1",
                    "rel": "delete-person",
                    "method": "DELETE"
                }
            ],
            "data": {
                "id": 1,
                "name": "Fanie",
                "email": "fanie@mail.com"
            }
        },
        {
            "_links": [
                {
                    "href": "http://localhost:52691/api/people/2",
                    "rel": "get-person",
                    "method": "GET"
                },
                {
                    "href": "http://localhost:52691/api/people/2",
                    "rel": "update-person",
                    "method": "PUT"
                },
                {
                    "href": "http://localhost:52691/api/people/2",
                    "rel": "delete-person",
                    "method": "DELETE"
                }
            ],
            "data": {
                "id": 2,
                "name": "Maarten",
                "email": "maarten@example.com"
            }
        },
        {
            "_links": [
                {
                    "href": "http://localhost:52691/api/people/2",
                    "rel": "get-person",
                    "method": "GET"
                },
                {
                    "href": "http://localhost:52691/api/people/2",
                    "rel": "update-person",
                    "method": "PUT"
                },
                {
                    "href": "http://localhost:52691/api/people/2",
                    "rel": "delete-person",
                    "method": "DELETE"
                }
            ],
            "data": {
                "id": 2,
                "name": "Marcel",
                "email": "marcel@example.com"
            }
        }
    ]
}

Grab the source code from my GitHub repo here: https://github.com/faniereynders/aspnetcore-hateoas

This project will make its way to NuGet soon.

It cannot get any simpler. Comments and feedback welcome!