Flutter - Send Json over HTTP Post - flutter

I am trying to send a Json over HTTP post to update a record in my database. I've connected to the server but I'm getting a 415 "Unsupported Media Type" error when I run the request.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String url = 'http://<Hostname>:
<Port>/jderest/orchestrator/JDE_ORCH_Sample_UpdateMeterReadings_Generic';
Future<String> makeRequest() async {
var response = await http
.post(Uri.encodeFull(url), body: json.encode({
"NewHourMeterReading": "650",
"EquipmentNumber": "34665",
"NewFuelMeterReading": "650"
}), headers: {"Accept": "application/json"});
print(response.body);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new RaisedButton(
child: new Text('Make Request'),
onPressed: makeRequest,
)));
}
}
Can someone please let me know how to get past this error?
the error that I am facing is this.
I/flutter ( 5881): Unsupported Media Type
Screenshot of Response Headers/Status Code/Body
Sorry for the messy code, it didn't copy paste over every well.

You'll have to add the content-type to your header, setting its value to application/json.
By specifying Accept you're saying that your client is able to understand that response type, not that your request content is of the JSON type.
Basically you're saying "hey there, I'm able to understand JSON, so you can send it to me and I'll be fine with it" but you're not saying "hey I'm going to send you a JSON, be prepared for it!"
For a better understanding, you can find more about Accept here and Content-type here.

You are using incomplete headers for sending the json payload. That is why the server is not accepting you request.
Use the following headers instead:
headers: {
"content-type" : "application/json",
"accept" : "application/json",
},

Send Json and Accept Json using:-
Future<String> addData(Map<String, dynamic> request) async {
final url = 'http_url';
try {
final response = await http.post(url,
headers: {
"content-type" : "application/json",
"accept" : "application/json",
},
body: jsonEncode(request));
final responseData = jsonDecode(response.body) as Map<String,dynamic>;
return responseData['message'];
} catch (error) {
throw error;
}
}

Related

LateInitializationError: Field not initialized Error in Flutter

Can anyone help me with this problem?
I have the requester class, with the username attribute, as shown in the example below:
class Requester {
late String username;
}
I also have the getInformation() method, which is called in the "click" event, as shown in the example below:
getInformation() async {
Requester requester = Requester();
RequesterEndpoints endpoint = RequesterEndpoints();
final String token = "tokenExemplo";
final uri = Uri.parse(endpoint.getInformation);
final headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json',
'Authorization': 'Bearer ${token}'
};
Response response = await get(uri, headers: headers);
dynamic responseBody = jsonDecode(response.body);
dynamic requesterBody = responseBody['requester'];
requester.username = requesterBody['username'];
}
The method, in the last line, changes, or should change, the value of the username attribute of the requester class. The requesterBody['username'] is a String type value, coming from an API. If I make one:
print(requesterBody['username'])
The username coming from the API will be displayed. That is, the value exists.
If I do a print on requester.username, right after requester.username = requesterBody['username'];, I can see that the username attribute was changed successfully.
I want to use this requester.username value in a view. I'm doing it this way:
import 'package:flutter/material.dart';
import 'package:mobile/models/requester.dart';
class HomeRequesterScreen extends StatefulWidget {
const HomeRequesterScreen({Key? key}) : super(key: key);
#override
State<HomeRequesterScreen> createState() => _HomeRequesterScreenState();
}
class _HomeRequesterScreenState extends State<HomeRequesterScreen> {
Requester requester = Requester();
#override
Widget build(BuildContext context) {
return Container(
child: Text(requester.username);
);
}
}
It is important to mention that the view is only called after the username attribute has been changed, in the getInformation() method.
But when I assign requester.username to Text, I get this error:
LateError (LateInitializationError: Field 'username' has not been initialized.)
In a direct way, I want to use the attribute value of a class in a view.
Does anyone know how to resolve this?
From the code that you shared:
in _HomeRequesterScreenState you just create a new instance of Requester and never assign any value to it. It does not contain anything.
Your getInformation() method is void, you create a variable there and never pass it anywhere even though you called the method.
In DTO classes, like your model, it's not a good practice to use late variables, if not for a reason. In your case, absolutely no need to.
So first, get rid of late, this way it would be easier for you understand if you are actually placing any data where you think it should be.
class Requester {
final String username;
Requester({required this.username});
}
Then make your method return your model.
Future<Requester> getInformation() async {
RequesterEndpoints endpoint = RequesterEndpoints();
final String token = "tokenExemplo";
final uri = Uri.parse(endpoint.getInformation);
final headers = {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Accept': 'application/json',
'Authorization': 'Bearer ${token}'
};
Response response = await get(uri, headers: headers);
dynamic responseBody = jsonDecode(response.body);
dynamic requesterBody = responseBody['requester'];
return Requester(username: requesterBody['username']);
}
Then explicitly create the instance in your business logic / state management level and pass it to UI.
Since I only have your UI code, let's assume we just do it there. Not to forget that while your API call is in progress, you don't have username to show, so you need to show something else instead and call setState once loaded.
import 'package:flutter/material.dart';
import 'package:mobile/models/requester.dart';
class HomeRequesterScreen extends StatefulWidget {
const HomeRequesterScreen({Key? key}) : super(key: key);
#override
State<HomeRequesterScreen> createState() => _HomeRequesterScreenState();
}
class _HomeRequesterScreenState extends State<HomeRequesterScreen> {
Requester? requester;
#override
void initState() {
super.initState();
loadRequester();
}
Future<void> loadRequester() async {
requester = await getInformation();
setState(() {});
}
#override
Widget build(BuildContext context) {
return Container(
child: requester != null ? Text(requester!.username) : CircularProgressIndicator();
);
}
}

