Candoumbe.Forms
0.3.0
dotnet add package Candoumbe.Forms --version 0.3.0
NuGet\Install-Package Candoumbe.Forms -Version 0.3.0
<PackageReference Include="Candoumbe.Forms" Version="0.3.0" />
paket add Candoumbe.Forms --version 0.3.0
#r "nuget: Candoumbe.Forms, 0.3.0"
// Install Candoumbe.Forms as a Cake Addin #addin nuget:?package=Candoumbe.Forms&version=0.3.0 // Install Candoumbe.Forms as a Cake Tool #tool nuget:?package=Candoumbe.Forms&version=0.3.0
FORMS
Introduction
This project aims at describing forms using HTML like syntax and objects.
The idea behind this project is to give opportunity to APIs written in .NET to describe their endpoints (responses and inputs) in a "HTML like way" so clients could dynamically generate inputs to push data to a given endpoints.
Why
I know what you're thinking : "Open API and swagger already solve this !". Well, yes and no. Yes, the Open API specification defines how to describe an API from a global perspective (shape of resources, supported HTTP verbs, ...).
But consider the following use case : you are building an API that handle bank accounts.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"balance": {
"type": "number"
},
"currency": {
"type": "string"
}
},
"required": [
"id",
"balance",
"currency",
"name"
]
}
When an API client reads an account
GET /accounts/{id}
the API would return an account
with balance
that is either :
balance > 0
: you can withdraw money or make a deposit.balance <= 0
: you can only make a deposit.
How would you advertise that behavior to API consumers using only swagger ? As far as I can tell, there's no way to do this as what can be done is very business/context/state specific.
With Candoumbe.Forms, you have a set of classes to help you display that behavior when sending resources back to API clients. Modeled after the ION spec, it provides a set of classes that can be used in API reponses to convey additional meanings
- Form : models a form that a client must comply to in order to submit data to create a new account
Given the following AccountModel
public record NewAccountModel(Guid Id, string Name, double InitialBalance);
the backend can "describe" the form for to use using the FormBuilder
class as follow
FormBuilder<NewAccountModel> createAccountFormBuilder = new(new Link { Href = "url/where/data/will/be/sent", Method = "POST", Relations = ["create-form"] });
createAccountFormBuilder.AddField(static x => x.Id);
createAccountFormBuilder.AddField(static x => x.Name);
createAccountFormBuilder.AddField(static x => x.InitialBalance);
Form form = createAccountFormBuilder.Build();
would result in the following form
(JSON representation)
{
"fields": [
{
"label": "Id",
"name": "Id"
},
{
"label": "Name",
"name": "Name"
},
{
"type": "Integer",
"label": "InitialBalance",
"name": "InitialBalance"
}
],
"meta": {
"href": "url/where/data/must/be/sent",
"relations": [
"create-form"
],
"method": "POST",
"template": false
}
}
Given that json representation, any client could then build the form that could be used to create new accounts
using HTML
<form action="url/where/data/must/be/sent">
<label for="Id">Id</label>
<input type="text" id="Id" name="Id"/>
<label for="Name">Name</label>
<input type="text" id="Name" name="Name"/>
<label for="InitialBalance">Id</label>
<input type="text" id="InitialBalance" name="InitialBalance"/>
<button type="submit">Create account</button>
<button type="button">Cancel</button>
</form>
Same could have been achieved with exploring an Open API ?!?!
You are definitely right ! That's exactly one of the purpose for which Open API was designed.
But Candoumbe.Forms is that you can add more metadatas when describing a form
Going H.A.T.E.O.S.
One of the fundamental concept of HATEOS is to provide API responses that are self descriptive so that clients can discover the API without any
prior knowledge.
For an account
resource with positive balance
{
"item": {
"id": "3bc34535dfde",
"balance": 70,
"currency": "$"
},
"links": [
{
"rel" : "deposit",
"method": "POST",
"href": "/accounts/3bc34535dfde/deposits"
},
{
"rel" : "withdrawal",
"method": "POST",
"href": "/accounts/3bc34535dfde/withdrawals"
}
]
}
whereas the following representation would be sent when balance < 0
{
"item": {
"id": "3bc34535dfde",
"balance": -20,
"currency": "$"
},
"links": [
{
"rel" : "deposit",
"verb": "POST",
"link": "/accounts/3bc34535dfde/deposits"
}
]
}
Providing consistent and dynamic navigation and/or action links allow any client to "react" and adapt to the state of the any resource.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Candoumbe.MiscUtilities (>= 0.14.0)
- Newtonsoft.Json.Schema (>= 3.0.16)
- Optional (>= 4.0.0)
-
.NETStandard 2.1
- Candoumbe.MiscUtilities (>= 0.14.0)
- Newtonsoft.Json.Schema (>= 3.0.16)
- Optional (>= 4.0.0)
-
net8.0
- Candoumbe.MiscUtilities (>= 0.14.0)
- Newtonsoft.Json.Schema (>= 3.0.16)
- Optional (>= 4.0.0)
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 |
---|---|---|
0.3.0 | 413 | 12/28/2024 |
0.3.0-beta0005 | 2,301 | 4/16/2023 |
0.3.0-beta0004 | 334 | 4/16/2023 |
0.3.0-beta0001 | 136 | 3/24/2023 |
### 🚀 New features
• Added net8.0 TFM support
• Added support of DateOnly properties
### ⚠️ Breaking changes
• Changed Link.Relation from string to string[] [BREAKING]
• Dropped netstandard1.0 TFM support
• Dropped net5.0 TFM support
• Removed Ultimately dependency
• Changed IonResourceto a record (netstandard2.1• and net5+)
• Changed Formto a record (netstandard2.1• and net5+)
• Changed FormFieldto a record (netstandard2.1• and net5+)
• Changed Linkto a record (netstandard2.1• and net5+)
### 🧹 Housekeeping
• Updated Candoumbe.Pipelines to 0.12.1
• Updated Candoumbe.MiscUtilities to 0.14.0
• Improve unit tests readability
Full changelog at https://github.com/candoumbe/Forms/blob/main/CHANGELOG.md