public Vmachine(IUserHub userHub, IMachine machine) { _userHub = userHub; _machine = machine; Get["/"] = _ => { return "hello world!"; }; Get["/users", runAsync: true] = async (_, ct) => { var users = await _userHub.List(); return users.Either<IEnumerable<AcmeUser>, Error, Response>( ifSuccess: (x, msgs) => Response.AsJson(x.Select(u => u.UserName)), ifFailure: msgs => HttpStatusCode.InternalServerError); }; Get["/users/{id}", runAsync: true] = async (parameters, ct) => { this.RequiresAuthentication(); var wallet = await _userHub.ProbeWallet((UserId)parameters.id); return wallet.Either<Wallet, Error, Response>( ifSuccess: (x, msgs) => Response.AsJson(x.Select(kv => new { nominal = kv.Key, amount = kv.Value })), ifFailure: msgs => HttpStatusCode.NotFound); }; Post["/users/suicide/", runAsync: true] = async (parameters, ct) => { this.RequiresAuthentication(); var cadaver = await _userHub.Kill(((AuthenticatedUser)Context.CurrentUser).Id); return cadaver.Either<UserId, Error, Response>( ifSuccess: (x, msgs) => HttpStatusCode.NoContent, ifFailure: msgs => HttpStatusCode.NotFound); }; Post["/register", runAsync: true] = async (parameters, ct) => { var registerParams = this.Bind<RegisterParams>(); var user = await _userHub.Summon(registerParams.UserName, registerParams.Password); return user.Either<UserId, Error, Response>( ifSuccess: (x, msgs) => this.LoginAndRedirect(x, fallbackRedirectUrl: "/users/" + x), ifFailure: msgs => HttpStatusCode.UnprocessableEntity); }; Post["/login", runAsync: true] = async (parameters, ct) => { var loginParams = this.Bind<LoginParams>(); var res = await _userHub.Find(loginParams.UserName); var q = from user in res from authed in user.Password == loginParams.Password ? Result<AcmeUser, Error>.Succeed(user) : Result<AcmeUser, Error>.FailWith(Error.BAD_PASSWORD) select authed; return q.Either<AcmeUser, Error, Response>( ifSuccess: (x, msgs) => this.LoginAndRedirect(x.Id, fallbackRedirectUrl: "/users/" + x.Id), ifFailure: msgs => HttpStatusCode.Forbidden); }; Post["logout"] = _ => this.LogoutAndRedirect("/machine/menu"); Get["/machine/commitedCash", runAsync: true] = async (_, ct) => { var cash = await _machine.DisplayCommitedCash(); return cash.Either<CoinValue, Error, Response>( ifSuccess: (x, msgs) => $"cash commited: {x}", ifFailure: msgs => HttpStatusCode.InternalServerError); }; Get["/machine/menu", runAsync: true] = async (_, ct) => { var menu = await _machine.ShowMenu(); var response = menu.Either<Menu, Error, Response>( ifSuccess: (x, msgs) => Response.AsJson(x.Select(kv => new { name = kv.Key.ToString(), cost = kv.Value.Item1, count = kv.Value.Item2 })), ifFailure: msgs => HttpStatusCode.InternalServerError); return response; }; Post["/machine/charge/", runAsync: true] = async (parameters, ct) => { return null; }; }