cfug / dio

A powerful HTTP client for Dart and Flutter, which supports global settings, Interceptors, FormData, aborting and canceling a request, files uploading and downloading, requests timeout, custom adapters, etc.
https://dio.pub
MIT License
12.25k stars 1.49k forks source link

incorrect formatting when parsing `multipart` form data using `FormData.fromMap()` causes `NullReferenceException` in .NET backend #2208

Closed MohaAmiry closed 1 week ago

MohaAmiry commented 1 week ago

Package

dio

Version

5.4.1

Operating-System

Android

Adapter

Default Dio

Output of flutter doctor -v

[√] Flutter (Channel stable, 3.19.6, on Microsoft Windows [Version 10.0.22631.3527], locale en-US)
    • Flutter version 3.19.6 on channel stable at C:\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 54e66469a9 (3 weeks ago), 2024-04-17 13:08:03 -0700
    • Engine revision c4cd48e186
    • Dart version 3.3.4
    • DevTools version 2.31.1

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at C:\Users\mdbm\AppData\Local\Android\sdk
    • Platform android-34, build-tools 34.0.0
    • Java binary at: C:\Program Files\Android\Android Studio1\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-b2043.56-10550314)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • CHROME_EXECUTABLE = C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe

[√] Visual Studio - develop Windows apps (Visual Studio Enterprise 2022 17.7.4)
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Enterprise
    • Visual Studio Enterprise 2022 version 17.7.34031.279
    • Windows 10 SDK version 10.0.22621.0

[!] Android Studio (version 2022.3)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    X Unable to determine bundled Java version.
    • Try updating or re-installing Android Studio.

[√] Android Studio (version 2023.1)
    • Android Studio at C:\Program Files\Android\Android Studio1
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.7+0-b2043.56-10550314)

[√] IntelliJ IDEA Ultimate Edition (version 2023.2)
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA 2023.2
    • Flutter plugin version 75.1.4
    • Dart plugin version 232.8660.129

[√] Connected device (4 available)
    • sdk gphone64 x86 64 (mobile) • emulator-5554 • android-x64    • Android 14 (API 34) (emulator)
    • Windows (desktop)            • windows       • windows-x64    • Microsoft Windows [Version 10.0.22631.3527]
    • Chrome (web)                 • chrome        • web-javascript • unknown
    • Edge (web)                   • edge          • web-javascript • Microsoft Edge 124.0.2478.80

[√] Network resources
    • All expected network resources are available.

! Doctor found issues in 1 category.

Dart Version

3.3.4

Steps to Reproduce

1- get a map object like:

var map = {
        "location": {
          "address": "addressfdsfdsafsa",
          "longitude": "1.0",
          "latitude": "2.0"
        },
        "bankCard": {"number": "dsa", "expDate": "2024-05-05"},
        "email": "e@e.com",
        "name": "eee",
        "password": "zaqQ123#",
        "phone": "555555555"
      };
var form = FormData.fromMap(map);
print(form.fields);

Expected Result

the expected parsed value when print(form.fields) is:

[MapEntry(email: e@e.com ), 
MapEntry(password: zaqQ123#),
MapEntry(phone: 555555555),
MapEntry(name: eee),
MapEntry(location: {"address":"addressfdsfdsafsa","longitude":1.0,"latitude":2.0}),
MapEntry(bankCard: {"number":"dsa","expDate":"2024-05-05"})]

notice the location and bankCard values were parsed as jsons.

Actual Result

the actual result when print(form.fields) is:

[MapEntry(location[address]: addressfdsfdsafsa),
MapEntry(location[longitude]: 1.0),
MapEntry(location[latitude]: 2.0),
MapEntry(bankCard[number]: dsa),
MapEntry(bankCard[expDate]: 2024-05-05),
MapEntry(email: e@e.com),
MapEntry(name: eee),
MapEntry(password: zaqQ123#),
MapEntry(phone: 555555555)]

notice the location and bankCard fields were parsed independently in a different format. this causes NullReferenceExceptions when passed to a .NET backend.

AlexV525 commented 1 week ago

This is intended because every field would be converted to String in a FormData. Fields are converted recursively so you'll see location[address]. You should probably add jsonEncode for the value of location and bankCard to make it explicitly a string type.

ref: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects

MohaAmiry commented 1 week ago

@AlexV525 i know, i ended up building the FormData by hand and used jsonEncoder. the issue is the expected output from formData.fromMap is to handle the objects correctly instead of forcing the user to build the formData manually when an object exists in the form.