2

I have been trying to handle post request in aqueduct. After reading the documentation this is what I have been able to come up with channel.dart

 router
.route("/chat")//"/chat/[:id]")
.link(() => ChatController());

chatController.dart

> import 'package:web_api/web_api.dart';

    class ChatController extends ResourceController{

      @Operation.get('id')
      Future<Response> getProjectById(@Bind.path("id") int id) async {
        // GET /chat/:id
        print(id);
        //return Response.ok({"key": "value"});
      }

      @Operation.post()
      Future<Response> createChat(@Bind.body() Chat chat) async {
        // POST /project

        print("post");
        final Map<String, dynamic> body = await request.body.decode();
        final name =body['name'] as String;
        print(" 1) name ==> $name");

        //return Response.ok({"key": "value"});
      }

    }
    class Chat extends Serializable{
       int id;
      String name;

      @override
      void readFromMap(Map<String, dynamic> map) {
        id = map['id'] as int;
        name = map['name'] as String;
      }

      @override
      Map<String, dynamic> asMap() {
        return {
          'id': id,
          'name': name
        };
      }
}

and finally html template

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <form action="http://127.0.0.1:8888/chat" method="POST">
        <input id="id" name="id">
        <input id="name" name="name">
        <button type="submit">Submit</button>
    </form>

</body>
</html>

the html template is not served by aquaduct. It's a different location all together. When I submit the form my console logs.

[INFO] aqueduct: Server aqueduct/2 started.  
[INFO] aqueduct: POST /chat 15ms 415  

why am I not seeing the body conents, how could I get to see the body (form values)

Suragch
  • 484,302
  • 314
  • 1,365
  • 1,393
kenn
  • 1,384
  • 12
  • 19

2 Answers2

2

You are getting a 415 Media Type Unsupported error. You can see this in the log, and you'd see it in your client response as well.

By default, a ResourceController only accepts application/json data. You have to set acceptedContentTypes in your controller to take form data. The easiest way to do this is to override the property in ChatController:

class ChatController {
  ...
  @override
  List<ContentType> acceptedContentTypes = [ContentType("application", "x-www-form-urlencoded")];
  ...
}
Joe Conway
  • 1,566
  • 9
  • 8
  • I should also point out that form data is always decoded into a `Map>`, because it is possible to have more than one element with the same key. In your `Serializable` type, you'll need to treat both the id and name as a `List` and grab the first element from it. – Joe Conway Oct 18 '18 at 23:21
  • When i add the acceptedContentTypes,the post function is being called however am getting a cast error in Chat class that extends Serializable. Attempting to convert name String to List the errror seem to persist. Internal error 500. – kenn Oct 19 '18 at 07:46
  • Your initial post method was fine - when you bind the body, it is automatically decoded, creates a new `Chat` object, and then calls its `readFromMap`. You need to keep your properties declared as `String`s. In `readFromMap`, you can assign those properties like `id = map['id']?.first as String;` – Joe Conway Oct 19 '18 at 15:48
1

To all future seekers with the same problem thuought should append to Joe Conway answer above. in the html template change

  <form action="http://127.0.0.1:8888/chat" method="POST">

to

<form action="http://127.0.0.1:8888/chat" method="POST" enctype="application/x-www-form-urlencoded">

then add

...
  @override
  List<ContentType> acceptedContentTypes = [ContentType("application", "x-www-form-urlencoded")];
  ...

to your controller and then to you serializable class in my case chat class.change the String to a list.These will be as follows

class Chat extends Serializable{
  List<String> id;
  List<String> name;

  @override
  void readFromMap(Map<String, dynamic> map) {
    id = map[0] as List<String>;
    name = map[1] as List<String>;
  }

  @override
  Map<String, dynamic> asMap() {
    return {
      'id': id[0],
      'name': name[1]
    };
  }
}

and finally alter you post methon in your controller.

@Operation.post()
  Future<Response> createProject(@Bind.body() Chat chat) async {
    // POST /project

    print("post");
    Map<String, List<String>> body = await request.body.decode();
    final name =body["name"][0] ;

    print("\n\n 1) body ==> $body");
     print("\n\n 1) name ==> $name");


    return Response.ok({"key": "value"});
  }

I sincerly hope that helps someone in the future with the same problem.

kenn
  • 1,384
  • 12
  • 19