-
Notifications
You must be signed in to change notification settings - Fork 0
IHateoas Abstraction usage
The next examples will demonstrate how to use the IHateoas
and IHateoas<T>
abstractions to generate HATEOAS links in an ASP.NET Core controller.
The generated links contain information about the available actions that can be performed on the Member
object, along with the URLs to perform those actions. The rel
attribute in each link represents the relationship between the current resource and the linked resource, while the method
attribute represents the HTTP method used to access the linked resource.
Let's assume we have a MembersController
in our application with an action that retrieves a Member by ID and returns it as JSON.
The following code snippet provides an example of how to use IHateoas
in an ASP.NET Core Web API controller.
using HateoasNet;
using System.Linq;
using System.Collection.Generics;
[ApiController]
[Route("[controller]")]
public class MembersController : ControllerBase
{
private readonly IHateoas _hateoas;
private readonly List<Member> _members;
public MembersController(List<Member> members, IHateoas hateoas)
{
_hateoas = hateoas;
_members = members;
}
[HttpGet("{id:guid}", Name = "get-member")]
public IActionResult Get(Guid id)
{
var member = _members.SingleOrDefault(i => i.Id == id);
var links = _hateoas.Generate(member);
return member != null ? Ok(new { data = member, links }) : NotFound() as IActionResult;
}
}
In the constructor of the MembersController
, we inject the IHateoas
implementation along with any other of its dependencies. Within the Get
method, the controller first retrieves the member from the list of members based on the provided ID. If the member is found, the controller generates HATEOAS links for the member using the Generate
method of the IHateoas
instance taking an object
of any type. In this case, we pass in the Member
object retrieved from the list. Finally, the controller returns a 200 OK response along with the member data and the generated links, or a 404 Not Found response if the member is not found.
Note that the HATEOAS links generated by the IHateoas
instance are based on the configurations defined in the IHateoasSourceBuilder
implementations. In the previous examples, we showed how to define such configurations for different types of resources like Member
with the MemberHateoasBuilder
.
The generic version of the IHateoas
interface allows you to specify the TOutput type for resources for which you want to generate HATEOAS links. This is useful when you want to generate links expressed different than default List<IHateoasLink>
, in this case ImmutableDictionary<string, object>>
.
using HateoasNet;
using System.Linq;
using System.Collections.Generic;
[ApiController]
[Route("[controller]")]
public class GuildsController : ControllerBase
{
private readonly IHateoas<ImmutableDictionary<string, object>> _hateoas;
private readonly List<Guild> _guilds;
public GuildsController(List<Guild> guilds, IHateoas<ImmutableDictionary<string, object>> hateoas)
{
_hateoas = hateoas;
_guilds = guilds;
}
[HttpGet("{id:guid}", Name = "get-guild")]
public IActionResult Get(Guid id)
{
var guild = _guilds.SingleOrDefault(i => i.Id == id);
var links = _hateoas.Generate(guild);
return guild != null ? Ok(new { data = guild, links }) : NotFound() as IActionResult;
}
}
We're using the generic version of the IHateoas
interface to generate links for a Guild resource. We've specified the generic type as ImmutableDictionary<string, object>
to shape the links
property in the final output object.
The GuildsController
constructor takes IHateoas<ImmutableDictionary<string, object>>
and any of its dependencies as arguments. The List<Guild>
argument is used to retrieve the requested guild by ID. If the guild is found, then generates HATEOAS links for the guild, which are returned along with the guild data in an 200 Ok response. If the guild is not found, a 404 Not Found response is returned.
In this code snippet, we see an implementation of the generic interface IHateoas with help of AbstractHateoas<ImmutableDictionary<string, object>>
base implementations.
using HateoasNet;
using System.Linq;
using System.Collections.Generic;
using System.Collections.Immutable;
public class DictionaryHateoas : AbstractHateoas<ImmutableDictionary<string, object>>
{
public DictionaryHateoas(IHateoas hateoas) : base(hateoas)
{
}
protected override ImmutableDictionary<string, object> GenerateCustom(IEnumerable<HateoasLink> links)
{
return links.ToImmutableDictionary(x => x.Rel, x => (object)new { x.Href, x.Method });
}
}
The DictionaryHateoas
class provides the implementation of the abstract GenerateCustom
method which generates a ImmutableDictionary<string, object>
of links with their respective href and method. This method is called by the base AbstractHateoas<ImmutableDictionary<string, object>>
implementation of IHateoas<ImmutableDictionary<string, object>>
. Its constructor takes an IHateoas
root interface that knows how to generate links for any configured resource type.
In addition to the built-in IHateoas
interface, you can also create your own implementations of the IHateoas<T>
interface to customize the generated HATEOAS links for specific T output types.
To register the custom IHateoas<T>
implementations, you can use the RegisterAllCustomHateoas
extension method on the IServiceCollection
object. Here's an example of how to register all custom IHateoas<T>
implementations found in the assembly that contains you Startup
class:
using HateoasNet.DependencyInjection.Core;
public void ConfigureServices(IServiceCollection services)
{
// other registrations...
// optional step to register all custom IHateoas<T> implementations in separated files found in a given assemblies
services.RegisterAllCustomHateoas(new Assembly[] { typeof(Startup).Assembly }, ServiceLifetime.Scoped);
// other registrations...
}
This code registers all custom IHateoas<T>
implementations found in the assembly that contains the Startup class as Scoped
services. You can replace typeof(Startup).Assembly
with the assembly that contains your custom IHateoas<T>
implementations.