1

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?

Birei
  • 35,723
  • 2
  • 77
  • 82
  • @AMieres: Not quite, because if I remove the `DemoFallback` path, the browser returns me a `(404) Page not found` after submitting the form. – Birei Jan 29 '19 at 14:29
  • You are right, according to the documentation it tries the options in the order declared and uses the first one that matches. Which means the form of the JSON the browser sends is not `{ "name" : "..."}` – AMieres Jan 29 '19 at 14:53
  • @AMieres: Either the form and the type already have one field: (``) and `type Data = { name: string }`. – Birei Jan 29 '19 at 15:34
  • 1
    According to this post: https://stackoverflow.com/questions/22195065/how-to-send-a-json-object-using-html-form-data the form is not sent in Json format unless you serialize it that way. – AMieres Jan 29 '19 at 15:44
  • @AMieres: You are right in your last comment. It has worked using `[]` from the docs, instead of `[]`. Add it to an answer so I can approve it. – Birei Jan 29 '19 at 16:11

1 Answers1

4

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
AMieres
  • 4,944
  • 1
  • 14
  • 19