Reputation: 11570
My Controller's Post method always has null property values on parameter when triggered.
Environment:
I'm using ASP.Net Core WebAPI with F#.
Attempt:
I tried to apply a suggestion from this link to my Startup.fs file:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver <-
Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
However, GlobalConfiguration is an unrecognized type.
Here's a larger view of my attempt:
type Startup private () =
new (configuration: IConfiguration) as this =
Startup() then
this.Configuration <- configuration
// *** I INSERTED THIS BELOW *** //
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver <-
Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()
Similar questions:
I did review this link. However, nothing worked.
HTTP Post:
This is the Post method where I keep observing null property values on my parameter:
[<HttpPost>]
member x.Post(request:DataTransfer.Request) = (* "request" parameter is always null *)
request |> Query.carriers
|> function
| Error _ -> x.StatusCode(500) :> IActionResult
| Ok carriers -> x.Ok(carriers) :> IActionResult
The actual type is defined here:
[<CLIMutable>]
type Request = {
RequestId : string
Customer : Customer
ItemQtys : ItemQty seq
}
Client:
My client app makes the following call:
let client = WebGateway.httpClient APIBaseAddress
let response = client.PostAsJsonAsync("carriers", request) |> toResult
Here's the request type on the client:
[<CLIMutable>]
type Request = {
RequestId : string
Customer : Customer
ItemQtys : ItemQty seq
}
UPDATE:
I then attempted to apply a suggestion from this link and also using this reference. It didn't work though.
member this.ConfigureServices(services: IServiceCollection) =
// Add framework services.
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddJsonOptions(fun opt ->
let resolver = Newtonsoft.Json.Serialization.DefaultContractResolver()
resolver.NamingStrategy <- null
opt.SerializerSettings.ContractResolver <- resolver
) |> ignore
Postman:
Screenshots:
Partial Success:
The following seems promising:
Hence, the code above results in actual values sent from the client. However, I haven't found a way to convert the object into the data transfer type that I need.
Upvotes: 2
Views: 330
Reputation: 6510
You don't need to mess with Contract Resolvers in ASP.NET Core to use camel-case and F# record types, as you did with ASP.NET. I would take all of that out, or try creating a simple test project to get it working, then go back and make the appropriate changes to your real project. With no additional configuration, you should be able to get something working just by following these steps:
dotnet new webapi -lang F#
ValuesController.fs
: [<CLIMutable>]
type Request =
{
Name: string
Value: string
}
Post
method to be something like this: [<HttpPost>]
member this.Post([<FromBody>] request:Request) =
this.Created(sprintf "/%s" request.Name, request)
{
"name": "test",
"value": "abc"
}
You should see the request object echoed back with a 201 response.
Upvotes: 1