Why is GetConnect/GetX/Flutter not calling my backend and returning a null object? - flutter-getx

I'm using get: 4.6.5
I have defined a provider
class CredentialsProvider extends GetConnect implements GetxService {
#override
void onInit() {
httpClient.defaultDecoder =
(val) => Auth.fromJson(val as Map<String, dynamic>);
httpClient.baseUrl = 'http://localhost:1337/api/';
super.onInit();
}
Future<Response<dynamic>> postCredentials(Credentials credentials) async {
return await post('auth/local', credentials);
}
}
In my binding class add it as a dependency
class LoginBinding extends Bindings {
#override
void dependencies() {
Get.lazyPut(() => CredentialsProvider());
Get.lazyPut(() => LoginController());
}
}
And register the LoginView as a route
GetPage(
name: "/login",
page: () => const LoginView(),
binding: LoginBinding(),
)
And added it to my controller
class LoginController extends GetxController {
final provider = Get.put(CredentialsProvider());
//...
}
The controller is used in my LoginView
class LoginView extends GetView<LoginController> {...}
In my MaterialButton of the LoginView I use the onPressed to call the provider and get the result object Auth and print it out as json.
onPressed: () {
var c = Credentials(
identifier: controller.emailController.text,
password: controller.passwordController.text);
controller.provider.postCredentials(c).then((value) {
var auth = value.body as Auth;
print(auth.toJson());
});
},
I generated my Auth model from JSON using the GetX cli:
class Auth {
String? jwt;
User? user;
Auth({this.jwt, this.user});
Auth.fromJson(Map<String, dynamic> json) {
jwt = json['jwt'];
user = json['user'] != null ? User?.fromJson(json['user']) : null;
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['jwt'] = jwt;
if (user != null) {
data['user'] = user?.toJson();
}
return data;
}
}
class User {
int? id;
String? username;
String? email;
String? provider;
bool? confirmed;
bool? blocked;
String? createdAt;
String? updatedAt;
User(
{this.id,
this.username,
this.email,
this.provider,
this.confirmed,
this.blocked,
this.createdAt,
this.updatedAt});
User.fromJson(Map<String, dynamic> json) {
id = json['id'];
username = json['username'];
email = json['email'];
provider = json['provider'];
confirmed = json['confirmed'];
blocked = json['blocked'];
createdAt = json['createdAt'];
updatedAt = json['updatedAt'];
}
Map<String, dynamic> toJson() {
final data = <String, dynamic>{};
data['id'] = id;
data['username'] = username;
data['email'] = email;
data['provider'] = provider;
data['confirmed'] = confirmed;
data['blocked'] = blocked;
data['createdAt'] = createdAt;
data['updatedAt'] = updatedAt;
return data;
}
}
What I get in the console is
flutter: {jwt: null}
And my localhost service is never called.

The issue was with the decoder for the request being different that for the response. So I ended up with something like this:
Future<Auth> postCredentials(Map<String, dynamic> body) async {
var response = await post(
contentType: 'application/json',
decoder: (val) => Auth.fromJson(val as Map<String, dynamic>),
"/api/auth/local",
body);
return response.body as Auth;
}
And I call this via
controller.provider.postCredentials(credentials.toJson());

Related

Login from Flutter into Django Framework always showing Invalid Password

