I'm trying to use a POST
endpoint that accepts JSON
data from a HTML
form, but only get 404 - Page not found
as a result, unless I add another endpoint without the payload.
So I can create a demo project from template and make small changes to test this issue:
cd /tmp
dotnet new websharper-web --name Demo --language F#
cd Demo
dotnet run ## Ok!
Edit main.html
to add the form:
<div class="container">
...
</div>
<form method="post" action="/demo" enctype="application/x-www-form-urlencoded">
<label>Name</label>
<input type="text" name="name" />
<button type="submit">Post</button>
</form>
<footer class="footer">
...
</footer>
Add to Site.fs
the code to handle the form request:
type Data = { name: string }
type EndPoint =
| [<EndPoint "GET /">] Home
| ...
| [<EndPoint "POST /demo"; Json "data">] Demo of data: Data
| [<EndPoint "POST /demo">] DemoFallback
[<Website>]
let Main =
Application.MultiPage (fun ctx endpoint ->
match endpoint with
| ...
| EndPoint.Demo data ->
printfn "Data: %A" data
Content.Text "Ok demo with post data"
| EndPoint.DemoFallback ->
Content.Text "I don't expect this route"
)
Run the project again:
dotnet run
And from the browser I get I don't expect this route
, but from curl
:
curl -i -H "Content-Type: application/json" \
-XPOST "http://localhost:5000/demo" \
-d '{ "name": "me" }'
or with different content-type
:
curl -i -H "Content-Type: application/x-www-form-urlencoded" \
-XPOST "http://localhost:5000/demo" \
-d '{ "name": "me" }'
both yield:
HTTP/1.1 200 OK
Date: Tue, 29 Jan 2019 12:57:19 GMT
Server: Kestrel
Transfer-Encoding: chunked
Ok demo with post data
What am I missing here?
An HTML form does not send the information in Json format instead it uses url-encoded which is similar to the query parameters in a url except that they go in the body of the request and not the URL, for instance if you have 2 fields User & Password:
User=John&Password=123456
In order to receive the data from the form you need to use the [< FormData >]
attribute:
type Data = { [< FormData >] name: string }
and indicate the EndPoint lile this:
| [< EndPoint "POST /demo" >] Demo of data: Data