Oliveira.HATEOAS
10.0.301.12
dotnet add package Oliveira.HATEOAS --version 10.0.301.12
NuGet\Install-Package Oliveira.HATEOAS -Version 10.0.301.12
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Oliveira.HATEOAS" Version="10.0.301.12" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Oliveira.HATEOAS" Version="10.0.301.12" />
<PackageReference Include="Oliveira.HATEOAS" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Oliveira.HATEOAS --version 10.0.301.12
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: Oliveira.HATEOAS, 10.0.301.12"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Oliveira.HATEOAS@10.0.301.12
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Oliveira.HATEOAS&version=10.0.301.12
#tool nuget:?package=Oliveira.HATEOAS&version=10.0.301.12
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
Oliveira.HATEOAS
📚 Projeto de estudo — este pacote foi construído como parte de meus estudos no curso da Udemy.
Esta é uma biblioteca inteligente para implementar o padrão HATEOAS em suas APIs RESTful, implementada com base em este projeto.
📦 Installation
Package Manager Console
Install-Package Oliveira.HATEOAS -Version 10.0.301.10
NuGet Package Manager
🚀 How to use
1. Implement ISupportsHypermedia in your exposed object
using RestWithASPNET10Erudio.Hypermedia;
using RestWithASPNET10Erudio.Hypermedia.Abstract;
namespace RestWithASPNET10Erudio.Data.DTO.V1
{
public class BookDTO : ISupportsHypermedia
{
public long Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public decimal Price { get; set; }
public DateTime LaunchDate { get; set; }
public List<HypermediaLink> Links { get; set; } = [];
}
}
2. Implement your enricher with ContentResponseEnricher<T>
using Microsoft.AspNetCore.Mvc;
using RestWithASPNET10Erudio.Data.DTO.V1;
using RestWithASPNET10Erudio.Hypermedia.Constants;
namespace RestWithASPNET10Erudio.Hypermedia.Enricher
{
public class BookEnricher : ContentResponseEnricher<BookDTO>
{
protected override Task EnrichModel(
BookDTO content, IUrlHelper urlHelper)
{
var request = urlHelper.ActionContext.HttpContext.Request;
var baseUrl = $"{request.Scheme}://" +
$"{request.Host.ToUriComponent()}" +
$"{request.PathBase.ToUriComponent()}/api/book/v1";
content.Links.AddRange(GenerateLinks(content.Id, baseUrl));
return Task.CompletedTask;
}
private IEnumerable<HypermediaLink> GenerateLinks(long id, string baseUrl)
{
//return new List<HypermediaLink>
return
[
// This new HypermediaLink is equal to new() in C# 9.0
new ()
{
Rel = RelationType.COLLECTION,
Href = $"{baseUrl}",
Type = ResponseTypeFormat.DefaultGet,
Action = HttpActionVerb.GET
},
new ()
{
Rel = RelationType.SELF,
Href = $"{baseUrl}/{id}",
Type = ResponseTypeFormat.DefaultGet,
Action = HttpActionVerb.GET
},
new ()
{
Rel = RelationType.CREATE,
Href = $"{baseUrl}",
Type = ResponseTypeFormat.DefaultPost,
Action = HttpActionVerb.POST
},
new ()
{
Rel = RelationType.UPDATE,
Href = $"{baseUrl}",
Type = ResponseTypeFormat.DefaultPut,
Action = HttpActionVerb.PUT
},
new ()
{
Rel = RelationType.DELETE,
Href = $"{baseUrl}/{id}",
Type = ResponseTypeFormat.DefaultDelete,
Action = HttpActionVerb.DELETE
}
];
}
}
}
3. Expose your endpoints in the controller
The HyperMediaFilter enriches every Ok(...) response, so your controller stays focused on the business logic.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using RestWithASPNET10Erudio.Data.DTO.V1;
using RestWithASPNET10Erudio.Model;
using RestWithASPNET10Erudio.Services;
namespace RestWithASPNET10Erudio.Controllers.V1
{
[ApiController]
[Route("api/[controller]/v1")]
[Authorize("Bearer")]
public class BookController : ControllerBase
{
private readonly IBookServices _bookService;
private readonly ILogger<BookController> _logger;
public BookController(IBookServices bookService, ILogger<BookController> logger)
{
_bookService = bookService;
_logger = logger;
}
[HttpGet]
[ProducesResponseType(200, Type = typeof(BookDTO))]
[ProducesResponseType(400)]
[ProducesResponseType(401)]
public IActionResult FindAll()
{
return Ok(_bookService.FindAll());
}
[HttpGet("{id}")]
[ProducesResponseType(200, Type = typeof(BookDTO))]
[ProducesResponseType(400)]
[ProducesResponseType(401)]
public IActionResult FindByID(long id)
{
var book = _bookService.FindByID(id);
if (book == null) return NotFound();
return Ok(book);
}
[HttpPost]
[ProducesResponseType(200, Type = typeof(BookDTO))]
[ProducesResponseType(400)]
[ProducesResponseType(401)]
public IActionResult Post([FromBody] BookDTO book)
{
_logger.LogInformation("Creating new Book: {title}", book.Title);
var createdBook = _bookService.Create(book);
if (createdBook == null)
{
_logger.LogError("Failed to create book with title {title}", book.Title);
return NotFound();
}
return Ok(createdBook);
}
[HttpPut]
[ProducesResponseType(200, Type = typeof(BookDTO))]
[ProducesResponseType(400)]
[ProducesResponseType(401)]
public IActionResult Update([FromBody] BookDTO book)
{
return Ok(_bookService.Update(book));
}
[HttpDelete("{id}")]
[ProducesResponseType(204, Type = typeof(BookDTO))]
[ProducesResponseType(400)]
[ProducesResponseType(401)]
public IActionResult Delete(long id)
{
_bookService.Delete(id);
return NoContent();
}
}
}
4. Register the HyperMediaFilter and your enrichers in your Program.cs
builder.Services.AddControllers(options =>
{
options.Filters.Add<HyperMediaFilter>();
});
var filterOptions = new HyperMediaFilterOptions();
filterOptions.ContentResponseEnricherList.Add(new PersonEnricher());
filterOptions.ContentResponseEnricherList.Add(new BookEnricher());
5. Enjoy 🎉
Response as JSON
[
{
"id": 1,
"title": "Working effectively with legacy code",
"author": "Michael C. Feathers",
"price": 49.00,
"launchDate": "2017-11-29T13:50:05.878",
"links": [
{
"rel": "collection",
"href": "https://localhost:44300/api/book/v1",
"type": "application/json",
"action": "GET"
},
{
"rel": "self",
"href": "https://localhost:44300/api/book/v1/1",
"type": "application/json",
"action": "GET"
},
{
"rel": "create",
"href": "https://localhost:44300/api/book/v1",
"type": "application/json",
"action": "POST"
},
{
"rel": "update",
"href": "https://localhost:44300/api/book/v1",
"type": "application/json",
"action": "PUT"
},
{
"rel": "delete",
"href": "https://localhost:44300/api/book/v1/1",
"type": "no-content",
"action": "DELETE"
}
]
},
{
"id": 2,
"title": "Design Patterns",
"author": "Ralph Johnson, Erich Gamma, John Vlissides e Richard Helm",
"price": 45.00,
"launchDate": "2017-11-29T15:15:13.636",
"links": [
{
"rel": "collection",
"href": "https://localhost:44300/api/book/v1",
"type": "application/json",
"action": "GET"
},
{
"rel": "self",
"href": "https://localhost:44300/api/book/v1/2",
"type": "application/json",
"action": "GET"
},
{
"rel": "create",
"href": "https://localhost:44300/api/book/v1",
"type": "application/json",
"action": "POST"
},
{
"rel": "update",
"href": "https://localhost:44300/api/book/v1",
"type": "application/json",
"action": "PUT"
},
{
"rel": "delete",
"href": "https://localhost:44300/api/book/v1/2",
"type": "no-content",
"action": "DELETE"
}
]
}
]
Response as XML
<ArrayOfBookDTO xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<BookDTO>
<Id>1</Id>
<Title>Working effectively with legacy code</Title>
<Author>Michael C. Feathers</Author>
<Price>49.00</Price>
<LaunchDate>2017-11-29T13:50:05.878</LaunchDate>
<Links>
<HypermediaLink Rel="collection" Href="https://localhost:44300/api/book/v1" Type="application/json" Action="GET" />
<HypermediaLink Rel="self" Href="https://localhost:44300/api/book/v1/1" Type="application/json" Action="GET" />
<HypermediaLink Rel="create" Href="https://localhost:44300/api/book/v1" Type="application/json" Action="POST" />
<HypermediaLink Rel="update" Href="https://localhost:44300/api/book/v1" Type="application/json" Action="PUT" />
<HypermediaLink Rel="delete" Href="https://localhost:44300/api/book/v1/1" Type="no-content" Action="DELETE" />
</Links>
</BookDTO>
<BookDTO>
<Id>2</Id>
<Title>Design Patterns</Title>
<Author>Ralph Johnson, Erich Gamma, John Vlissides e Richard Helm</Author>
<Price>45.00</Price>
<LaunchDate>2017-11-29T15:15:13.636</LaunchDate>
<Links>
<HypermediaLink Rel="collection" Href="https://localhost:44300/api/book/v1" Type="application/json" Action="GET" />
<HypermediaLink Rel="self" Href="https://localhost:44300/api/book/v1/2" Type="application/json" Action="GET" />
<HypermediaLink Rel="create" Href="https://localhost:44300/api/book/v1" Type="application/json" Action="POST" />
<HypermediaLink Rel="update" Href="https://localhost:44300/api/book/v1" Type="application/json" Action="PUT" />
<HypermediaLink Rel="delete" Href="https://localhost:44300/api/book/v1/2" Type="no-content" Action="DELETE" />
</Links>
</BookDTO>
</ArrayOfBookDTO>
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net10.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 10.0.301.12 | 108 | 7/29/2026 |
| 10.0.301.11 | 107 | 7/29/2026 |
| 10.0.301.10 | 104 | 7/24/2026 |
| 10.0.301.9 | 127 | 7/24/2026 |
| 10.0.301.8 | 102 | 7/24/2026 |
| 10.0.301.7 | 103 | 7/24/2026 |
| 10.0.301.5 | 100 | 7/23/2026 |
| 10.0.301.4 | 100 | 7/23/2026 |
| 10.0.301.3 | 108 | 7/23/2026 |
| 10.0.301.1 | 99 | 7/22/2026 |