Is there a way to use flutter to access twitter API without errors?

I am just starting to learn flutter and would like to know how to access the endpoints of the twitter API for a project I was creating. I wanted to display a tweet at first ( eventually it would be a random tweet generated with a button.)
My code is given below:
import 'package:twitter_api/twitter_api.dart';
import 'package:flutter/material.dart';
void main() {
runApp(Twittwrapp());
}
final _oauth = new twitterApi(
consumerKey: 'consumerkeyhere',
consumerSecret: 'consumersecrethere',
token: 'tokenhere',
tokenSecret: 'tokensecrethere',
);
Future twitterRequest = _oauth.getTwitterRequest(
"GET",
"statuses/user_timeline.json",
options: {
"user_id": "19025957",
"screen_name": "TTCnotices",
"count": "20",
"trim_user": "true",
"tweet_mode": "extended",
},
);
class Twittwrapp extends StatefulWidget{
#override
_Twitte createState() => _Twitte();
}
class _Twitte extends State<Twittwrapp>{
var tweet = await twitterRequest;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Text(tweet),
),
);
}
}
And the error i get is XMLHTTPREQUEST.
You can try this.
import 'package:http/http.dart' as http;
var response = await http.get(Uri.http('example.com', 'apiPath'), //without https:// http:// or www
headers: <String, String>{
'consumerKey': 'consumerkeyhere',
'consumerSecret': 'consumersecrethere',
'token': 'tokenhere',
'tokenSecret': 'tokensecrethere',
...
}
);
if (response.statusCode == 200) {
// request successful
print(response.body);
getQuestion();
} else {
// request error
print(response.statusCode); // compare this code with https://developer.mozilla.org/en-US/docs/Web/HTTP/Status and find the problem
}

fetch data from an API with the use of ID in flutter

