Dymond
Dymond

Reputation: 2277

Cannot generate auto decoder for MongoDB.Bson.BsonObjectId

I'm trying to create an user and add the info into MongoDB.

The type looks like this.

[<CLIMutable>]
type User =
    { 
    Id: BsonObjectId
    Name: string
    LastName: string
    Role: string
    Email: string
    Password: string 
  }

and signup function,

let signup : HttpHandler =
   fun (next : HttpFunc) (ctx : HttpContext) ->
       task {
            
            let! payload = ctx.BindJsonAsync<User>()
            let updated = updateUserPassword (payload, BCrypt.HashPassword(payload.Password, 10))
            try
                do! UserCollection.InsertOneAsync updated
                let maybe = UserCollection.Find(fun user -> user.Email = payload.Email).ToEnumerable() |> Seq.tryHead
                match maybe with
                | Some doc -> return! Successful.OK (userToDTO (doc)) next ctx
                | None -> return! RequestErrors.BAD_REQUEST "Invalid User" next ctx
            with :? Exception -> return! ServerErrors.INTERNAL_ERROR "Something Went Wrong" next ctx
        }

But when I try to create the user I get error : Cannot generate auto decoder for MongoDB.Bson.BsonObjectId

If I change the Id to Id:string, I can save to the DB so connection works. But using string will not have the effect I want of course. Where reading this post, but cannot see what the difference really are :( https://medium.com/@mukund.sharma92/cruding-in-f-with-mongodb-e4699d1ac17e

And the repo I'm playing with is https://github.com/AngelMunoz/Giraffarig

Thanks in advance

Upvotes: 1

Views: 95

Answers (1)

Brian Berns
Brian Berns

Reputation: 17038

After looking at this a while, I think the solution is to modify the signup function so that it works like the login function. Specifically:

  • Create a type called SignupPayload in Types.fs that is similar to the existing LoginPayload type. The SignupPayload type should contain all of the User fields except BsonObjectId.
  • Modify the signup function to deserialize the payload.
  • Use the deserialized payload to build and save an actual User object.

So the final code looks something like this:

let! payload = ctx.BindJsonAsync<SignupPayload>()
let user = payload |> SignupPayload.toUser
let updated = updateUserPassword (user, BCrypt.HashPassword(user.Password, 10))

Upvotes: 1

Related Questions