F# Giraffe/Saturn - Как BindModelAsync с типами параметров
Я пытаюсь создать простой WebAPI с Saturn и хочу представить входные данные как все необязательные типы, так как есть вероятность, что потребитель API не вводит правильные данные. Я хочу подтвердить ввод пользователя с помощьюValidate
метод, который выглядит как UnvalidatedUserInput -> Result<ValidUserInput, ValidationError list>
.
Похоже, я должен использовать ctx.BindModelAsync<UnvalidatedUserInput >()
для десериализации тела запроса, но он не десериализуется в UnvalidatedUserInput
тип из-за option
с. Я получаю следующую ошибку:
Исключение типа "Newtonsoft.Json.JsonSerializationException" произошло в System.Private.CoreLib.dll, но не было обработано в пользовательском коде: "Неожиданное свойство" solarSystemId "обнаружено при чтении объединения. Путь 'solarSystemId', строка 3, позиция 20.'
Итак, я попытался удалить option
s из типов, но теперь BindModelAsync
устанавливает недостающие параметры как null
и я не могу использовать isNull
на нем, потому что это не допускающий значение NULL тип в F#. Как я могу обойти это и безопасно проверить ввод пользователя?
Я читал, что, возможно, мне следует использовать Json -модуль https://github.com/microsoft/fsharplu/, но я не вижу примеров того, как это сделать. Я также видел, что, возможно, в.NET 5.0 будет поддержка десериализации для различаемых объединений, но что я могу сделать до этого?
Вот мой HttpHandler:
let asteroidCreatedEventHandler : HttpHandler =
fun (next : HttpFunc) (ctx : HttpContext) ->
task {
let! rawEvent = ctx.BindModelAsync<UnverifiedAsteroidCreatedEvent>()
let validationResult = Validation.validateAsteroidCreatedEvent rawEvent
match validationResult with
| Ok verifiedEvent ->
AddMinableToSolarSystem verifiedEvent |> ignore
ctx.SetStatusCode 204
return! Successful.NO_CONTENT next ctx
| Error err ->
ctx.SetStatusCode 400
return! RequestErrors.BAD_REQUEST err next ctx
}
И мой роутер:
let appRouter = router {
post "/asteroid-created" Asteroids.Controller.asteroidCreatedEventHandler
forward "" browserRouter
}
Определения типов:
type Coordinates =
{
X: int
Y: int
}
override this.ToString() =
sprintf "(%i, %i)" this.X this.Y
type UnverifiedAsteroidCreatedEvent =
{ Id: System.Guid option
SolarSystemId: System.Guid option
Coordinates: Coordinates option }
PS любые другие очевидные ошибки или запахи кода, которые вы можете почерпнуть из этих фрагментов, пожалуйста, дайте мне несколько советов!