I work on a delivery man application and I need to have from an API the details of an order received on the account of a delivery man.
here is an example:
{
"Status": "1",
"Order": {
"deliveryCost": "5.000",
"amount": "38.400",
"total": "43,400",
"hors_remise": "34.560",
"Dishes": [
{
"cartID": "00000",
"dishID": "13548",
"dimensionID": 0,
"title": "Classic 16 pieces trays:",
"ingredient": "10 piece trays + 2 gunkan + 4 shrimp crunchy",
"price": "38.400",
"quantity": "1",
"imagePath": "https://www.monresto.net/test/plats/P_170121112803.jpg",
"Options": []
}
],
and to access of all this information I must specify the "KEY" I had on the postan
my question is how can i add (orderID)?
there is my code :
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:flutter/material.dart';
class datePageClass extends StatefulWidget {
#override
_datePageClassState createState() => _datePageClassState();
}
class _datePageClassState extends State<datePageClass> {
void getData() async {
http.Response response = await http.post(
'https://api/ws/v3/Delivery/orderDetails.php');
if (respo
nse.statusCode == 200) {
String data = response.body;
var cmddetails = jsonDecode(data);
print(cmddetails);
} else {
print(response.statusCode);
}
print('');
}
#override
Widget build(BuildContext context) {
getData();
return MaterialApp(
home: Scaffold(
backgroundColor: Colors.lightBlue,
),
);
}
}
Did you try this?
var response = await http.post('https://www.apiurl.com/ws/v2/details.php', body: {'OrderID': 1209, 'OtherParam': 'value'});
Then in PHP
$OrderID = $_POST["OrderID"];
$OtherParam = $_POST["OtherParam"];
Make sure to sanitize the variables to avoid SQL Injections
And then you can send JSON back to dart/flutter.
Pre-check: Are your sure that this URL expects http-POST not http-GET?
You want to add orderID to the request, right?
If that's the case, first you need to find if API expects this parameter as query parameter or part of the body.
Nevertheless, here are examples for both cases.
String orderDetailsUrl = 'https://www.monresto.net/ws/v3/Delivery/orderDetails.php';
orderID as query parameter:
orderDetailsUrl += "?orderID=FIXME_ORDER_ID";
http.Response response = await http.post(orderDetailsUrl);
orderID as part of request body:
Map<String, dynamic> data = Map()
..putIfAbsent("orderID", () => "FIXME_ORDER_ID")
var body = jsonEncode(data);
http.Response response = await http.post(orderDetailsUrl, headers: {"Content-Type": "application/json"}, body: body);

How to post JSON to api in flutter? [duplicate]

I am trying to send a Json over HTTP post to update a record in my database. I've connected to the server but I'm getting a 415 "Unsupported Media Type" error when I run the request.
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String url = 'http://<Hostname>:
<Port>/jderest/orchestrator/JDE_ORCH_Sample_UpdateMeterReadings_Generic';
Future<String> makeRequest() async {
var response = await http
.post(Uri.encodeFull(url), body: json.encode({
"NewHourMeterReading": "650",
"EquipmentNumber": "34665",
"NewFuelMeterReading": "650"
}), headers: {"Accept": "application/json"});
print(response.body);
}
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new RaisedButton(
child: new Text('Make Request'),
onPressed: makeRequest,
)));
}
}
Can someone please let me know how to get past this error?
the error that I am facing is this.
I/flutter ( 5881): Unsupported Media Type
Screenshot of Response Headers/Status Code/Body
Sorry for the messy code, it didn't copy paste over every well.
You'll have to add the content-type to your header, setting its value to application/json.
By specifying Accept you're saying that your client is able to understand that response type, not that your request content is of the JSON type.
Basically you're saying "hey there, I'm able to understand JSON, so you can send it to me and I'll be fine with it" but you're not saying "hey I'm going to send you a JSON, be prepared for it!"
For a better understanding, you can find more about Accept here and Content-type here.
You are using incomplete headers for sending the json payload. That is why the server is not accepting you request.
Use the following headers instead:
headers: {
"content-type" : "application/json",
"accept" : "application/json",
},
Send Json and Accept Json using:-
Future<String> addData(Map<String, dynamic> request) async {
final url = 'http_url';
try {
final response = await http.post(url,
headers: {
"content-type" : "application/json",
"accept" : "application/json",
},
body: jsonEncode(request));
final responseData = jsonDecode(response.body) as Map<String,dynamic>;
return responseData['message'];
} catch (error) {
throw error;
}
}

I want to execute a function when the Flutter app starts

I want to send an ID to the server and receive json when the app is launched.
Flow
1.Start my app (Show splash screen)
2.Json request to server
3.If there is data, display page1. If not, display page2
it seems you my need to get a bit more learning about Flutter, my sugest is to start with this one only 10 euros will give you base from where will be easier to learn the rest, that said, to get a databse i'm using this code:
//lib/services/networking_service.dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
class NetworkHelper {
final String json;
final url = 'HERE YOU CAN PUT YOUR API URL';
NetworkHelper(this.json);
Map<String, String> headers = {
"Content-type": "application/x-www-form-urlencoded"
};
Future getData(BuildContext context) async {
http.Response response = await http.post(url, body: json, headers: headers);
if (response.statusCode == 200) {
Map<String, dynamic> decodedResp = jsonDecode(response.body);
print(decodedResp);
return decodedResp;
} else {
print(response.statusCode);
return null;
}
}
}
You can call it from your main like this:
static getCategories(BuildContext context) async {
String json =
'q={"f":"listCategories","Store_id":"$storeId","LANG":"$lang","UID":"$uid"}';
//THIS json VARIABLE IS WHERE YOU NEED TO PUT YOUR API CALL LĂ“GIC TO GET THAT ID, I LEAVE THIS FOR YOUR BETTER UNDERSTANDING
NetworkHelper networkHelper = NetworkHelper(json);
var decodedResp = await networkHelper.getData(context);
final CategoriesModel respData = CategoriesModel.fromJson(decodedResp);
print(respData);
//HERE YOU MAY RETURN O STORE IN PROVIDER YOUR RESPONSE AND SEND THE USER TO THE PAGE YOU CONSIDER
}
If you need more help I'm happy to help, but consider taking the course o learn a bit more, it will be lots more easy and enjoyable after.
use SchedulerBinding it runs when page is opened and widgets are build.
#override
void initState() {
super.initState();
SchedulerBinding.instance.addPostFrameCallback((_) {
// your code after page opens,splash keeps open until work is done
});
}
#override
void initState() {
super.initState();
Timer(
Duration(seconds: 3),// you can do your stuff here when splash screen run
() => Navigator.of(context).pushReplacement(MaterialPageRoute(
builder: (BuildContext context) => LoginScreen())));}
and please put this code into the spalsh screen