'GetX middleware runs before binding?

Here is my Auth middleware:

import 'package:donirajkrv/controllers/user_controller.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';

class AuthMiddleware extends GetMiddleware {
  final authService = Get.find<UserController>().isUserLogged; // Here is error, this line can't find UserController
  @override
  int? get priority => 1;
  bool isAuthenticated = false;

  @override
  RouteSettings? redirect(String? route) {
    isAuthenticated = true;
    if (isAuthenticated == false) {
      return const RouteSettings(name: '/login');
    }
    return null;
  }
}

A line from above (where is my comment) returns me an error:

════════ Exception caught by widgets library ═══════════════════════════════════
The following message was thrown building MyApp(dirty):
"UserController" not found. You need to call "Get.put(UserController())" or "Get.lazyPut(()=>UserController())"

The relevant error-causing widget was
MyApp
lib/main.dart:9

And middleware makes me that error.

...
 GetMaterialApp(
      initialBinding: UserBinding(),
...

I have tried to fix this with:

GetPage(
      name: '/${Routes.HOME_PAGE}',
      page: () => const HomePage(),
      binding: UserBinding(),
      middlewares: [AuthMiddleware()])

But again same error.



Solution 1:[1]

I am here again, with a solution at this time :P

Please add this static method in your user_controller.dart file

static UserController get findOrInitialize{
    try{
      return Get.find<UserController>();
    }catch(e){
      //get controller is not initialized yet
      Get.put(UserController());
      return Get.find<UserController>();
    }
  }

In the initiation of the controller in user_bindings.dart file

instead of

@override
void dependencies() {
    UserController()
  }

do it like this:

@override
  void dependencies() {
    UserController.findOrInitialize;
  }

Finally, in the auth_middleware.dart file

initiate your controller like the example below:

final authService = UserController.findOrInitialize;

You can find the whole example here: https://github.com/Prosa/Flutter-GetX-Bindings-Example

Solution 2:[2]

Problem

The Middleware gets initialized before the Binding. (As to why this happens should be discussed with Getx.)

Solution

Move the Binding out of the method call initialBinding and place it somewhere else. This solution is a bit hacky, but solves the problem with one line of code.

Code Before

  @override
  Widget build(BuildContext context) {

    return GetMaterialApp(
      initialBinding: UserBinding(),
    ...

Code After

  @override
  Widget build(BuildContext context) {
 
    Get.put<UserBinding>(UserBinding()); // ADDED

    return GetMaterialApp(
      // initialBinding: UserBinding(),    REMOVED
    ...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Prodromos Sarakinou
Solution 2