Chinmay Naphade
Chinmay Naphade

Reputation: 808

How to make HTTP POST request with url encoded body in flutter?

I'm trying to make an post request in flutter with content type as url encoded. When I write body : json.encode(data), it encodes to plain text.

If I write body: data I get the error type '_InternalLinkedHashMap<String, dynamic>' is not a subtype of type 'String' in type cast

This is the data object

var match = {
  "homeTeam": {"team": "Team A"},
  "awayTeam": {"team": "Team B"}
};

And my request

var response = await post(Uri.parse(url),
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: match,
    encoding: Encoding.getByName("utf-8"));

Upvotes: 67

Views: 200532

Answers (11)

buckleyJohnson
buckleyJohnson

Reputation: 489

You can use addAll()...

var multipart = await http.MultipartFile.fromPath("userfile", file.path);//userFile must match server

var requestMultipart = http.MultipartRequest("POST", Uri.parse("uri"));

requestMultipart.files.add(multipart);

Map<String, String> data = {
  "name_of_image": "testName",
  "id_image": "2",//if the
  "upload_type": "Insert",
  "id_location": "2"
};

requestMultipart.fields.addAll(data);

Upvotes: 0

Asmaa Amrawy
Asmaa Amrawy

Reputation: 37

If you are using dio you can do it using :

dio.post(
      '/info',
      data: {'id': 5},
      options: Options(contentType: Headers.formUrlEncodedContentType),
    );

check https://github.com/flutterchina/dio for more details

Upvotes: 1

Suragch
Suragch

Reputation: 511846

I came here just trying to make an HTTP POST request. Here is an example of how to do that:

import 'dart:convert';
import 'package:http/http.dart';


makePostRequest() async {

  final uri = Uri.parse('http://httpbin.org/post');
  final headers = {'Content-Type': 'application/json'};
  Map<String, dynamic> body = {'id': 21, 'name': 'bob'};
  String jsonBody = json.encode(body);
  final encoding = Encoding.getByName('utf-8');

  Response response = await post(
    uri,
    headers: headers,
    body: jsonBody,
    encoding: encoding,
  );

  int statusCode = response.statusCode;
  String responseBody = response.body;
}

See also

Upvotes: 28

sujith s
sujith s

Reputation: 914

Post encoded URL request

 static Future<http.Response> genearalRequest() async {
  Map<String,String> headers = new Map();
  headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF-8";
 var data = {
    "data1": "datat1 value",
    "data2": "value2"
   };
var parts = [];
data.forEach((key, value) {
  parts.add('${Uri.encodeQueryComponent(key)}='
      '${Uri.encodeQueryComponent(value)}');
});
var formData = parts.join('&');

print(formData);
return await http.post('$baseUrl/oauth/token', headers: headers, body: formData);

}

Reference

Upvotes: 1

Richard Heap
Richard Heap

Reputation: 51692

You need to add three additional steps: First, you need to convert the JSON map to a String (using json.encode) Then you need to Uri encode it if you want to send it as application/x-www-form-urlencoded. Lastly, you need to give the parameter that you are posting a name.

For example (note, this is using the dart:io HttpClient, but it's basically the same):

  Future<HttpClientResponse> foo() async {
    Map<String, dynamic> jsonMap = {
      'homeTeam': {'team': 'Team A'},
      'awayTeam': {'team': 'Team B'},
    };
    String jsonString = json.encode(jsonMap); // encode map to json
    String paramName = 'param'; // give the post param a name
    String formBody = paramName + '=' + Uri.encodeQueryComponent(jsonString);
    List<int> bodyBytes = utf8.encode(formBody); // utf8 encode
    HttpClientRequest request =
        await _httpClient.post(_host, _port, '/a/b/c');
    // it's polite to send the body length to the server
    request.headers.set('Content-Length', bodyBytes.length.toString());
    // todo add other headers here
    request.add(bodyBytes);
    return await request.close();
  }

The above is for the dart:io version (which, of course, you can use in Flutter) If you would like to stick with the package:http version, then you need to tweak your Map a bit. body must be a Map<String, String>. You need to decide what you want as your POST parameters. Do you want two: homeTeam and awayTeam? or one, say, teamJson?

This code

  Map<String, String> body = {
    'name': 'doodle',
    'color': 'blue',
    'homeTeam': json.encode(
      {'team': 'Team A'},
    ),
    'awayTeam': json.encode(
      {'team': 'Team B'},
    ),
  };

  Response r = await post(
    url,
    body: body,
  );

produces this on the wire

name=doodle&color=blue&homeTeam=%7B%22team%22%3A%22Team+A%22%7D&awayTeam=%7B%22team%22%3A%22Team+B%22%7D

alternatively, this

  Map<String, String> body = {
    'name': 'doodle',
    'color': 'blue',
    'teamJson': json.encode({
      'homeTeam': {'team': 'Team A'},
      'awayTeam': {'team': 'Team B'},
    }),
  };

  Response r = await post(
    url,
    body: body,
  );

produces this on the wire

name=doodle&color=blue&teamJson=%7B%22homeTeam%22%3A%7B%22team%22%3A%22Team+A%22%7D%2C%22awayTeam%22%3A%7B%22team%22%3A%22Team+B%22%7D%7D

the package:http client takes care of: encoding the Uri.encodeQueryComponent, utf8 encoding (note that that's the default, so no need to specify it) and sending the length in the Content-Length header. You must still do the json encoding.

Upvotes: 61

Talha Rasool
Talha Rasool

Reputation: 1152

On the place of "UserModel" write the name of your model and do not pass String in the body it will create a problem using "Map" as given below.

static Future<UserModel> performUserLogin(String username, String password) async{
    
        try{
    
          Map<String, String> headers = {"Content-type": "application/json"};
          
    
          Map<String, String> JsonBody = {
            'username':  username,
            'password': password
          };
    
          print("The JSON Object is here $body");
          // make POST request
          final response = await http.post(loginAPIURL,body: JsonBody);
          // check the status code for the result
          int statusCode = response.statusCode;
          print("Login calling $response");
    
    
          if (statusCode == 200){
    
          
    
          }else{
            return null;
            //return UserModel();
            throw Exception("Error in login");
          }
    
        } catch (e) {
          throw Exception(e);
        }
      }

Upvotes: 1

Techalgoware
Techalgoware

Reputation: 620

Map<String, String> body = {
  'getDetails': 'true'
};

final response = await 
http.post("https://example.com/", body: body);

if (response.statusCode == 200) {
//Your code
}

Upvotes: 0

Doan Bui
Doan Bui

Reputation: 4418

I suggest using the Dio library. It supports a lot with working with APIs.

With newest Dio version. Simply do the following:

BaseOptions options = new BaseOptions(
baseUrl: "https://www.xx.com/api",
connectTimeout: 5000,
receiveTimeout: 3000,);
Dio dio = new Dio(options);
//
Map<String, String> params = Map();
params['username'] = '6388';
params['password'] = '123456';
//
response = await dio.post("/login", data: FormData.fromMap(params));

Upvotes: 3

k dimitrov
k dimitrov

Reputation: 389

I did it like this with dart's http package. It's not too fancy. My endpoint wasn't accepting the parameters with other methods, but it accepted them like this, with the brackets included in the parameter.

import 'package:http/http.dart' as http;

String url = "<URL>";

Map<String, String> match = {
  "homeTeam[team]": "Team A",
  "awayTeam[team]": "Team B",
};

Map<String, String> headers = {
    "Content-Type": "application/x-www-form-urlencoded"
}

http.post(url, body: body, headers: headers).then((response){
    print(response.toString());
});

Upvotes: 0

Nebi Sarıg&#252;l
Nebi Sarıg&#252;l

Reputation: 141

you need to use json.encode

example;

var match = {
  "homeTeam": {"team": "Team A"},
  "awayTeam": {"team": "Team B"}
};
var response = await post(Uri.parse(url),
    headers: {
      "Accept": "application/json",
      "Content-Type": "application/x-www-form-urlencoded"
    },
    body: json.encode(match),
    encoding: Encoding.getByName("utf-8"));

Upvotes: 14

wendu
wendu

Reputation: 1257

I'd like to recommend dio package to you , dio is a powerful Http client for Dart/Flutter, which supports Interceptors, FormData, Request Cancellation, File Downloading, Timeout etc.

dio is very easy to use, in your case you can:

Map<String, String> body = {
'name': 'doodle',
'color': 'blue',
'teamJson': {
  'homeTeam': {'team': 'Team A'},
  'awayTeam': {'team': 'Team B'},
  },
};

dio.post("/info",data:body, options: 
  new Options(contentType:ContentType.parse("application/x-www-form-urlencoded")))    

dio can encode the data automatically.

More details please refer to dio.

Upvotes: 31

Related Questions