I am trying to login from Flutter to my Django Rest Framework but I am always getting the same error Invalid Password although the credentials are correct.
Here is the login_request_model.dart:
class LoginRequestModel {
LoginRequestModel({
this.username,
this.email,
this.password,
});
late final String? username;
late final String? email;
late final String? password;
LoginRequestModel.fromJson(Map<String, dynamic> json) {
username = json['username'];
email = json['email'];
password = json['password'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['username'] = username;
_data['email'] = email;
_data['password'] = password;
return _data;
}
}
Here is the login_page.dart:
class LoginPage extends StatefulWidget {
const LoginPage({Key? key}) : super(key: key);
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
bool isApiCallProcess = false;
bool hidePassword = true;
GlobalKey<FormState> globalFormKey = GlobalKey<FormState>();
String? userName;
String? password;
#override
void initState() {
super.initState();
}
Rest of the login_page.dart where login is inserted:
Center(
child: FormHelper.submitButton(
"Login",
() {
if (validateAndSave()) {
setState(() {
isApiCallProcess = true;
});
LoginRequestModel model = LoginRequestModel(
username: userName,
password: password,
);
APIService.login(model).then(
(response) {
setState(() {
isApiCallProcess = false;
});
if (response) {
Navigator.pushNamedAndRemoveUntil(
context,
'/home',
(route) => false,
);
} else {
FormHelper.showSimpleAlertDialog(
context,
Config.appName,
"Invalid Username/Password !!",
"OK",
() {
Navigator.of(context).pop();
},
);
}
},
Here is the login_response_model.dart:
class LoginResponse {
dynamic? key;
List<dynamic>? non_field_errors;
LoginResponse({this.key, this.non_field_errors});
factory LoginResponse.fromJson(mapOfBody) {
return LoginResponse(
key: mapOfBody['key'],
non_field_errors: mapOfBody['non_field_errors'],
);
}
}
LoginResponseModel loginResponseJson(String str) =>
LoginResponseModel.fromJson(json.decode(str));
class LoginResponseModel {
dynamic? key;
List<dynamic>? non_field_errors;
LoginResponseModel({this.key, this.non_field_errors});
LoginResponseModel.fromJson(mapOfBody) {
key:
mapOfBody['key'];
non_field_errors:
mapOfBody['non_field_errors'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['key'] = key;
_data['non_field_errors'] = non_field_errors;
return _data;
}
}
class Data {
Data({
required this.username,
required this.email,
required this.date,
required this.id,
required this.key,
});
late final String username;
late final String email;
late final String date;
late final String id;
late final String key;
Data.fromJson(Map<String, dynamic> json) {
username = json['username'];
email = json['email'];
date = json['date'];
id = json['id'];
key = json['key'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['username'] = username;
_data['email'] = email;
_data['date'] = date;
_data['id'] = id;
_data['key'] = key;
return _data;
}
}
In my django rest framework I am getting Bad Request: /api/dj-rest-auth/login/
My question:
As there is not specific error that I am trying to fix, I want to know how can I spot the error by debugging I need an example of how to try and catch error. Is there something wrong with my LoginRequestModel or LoginResponseModel
it is usually a mismatch error, try to check the following
check if the data you are sending from your flutter side, is being recieved accurately from the django side. like for example, if the backend accepts the data like this..
{
"username" : "user",
"password" : "password"
}
and you are sending the data from flutter side like this..
{
"email" : "user",
"password" : "password"
}
it expects a key of username and is receiving an email, then its a bad request
I'm not sure about django being case sensitive, but sending the data as Username instead of username.. this results in a bad request response.
so in short, to debug this.. convert the data you are sending to json and see how the data is being sent.. and check from the django side how its being received.

Get User Model Array List

I need to get payments array in GetUserModel it returns from nodeJs api with database information
I get with this:
List? payments
Future getCurrentUser() async {
var loginDetails = await SharedService.loginDetails();
email = loginDetails?.data.email;
GetUserRequestModel model = GetUserRequestModel(email: email!);
var currentUserInfo = await APIService.getUserInfo(model);
balance = currentUserInfo.data?.balance;
payments = currentUserInfo.data?.payments; //does not working
print(payments)
}
currentUserInfo gives me everythings but I couldnt get payments array. print(payments)
gives me "Instant of payments" output how can I get payments array properly?
This is UserresponseModel:
import 'dart:convert';
GetUserResponseModel getUserResponseModelJSON(String str) =>
GetUserResponseModel.fromJson(json.decode(str));
class GetUserResponseModel {
GetUserResponseModel({
required this.message,
required this.data,
});
late final String message;
late final Data? data;
GetUserResponseModel.fromJson(Map<String, dynamic> json) {
message = json['message'];
data = (json['data'] != null ? Data.fromJson(json['data']) : null);
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['message'] = message;
_data['data'] = data?.toJson();
return _data;
}
}
class Data {
Data({
required this.username,
required this.email,
required this.balance,
required this.date,
required this.payments,
required this.id,
});
late final String username;
late final String email;
late final int balance;
late final String date;
late final List<Payments> payments;
late final String id;
Data.fromJson(Map<String, dynamic> json) {
username = json['username'];
email = json['email'];
balance = json['balance'];
date = json['date'];
payments =
List.from(json['payments']).map((e) => Payments.fromJson(e)).toList();
id = json['id'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['username'] = username;
_data['email'] = email;
_data['balance'] = balance;
_data['date'] = date;
_data['payments'] = payments.map((e) => e.toJson()).toList();
_data['id'] = id;
return _data;
}
}
class Payments {
Payments({
required this.paymentCost,
required this.paymentDate,
required this.id,
});
late final int paymentCost;
late final String paymentDate;
late final String id;
Payments.fromJson(Map<String, dynamic> json) {
paymentCost = json['paymentCost'];
paymentDate = json['paymentDate'];
id = json['_id'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['paymentCost'] = paymentCost;
_data['paymentDate'] = paymentDate;
_data['_id'] = id;
return _data;
}
}
And this is the getUserInfo:
static Future<GetUserResponseModel> getUserInfo(
GetUserRequestModel model) async {
var loginDetails = await SharedService.loginDetails();
Map<String, String> requestHeaders = {
'Content-Type': 'application/json',
'Authorization': 'Basic ${loginDetails!.data.token}'
};
var url = Uri.http(Config.apiURL, Config.getUserInfoAPI);
var response = await client.post(
url,
headers: requestHeaders,
body: jsonEncode(model.toJson()),
);
return getUserResponseModelJSON(response.body);
}
So I think you are looking to print the payments data.
In the payments class you should add
#override
String toString() {
return "";
// Return how you want to print the data. Here you could add for example the JSON output.
}
So the class will look like this
class Payments {
Payments({
required this.paymentCost,
required this.paymentDate,
required this.id,
});
late final int paymentCost;
late final String paymentDate;
late final String id;
Payments.fromJson(Map<String, dynamic> json) {
paymentCost = json['paymentCost'];
paymentDate = json['paymentDate'];
id = json['_id'];
}
Map<String, dynamic> toJson() {
final _data = <String, dynamic>{};
_data['paymentCost'] = paymentCost;
_data['paymentDate'] = paymentDate;
_data['_id'] = id;
return _data;
}
#override
String toString() {
return "${this.paymentCost!} : ${this.paymentDate!} : ${this.id!}";
}
}
I haven't tested this code.

how to pass the model class and return data in flutter

Model class:
#JsonSerializable()
class EmpVerifyEntity extends Equatable {
#JsonKey(name: "access_token")
final String accessToken;
final EmpVerifyEmployee employee;
const EmpVerifyEntity(this.accessToken, this.employee);
factory EmpVerifyEntity.fromJson(Map<String, dynamic> json) =>
_$EmpVerifyEntityFromJson(json);
Map<String, dynamic> toJson() => _$EmpVerifyEntityToJson(this);
static const empty = EmpVerifyEntity(
'123',
EmpVerifyEmployee(
'1', 'avatar', 'sId', 'empName', 'empId', 'designation', 1));
#override
String toString() {
return jsonEncode(this);
}
#override
// TODO: implement props
List<Object?> get props => [accessToken, employee];
}
#JsonSerializable()
class EmpVerifyEmployee extends Equatable {
#JsonKey(name: "password")
final String password;
final String avatar;
#JsonKey(name: "_id")
final String sId;
#JsonKey(name: "emp_name")
final String empName;
#JsonKey(name: "emp_id")
final String empId;
final String designation;
#JsonKey(name: "__v")
final int iV;
const EmpVerifyEmployee(this.password, this.avatar, this.sId, this.empName,
this.empId, this.designation, this.iV);
factory EmpVerifyEmployee.fromJson(Map<String, dynamic> json) =>
_$EmpVerifyEmployeeFromJson(json);
Map<String, dynamic> toJson() => _$EmpVerifyEmployeeToJson(this);
static const empty = const EmpVerifyEmployee(
'password', 'avatar', 'sId', 'empName', 'empId', 'designation', 1);
#override
String toString() {
return jsonEncode(this);
}
#override
// TODO: implement props
List<Object?> get props =>
[password, avatar, sId, empName, empId, designation, iV];
}
auth repo:
class AuthenticationRepository {
Future<void> logIn({ //login process
required String username,
required String password,
}) async {
print("------------------");
print(username);
var res = await http.post(
Uri.parse("https://cots.com/api/v1/employee/login"),
headers: {
'Content-type': 'application/json',
'Accept': 'application/json'
},
body: jsonEncode({"emp_id": username, "password": password}));
dynamic data = json.decode(res.body);
print(data);
if (data['employee']["is_active"] == true) {
_controller.add(AuthenticationStatus.authenticated);///here it shows authenticated
}
}
User Repo:
class UserRepository {
EmpVerifyEntity? _empVerifyEntity;
UserRepository(this._empVerifyEntity);
Future<EmpVerifyEntity?> getUser() async {
if (_empVerifyEntity != null) {
return _empVerifyEntity;
}
}
}
Auth Bloc:
class AuthenticationBloc
extends Bloc<AuthenticationEvent, AuthenticationState> {
AuthenticationBloc({
required AuthenticationRepository authenticationRepository,
required UserRepository userRepository,
}) : _authenticationRepository = authenticationRepository,
_userRepository = userRepository,
super(const AuthenticationState.unknown()) {
on<AuthenticationStatusChanged>(_onAuthenticationStatusChanged);
on<AuthenticationLogoutRequested>(_onAuthenticationLogoutRequested);
_authenticationStatusSubscription = _authenticationRepository.status.listen(
(status) => add(AuthenticationStatusChanged(status)),
);
}
final AuthenticationRepository _authenticationRepository;
final UserRepository _userRepository;
late StreamSubscription<AuthenticationStatus>
_authenticationStatusSubscription;
#override
Future<void> close() {
_authenticationStatusSubscription.cancel();
_authenticationRepository.dispose();
return super.close();
}
void _onAuthenticationStatusChanged(
AuthenticationStatusChanged event,
Emitter<AuthenticationState> emit,
) async {
switch (event.status) {
case AuthenticationStatus.unauthenticated:
return emit(const AuthenticationState.unauthenticated());
case AuthenticationStatus.authenticated:
final user = await _tryGetUser();
return emit(user != null
? AuthenticationState.authenticated(user)
: AuthenticationState.unauthenticated());
default:
return emit(const AuthenticationState.unknown());
}
}
void _onAuthenticationLogoutRequested(
AuthenticationLogoutRequested event,
Emitter<AuthenticationState> emit,
) {
_authenticationRepository.logOut();
}
Future<EmpVerifyEntity?> _tryGetUser() async {
try {
final user = await _userRepository.getUser();
return user; /////----------------Here I'm getting null as a user
} catch (e) {
print(e);
}
}
}
I can able to do login but can't able to fetch data because it shows null, In login method I should return data so that I can able to fetch. It is authenticated but user data is null, how to pass the return data to userRepo so that I can fetch in authBloc.
-------------------------------------THank you--------------------------

I am trying to get data from API but having error

This is my model class and I am trying to get all the data but getting error and don't know why.
HomePageModel homePageModelFromJson(String str) => HomePageModel.fromJson(json.decode(str));
String homePageModelToJson(HomePageModel data) => json.encode(data.toJson());
class HomePageModel with ChangeNotifier {
HomePageModel({
this.data,
});
List<Datum>? data;
factory HomePageModel.fromJson(Map<String, dynamic> json) => HomePageModel(
data: List<Datum>.from(json["data"]!.map((x) => Datum.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"data": List<dynamic>.from(data!.map((x) => x.toJson())),
};
}
class Datum {
Datum({
this.schoolid,
this.name,
this.logo,
this.address,
this.contact,
this.principalname,
this.principalcontact,
this.slogan,
this.webAddress,
this.description,
this.email,
this.pan,
this.establishedYear,
});
String? schoolid;
String? name;
String? logo;
String? address;
String? contact;
String? principalname;
String? principalcontact;
String? slogan;
String? webAddress;
String? description;
String? email;
String? pan;
int? establishedYear;
factory Datum.fromJson(Map<String, dynamic> json) => Datum(
schoolid: json["schoolid"],
name: json["name"],
logo: json["logo"],
address: json["address"],
contact: json["contact"],
principalname: json["principalname"],
principalcontact: json["principalcontact"],
slogan: json["slogan"],
webAddress: json["web_address"] == null ? null : json["web_address"],
description: json["description"] == null ? null : json["description"],
email: json["email"],
pan: json["pan"],
establishedYear: json["established_year"],
);
Map<String, dynamic> toJson() => {
"schoolid": schoolid,
"name": name,
"logo": logo,
"address": address,
"contact": contact,
"principalname": principalname,
"principalcontact": principalcontact,
"slogan": slogan,
"web_address": webAddress == null ? null : webAddress,
"description": description == null ? null : description,
"email": email,
"pan": pan,
"established_year": establishedYear,
};
}
This is how I am trying to fetch data:
class HomePageModels with ChangeNotifier{
List<HomePageModel> _hItem = [];
List<HomePageModel> get hItem{
return [..._hItem];
}
Future<void> getHomeData(BuildContext context) async{
const url = "https://shikshyasoftware.com.np/CoreApplicationandAPIService-4617993073/api/school";
try{
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body);
List<HomePageModel> loadedHomeData = [];
if(extractedData == null){
return;
}
if(response.statusCode == 200){
print(extractedData);
}
extractedData.forEach((element){
loadedHomeData.add(HomePageModel.fromJson(element));
});
_hItem = loadedHomeData;
// EasyLoading.showSuccess("data fetched sucessfull");
notifyListeners();
}catch(e){
rethrow;
}
}
}
But I am getting error:
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: type '(dynamic) => Null' is not a subtype of type '(String, dynamic) => void' of 'f'
The problem is the way you are trying to parse the data, you don't need to loop over every element to parse it, in your model just make it return a list type like this,
class HomePageModel with ChangeNotifier {
List<Datum>? data;
HomePageModel({this.data});
HomePageModel.fromJson(Map<String, dynamic> json) {
if (json['data'] != null) {
data = <Datum>[];
json['data'].forEach((v) {
data!.add(new Datum.fromJson(v));
});
}
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
if (this.data != null) {
data['data'] = this.data!.map((v) => v.toJson()).toList();
}
return data;
}
}
class Datum {
Datum({
this.schoolid,
this.name,
this.logo,
this.address,
this.contact,
this.principalname,
this.principalcontact,
this.slogan,
this.webAddress,
this.description,
this.email,
this.pan,
this.establishedYear,
});
String? schoolid;
String? name;
String? logo;
String? address;
String? contact;
String? principalname;
String? principalcontact;
String? slogan;
String? webAddress;
String? description;
String? email;
String? pan;
int? establishedYear;
Datum.fromJson(Map<String, dynamic> json) {
schoolid = json["schoolid"];
name = json["name"];
logo = json["logo"];
address = json["address"];
contact = json["contact"];
principalname = json["principalname"];
principalcontact = json["principalcontact"];
slogan = json["slogan"];
webAddress = json["web_address"];
description = json["description"];
email = json["email"];
pan = json["pan"];
establishedYear = json["established_year"];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['schoolid'] = this.schoolid;
data['name'] = this.name;
data['logo'] = this.logo;
data['address'] = this.address;
data['contact'] = this.contact;
data['principalname'] = this.principalname;
data['principalcontact'] = this.principalcontact;
data['slogan'] = this.slogan;
data['web_address'] = this.webAddress;
data['description'] = this.description;
data['email'] = this.email;
data['pan'] = this.pan;
data['established_year'] = this.establishedYear;
return data;
}
}
and in your view model you can just parse the extracted data from response.body like this,
class HomePageModels with ChangeNotifier {
HomePageModel? _hItem;
HomePageModel get hItem {
return _hItem!;
}
Future<void> getHomeData(BuildContext context) async {
const url =
"https://shikshyasoftware.com.np/CoreApplicationandAPIService-
4617993073/api/school";
try {
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
final extractedData = json.decode(response.body);
if (extractedData == null) {
return;
}
if (response.statusCode == 200) {
print(extractedData);
}
HomePageModel loadedHomeData =
HomePageModel.fromJson(extractedData);
_hItem = loadedHomeData;
// EasyLoading.showSuccess("data fetched sucessfull");
notifyListeners();
} catch (e) {
rethrow;
}
}
}
getHomeData(BuildContext context) async {
const url =
"https://shikshyasoftware.com.np/CoreApplicationandAPIService-4617993073/api/school";
try {
// EasyLoading.show(status: 'Loading...');
final response = await http.get(Uri.parse(url));
if (response.statusCode == 200) {
final extractedData = json.decode(response.body);
List loadedHomeData = extractedData;
_hItem = loadedHomeData.map((e) => HomePageModel.fromJson(e)).toList();
}
notifyListeners();
return _hItem;
} catch (e) {
rethrow;
}
}

Registering User using Flutter and PHP Laravel and saving User info with SharedPreferrence

I am trying to save result from json to SharedPreferrence but i keep getting Unhandled Exception: type 'String' is not a subtype of type 'int' of 'index'
This is my Code
_register(BuildContext context, User user) async {
var _userService = UserService();
var registeredUser = await _userService.createUser(user);
var encodeFirst = json.encode(registeredUser.body);
var result = json.decode(encodeFirst);
if(result['result'] == true){
SharedPreferences _prefs = await SharedPreferences.getInstance();
_prefs.setInt("userId", result["user"]["id"]);
_prefs.setString("userName", result["user"]["name"]);
_prefs.setString("userEmail", result["user"]["email"]);
Navigator.push(
context, MaterialPageRoute(builder: (context) => CheckoutScreen(cartItems: this.widget.cartItems,)));
} else {
_showSnackMessage(Text('Failed to register the user!', style: TextStyle(color: Colors.red),));
}
}
this is my User, UserService and Repository file
class User{
int id;
String name;
String email;
String password;
toJson(){
return{
'id': id.toString(),
'name': name,
'email': email,
'password': password
};
}
}
class UserService {
Repository _repository;
UserService(){
_repository = Repository();
}
createUser(User user) async{
return await _repository.httpPost('register', user.toJson());
}
}
httpPost(String api, data) async {
return await http.post(_baseUrl + "/" + api, body: data);
}
var encodeFirst = json.encode(registeredUser.body); will call User toJson()
And in toJson() , you have set 'id': id.toString(),
when you do var result = json.decode(encodeFirst);
It's actually a string not int
Correct toJson() please see below
// To parse this JSON data, do
//
// final user = userFromJson(jsonString);
import 'dart:convert';
User userFromJson(String str) => User.fromJson(json.decode(str));
String userToJson(User data) => json.encode(data.toJson());
class User {
int id;
String name;
String email;
String password;
User({
this.id,
this.name,
this.email,
this.password,
});
factory User.fromJson(Map<String, dynamic> json) => User(
id: json["id"],
name: json["name"],
email: json["email"],
password: json["password"],
);
Map<String, dynamic> toJson() => {
"id": id,
"name": name,
"email": email,
"password": password,
};
}