-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
96 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,63 +1,79 @@ | ||
namespace TodoBackend.Controllers | ||
|
||
open Microsoft.AspNetCore.Mvc | ||
open TodoBackend | ||
|
||
type FromClientIdHeaderAttribute() = inherit FromHeaderAttribute(Name="COMPLETELY_INSECURE_CLIENT_ID") | ||
|
||
type TodoView = | ||
{ id: int | ||
url: string | ||
order: int; title: string; completed: bool } | ||
|
||
type GetByIdArgsTemplate = { id: int } | ||
|
||
// Fulfills contract dictated by https://www.todobackend.com | ||
// To run: | ||
// & dotnet run -f netcoreapp2.1 -p Web | ||
// https://www.todobackend.com/client/index.html?https://localhost:5001/todos | ||
// # NB Jet does now own, control or audit https://todobackend.com; it is a third party site; please satisfy yourself that this is a safe thing use in your environment before using it._ | ||
// See also similar backends used as references when implementing: | ||
// https://github.com/ChristianAlexander/dotnetcore-todo-webapi/blob/master/src/TodoWebApi/Controllers/TodosController.cs | ||
// https://github.com/joeaudette/playground/blob/master/spa-stack/src/FSharp.WebLib/Controllers.fs | ||
[<Route "[controller]"; ApiController>] | ||
type TodosController(service: Todo.Service) = | ||
inherit ControllerBase() | ||
|
||
let toProps (value : TodoView) : Todo.Props = { order = value.order; title = value.title; completed = value.completed } | ||
|
||
member private __.WithUri(x : Todo.View) : TodoView = | ||
let url = __.Url.RouteUrl("GetTodo", { id=x.id }, __.Request.Scheme) // Supplying scheme is secret sauce for making it absolute as required by client | ||
{ id = x.id; url = url; order = x.order; title = x.title; completed = x.completed } | ||
|
||
[<HttpGet>] | ||
member __.Get([<FromClientIdHeader>]clientId : ClientId) = async { | ||
let! xs = service.List(clientId) | ||
return seq { for x in xs -> __.WithUri(x) } | ||
} | ||
using Microsoft.AspNetCore.Mvc; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
[<HttpGet("{id}", Name="GetTodo")>] | ||
member __.Get([<FromClientIdHeader>]clientId : ClientId, id) : Async<IActionResult> = async { | ||
let! x = service.TryGet(clientId, id) | ||
return match x with None -> __.NotFound() :> _ | Some x -> ObjectResult(__.WithUri x) :> _ | ||
namespace TodoBackendTemplate.Controllers | ||
{ | ||
public class FromClientIdHeaderAttribute : FromHeaderAttribute | ||
{ | ||
public FromClientIdHeaderAttribute() | ||
{ | ||
Name = "COMPLETELY_INSECURE_CLIENT_ID"; | ||
} | ||
} | ||
|
||
[<HttpPost>] | ||
member __.Post([<FromClientIdHeader>]clientId : ClientId, [<FromBody>]value : TodoView) : Async<TodoView> = async { | ||
let! created = service.Create(clientId, toProps value) | ||
return __.WithUri created | ||
public class TodoView | ||
{ | ||
public int Id { get; set; } | ||
public string Url { get; set; } | ||
public int Order { get; set; } | ||
public string Title { get; set; } | ||
public bool Completed { get; set; } | ||
} | ||
|
||
[<HttpPatch "{id}">] | ||
member __.Patch([<FromClientIdHeader>]clientId : ClientId, id, [<FromBody>]value : TodoView) : Async<TodoView> = async { | ||
let! updated = service.Patch(clientId, id, toProps value) | ||
return __.WithUri updated | ||
} | ||
// Fulfills contract dictated by https://www.todobackend.com | ||
// To run: | ||
// & dotnet run -f netcoreapp2.1 -p Web | ||
// https://www.todobackend.com/client/index.html?https://localhost:5001/todos | ||
// # NB Jet does now own, control or audit https://todobackend.com; it is a third party site; please satisfy yourself that this is a safe thing use in your environment before using it._ | ||
// See also similar backends used as references when implementing: | ||
// https://github.com/ChristianAlexander/dotnetcore-todo-webapi/blob/master/src/TodoWebApi/Controllers/TodosController.cs | ||
// https://github.com/joeaudette/playground/blob/master/spa-stack/src/FSharp.WebLib/Controllers.fs | ||
[Route("[controller]"), ApiController] | ||
public class TodosController : ControllerBase | ||
{ | ||
private readonly Todo.Service _service; | ||
|
||
public TodosController(Todo.Service service) => | ||
_service = service; | ||
|
||
private Todo.Props ToProps(TodoView value) => | ||
new Todo.Props {Order = value.Order, Title = value.Title, Completed = value.Completed}; | ||
|
||
private TodoView WithUri(Todo.View x) | ||
{ | ||
// Supplying scheme is secret sauce for making it absolute as required by client | ||
var url = Url.RouteUrl("GetTodo", new {id = x.Id}, Request.Scheme); | ||
return new TodoView {Id = x.Id, Url = url, Order = x.Order, Title = x.Title, Completed = x.Completed}; | ||
} | ||
|
||
[<HttpDelete "{id}">] | ||
member __.Delete([<FromClientIdHeader>]clientId : ClientId, id): Async<unit> = | ||
service.Execute(clientId, Todo.Commands.Delete id) | ||
[HttpGet] | ||
public async Task<IEnumerable<TodoView>> Get([FromClientIdHeader] ClientId clientId) => | ||
from x in await _service.List(clientId) select WithUri(x); | ||
|
||
[<HttpDelete>] | ||
member __.DeleteAll([<FromClientIdHeader>]clientId : ClientId): Async<unit> = | ||
service.Execute(clientId, Todo.Commands.Clear) | ||
[HttpGet("{id}", Name = "GetTodo")] | ||
public async Task<IActionResult> Get([FromClientIdHeader] ClientId clientId, int id) | ||
{ | ||
var res = await _service.TryGet(clientId, id); | ||
if (res == null) return NotFound(); | ||
return new ObjectResult(WithUri(res)); | ||
} | ||
|
||
[HttpPost] | ||
public async Task<TodoView> Post([FromClientIdHeader] ClientId clientId, [FromBody] TodoView value) => | ||
WithUri(await _service.Create(clientId, ToProps(value))); | ||
|
||
[HttpPatch("{id}")] | ||
public async Task<TodoView> Patch([FromClientIdHeader] ClientId clientId, int id, [FromBody] TodoView value) => | ||
WithUri(await _service.Patch(clientId, id, ToProps(value))); | ||
|
||
[HttpDelete("{id}")] | ||
public Task Delete([FromClientIdHeader] ClientId clientId, int id) => | ||
_service.Execute(clientId, new Todo.Commands.Delete {Id = id}); | ||
|
||
[HttpDelete] | ||
public Task DeleteAll([FromClientIdHeader] ClientId clientId) => | ||
_service.Execute(clientId, new Todo.Commands.Clear()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters