Writing a query parameter with an array of values in Flutter - flutter

I'm using the Http package on flutter. I have a query request that should take a large list of values
localhost/accounts/fax-info?ids=(66, 97) this works in post man however. In flutter I tried this exact thing and it just gives me a general error that doesn't tell me anything.
Future<List<CustomerInfo>> getFaxinfo(
List<UnfinishedAccount> accounts,
) async {
final baseUrl = 'localhost';
final int port = 3003;
final accountsPath = '/accounts';
final accountsFaxInfoPath = '$accountsPath/fax-info';
try {
final uri = Uri.parse('http://localhost:3003/accounts/fax-info?ids=(66, 97)');
final response = await http.get(uri, headers: headers);
if (response.statusCode == 200) {
print(jsonDecode(response.body));
}
return [CustomerInfo(sent: 200, received: 300, name: 'Test')];
} catch (err) {
print(err);
rethrow;
}
I tried mapping the values of accounts.id then converting that to a list, I'm not sure if that's the correct way to put it in the query as a list of values because it looks like (66,97) not [66, 97].

Related

not able to access json file in flutter api call

I want to use JSON from this link https://howtodoandroid.com/movielist.json.
This is my code where I want to call API from the above link
Future getMovieList() async {
final response = await http.get(Uri.parse("https://howtodoandroid.com/movielist.json"));
if (response.statusCode == 200) {
allMovielist = jsonDecode(response.body);
}
}
i got error "failed to load response data: no data found for resource with given identifier"
Future<List<YourModel>> getMovieList() async {
final response = await http.get(Uri.parse("https://howtodoandroid.com/movielist.json"));
if (response.statusCode == 200) {
/// On first the data will get is always unassigned or just dynamic
/// which cant be identify
final List<dynamic> list = jsonDecode(response.body);
/// try to print or log the data if the data goes to status 200 and able
/// to see it
log(list.map((e) => e).toList().toString());
/// this one will return the indicate assigned data
return list.map((e)=> YourModel.fromJson(e)).toList();
} else{
return [];
}
}
If you are trying this on the web run this command flutter run -d chrome --web-renderer html
if you still get a CROS error disable the web security.
1- Go to flutter\bin\cache and remove a file named: flutter_tools.stamp
2- Go to flutter\packages\flutter_tools\lib\src\web and open the file chrome.dart.
3- Find '--disable-extensions'
4- Add '--disable-web-security'
I get this answer from this link
or consider this package also
Example Code
Future getMoviesList() async {
var headers = <String, String>{'Content-Type': 'application/json'};
var url = Uri.parse('https://howtodoandroid.com/movielist.json');
var response = await http.get(url, headers: headers);
if (response.statusCode == 200) {
var result = json.decode(response.body);
print(result);
return result;
}
}

I want to create multiple filter list with dropdown in flutter/dart

I'm a new flutter developer.
So I want to create multiple filter lists with dropdowns...
This filter has 3 dropdown widgets, the expected result of this is that the search results can be combined with each other.
I'm kinda confused about how to start doing it, can you give me advice/reference/link related to this issue.
So far I just can do a single search (i got it from the search delegate)
Future<List<ModelKost>> getFilter({String? query}) async {
final prefs = await SharedPreferences.getInstance();
const key = 'token';
final value = prefs.get(key) ?? 0;
try {
var response = await http.get(Uri.parse('$serverUrl/home'), headers: {
'Accept': 'application/json',
'Authorization': 'Bearer $value'
});
if (response.statusCode == 200) {
data = json.decode(response.body)['data'];
results = data.map((e) => ModelKost.fromJson(e)).toList();
if (query != null) {
results = results
.where((e) =>
e.kabkot.toLowerCase().contains((query.toLowerCase())))
.toList();
}
} else {
debugPrint('fetch data error');
}
} on Exception catch (e) {
debugPrint('error: $e');
}
sortHarga = results;
return results;
}
How to implement it with multiple filters and with dropdown? thank you!
What you want to do is after the api call, store the result inside a list (for example allKosts). Then provide a getter to get the list, with the filter. Whenever you change a filter, you want to call setState and the getter's value will be updated automatically.
List<ModelKost> allKosts = [];
String kabkotFilter = '';
String tipeKotFilter = '';
List<ModelKost> get filteredKosts =>
results.where((e) => e.kabkot.toLowerCase().contains((kabkotFilter.toLowerCase())) && e.tipeKot.toLowerCase() == tipeKotFilter.toLowerCase())).toList();

Simple http request with basicauth stucks

I don’t really want to do anything other than a simple HTTP-request with a GET parameter and Basic Auth.
For this, I have written the following small class. However, not much seems to happen here. The request is started but it doesn’t seem to return any result. It runs and runs and should timeout or something like that.
class HttpService {
Future<List<Post>> getPosts() async {
final queryParameters = {
'data_type': 'temps_today',
};
String username = 'user';
String password = 'password';
String basicAuth =
'Basic ' + base64Encode(utf8.encode('$username:$password'));
print(basicAuth);
Response res = await get(Uri.https('mydomain.com', '/gartentemp/api/get_temp_data.php', queryParameters), headers: <String, String>{'authorization': basicAuth}); //stucks here
print(res.statusCode);
if (res.statusCode == 200) {
List<dynamic> body = jsonDecode(res.body);
List<Post> posts = body
.map(
(dynamic item) => Post.fromJson(item),
)
.toList();
return posts;
} else {
throw "Unable to retrieve posts.";
}
}
}
In the browser, a JSON file is delivered without any problems.
What's wrong with my try?
Thx niesel

Unable to use a Future value - Flutter/Dart

I've fetched a json object and deserialized it and then returned it too.
I want to use this in another file.
I'm unable to assign the values that I'm getting in the first step.
Here are all the codes...
Service
Future getGeoPoints(String accessToken, String tripId) async {
String requestUrl;
var response = await get(
Uri.parse(requestUrl),
headers: {
'Authorization': "Bearer $accessToken",
},
);
if (response.statusCode == 200) {
Map<String, dynamic> responseBody = json.decode(response.body);
GetGeoPoints geoPoints = GetGeoPoints.fromJson(responseBody);
List listOfGeoPoints = [];
for (var geoPoint in geoPoints.geoPoints) {
listOfGeoPoints.add(
{
'latitude': geoPoint.latitude,
'longitude': geoPoint.longitude,
'timestamp': geoPoint.timeStamp,
},
);
}
// print('List of geo points: ' + '$listOfGeoPoints');
return listOfGeoPoints;
} else {
throw Exception('Failed to load data from server');
}
}
File where I need the above values
List routeCoordinates;
Future<void> getValues() async {
getGeoPoints(widget.accessToken, widget.tripId)
.then((value) => routeCoordinates = value);
}
When I run the app, routeCoordinates is null but when I hotreload, it contains the value.
I want to have the values as soon as the screen starts. What is the right way to assign the values here?
I've also tried this:
routeCoordinates = getGeoPoints...
It throws error..
Please help.. Thanks..
The function getGeoPoints() is an asynchronous one. But on the other file, you are not using the await keyword, instead you are using then(). So your code is not waiting for that function to return value.
Try using below code,
List routeCoordinates;
Future<void> getValues() async {
routeCoordinates = await getGeoPoints(widget.accessToken, widget.tripId);
}
Let us know how it went.
You need to use a FutureBuilder to define a behaviour depending on the state of the request. You'll be able to tell the widget what to return while your app is waiting for the response to your request. You can also return a specific widget if you get an error(if your user is offline, for example).
Edit: I've linked the official docs but give this article a read if it's not clear enough.

Flutter: HttpClient post contentLength -- exception

Very weird...
In order to post some JSON data to my server, I define the contentLength to the length of the JSON encoded data but I then receive an exception that says "Content size exceeds specified contentLength". Difference is 1 byte.
Here is the source code:
Future<Map> ajaxPost(String serviceName, Map data) async {
var responseBody = json.decode('{"data": "", "status": "NOK"}');
try {
var httpClient = new HttpClient();
var uri = mid.serverHttps ? new Uri.https(mid.serverUrl, _serverApi + serviceName)
: new Uri.http(mid.serverUrl, _serverApi + serviceName);
var request = await httpClient.postUrl(uri);
var body = json.encode(data);
request.headers
..add('X-mobile-uuid', await _getDeviceIdentity())
..add('X-mobile-token', await mid.getMobileToken());
request.headers.contentLength = body.length;
request.headers.set('Content-Type', 'application/json; charset=utf-8');
request.write(body);
var response = await request.close();
if (response.statusCode == 200){
responseBody = json.decode(await response.transform(utf8.decoder).join());
//
// If we receive a new token, let's save it
//
if (responseBody["status"] == "TOKEN"){
await mid.setMobileToken(responseBody["data"]);
// Let's change the status to "OK", to make it easier to handle
responseBody["status"] = "OK";
}
}
} catch(e){
// An error was received
throw new Exception("AJAX ERROR");
}
return responseBody;
}
Some other times, it works fine...
Am I doing anything wrong with this code?
Many thanks for your help.
EDITED WITH SOLUTION:
Many thanks for your help. The simply fact of using utf8.encode(json.encode(data)) did not fully work. So, I turned to the http library and it now works like a charm. The code is even lighter!
Here is the new version of the code:
Future<Map> ajaxPut(String serviceName, Map data) async {
var responseBody = json.decode('{"data": "", "status": "NOK"}');
try {
var response = await http.put(mid.urlBase + '/$_serverApi$serviceName',
body: json.encode(data),
headers: {
'X-mobile-uuid': await _getDeviceIdentity(),
'X-mobile-token': await mid.getMobileToken(),
'Content-Type': 'application/json; charset=utf-8'
});
if (response.statusCode == 200) {
responseBody = json.decode(response.body);
//
// If we receive a new token, let's save it
//
if (responseBody["status"] == "TOKEN") {
await mid.setMobileToken(responseBody["data"]);
// Let's change the status to "OK", to make it easier to handle
responseBody["status"] = "OK";
}
}
} catch (e) {
// An error was received
throw new Exception("AJAX ERROR");
}
return responseBody;
}
I got it working with
req.headers.contentLength = utf8.encode(body).length;
From an indirect tip of the Utf8Codec documentation which states
decode(List codeUnits, { bool allowMalformed }) → String
Decodes the UTF-8 codeUnits (a list of unsigned 8-bit integers) to the corresponding string.
That means thatutf8.encode() returns codeUnits which actually means List<uint8>.
Encoding a String payload would in theory return a list which length is the length of the payload in bytes.
So using httpClient means to always measure the length of the payload in bytes, not the length of a String which may differ.
Günter is right. Content-Length has to be the length of the byte array after encoding from a String to bytes in whatever encoding you server requires.
There's a package called http which provides a slightly higher level api (it uses dart.io httpClient under the hood) which takes care of encoding the post body and length for you. For example, when you need to send application/x-www-form-urlencoded form it will even take a Map and do all the encoding for you (you still need to encode to json yourself). It's equally happy to send just a String or List<int>. Here's an example:
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,
);
Seems your string contains multibyte characters.
UTF8-encode the string to get the correct length:
var body = utf8.encode(json.encode(data));