You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter通过参数调用API报错400:请求数据问题排查

代码中的错误分析及修正方案

核心错误(直接导致400 Bad Request的原因)

  • URL参数拼接存在语法错误:请求URL中混入了无关的HTML标签(<span class="math-inline">、</span>),同时字符串插值语法错误:
    • 错误示例:TotalRooms=<span class="math-inline">totalroom、OccupiedRooms=</span>{OccupiedRoom.toStringAsFixed(2)}
    • 正确写法:使用Dart标准的字符串插值语法$变量名或${表达式},并移除所有无关HTML标签。
  • 传递格式化后的字符串而非原始数值:roomRevenue和TotalRevenue是经formatter.format()处理后的带格式字符串(可能包含逗号、货币符号等),后端无法将这类字符串解析为数字类型,触发参数校验失败。
    • 例如formatter.format(1234)可能输出"1,234",后端无法识别为有效数字。

其他逻辑/语法问题

  • 嵌套函数定义不合理:将submitform()函数定义在setState()回调内部,逻辑混乱且可能引发上下文相关问题,建议移到setState外部或直接内联请求逻辑。
  • POST请求参数放置不符合规范:虽然URL传参可行,但POST请求通常将参数放在请求体(body)中,而非URL查询参数,更符合RESTful规范且避免URL过长问题。
  • 冗余类型转换:多处存在不必要的类型转换,比如double.parse(((OccupiedRoom/totalroom)*100).toStringAsFixed(2)),可直接计算后保留小数,无需转字符串再转回double。

修正后的代码示例

// 将提交函数移到setState外部
Future<void> submitForm(String hotel, String date, int totalroom, double occupiedRoom, double adr, double occRate, double totalRoomRevenue, double revPAR, int fnbRevenue, double rawTotalRevenue) async {
  print('ready');
  // 构建正确的URL参数,移除HTML标签,使用标准插值语法
  final uri = Uri.parse(
    'http://xxxx/xxxx/api/hotel/InsertHotelDailyRevenue'
    '?hotel=$hotel'
    '&RptDate=$date'
    '&TotalRooms=$totalroom'
    '&OccupiedRooms=${occupiedRoom.toStringAsFixed(2)}'
    '&OccupancyRate=${occRate.toStringAsFixed(2)}'
    '&ADR=${adr.toStringAsFixed(2)}'
    '&RevPAR=${revPAR.toStringAsFixed(2)}'
    '&TotalRoomRevenue=$totalRoomRevenue'
    '&TotalFnBRevenue=$fnbRevenue'
    '&TotalRevenue=$rawTotalRevenue'
  );

  final response = await http.post(
    uri,
    headers: <String, String>{
      'Content-Type': 'application/x-www-form-urlencoded',
    },
  );

  print('after api');

  if (response.statusCode == 201) {
    print('201');
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('Data submitted successfully!')),
    );
  } else {
    String errorMessage = 'Failed to submit data.';
    switch (response.statusCode) {
      case 400:
        errorMessage = 'Bad request. Please check the submitted data.';
        break;
      case 401:
        errorMessage = 'Unauthorized. Please check your credentials.';
        break;
      case 403:
        errorMessage = 'Forbidden. You are not authorized to submit data.';
        break;
      default:
        errorMessage = 'Error: ${response.statusCode}';
    }
    throw Exception(errorMessage);
  }
}

// 原setState逻辑修正
setState(()  {
  String OccRoomText = _occRoomController.text;
  String ADRText = _adrController.text;
  String FnBRevenueText = _fnbrevenueController.text;
  String extraRevenueText = _extrarevenueController.text;      
  
  if (_formKey.currentState!.validate()) {
    print('2');
    String hotel = 'DTH';
    String date = _dateController.text;
    int totalroom = 299;
    double OccupiedRoom = double.parse(OccRoomText);
    double ADR = double.parse(ADRText);
    double FnBRevenue = double.parse(FnBRevenueText);
    double ExtraRevenue = double.parse(extraRevenueText);
    
    // 简化计算,移除冗余类型转换
    occRate = ((OccupiedRoom/totalroom)*100);
    TotalRoomRevenue = OccupiedRoom * ADR;
    RevPAR = TotalRoomRevenue / totalroom;
    TotalFnBRevenue = FnBRevenue + ExtraRevenue;
    int FNBRevenue = TotalFnBRevenue.round();
    final rawTotalRevenue = TotalRoomRevenue + FNBRevenue;
    
    // 格式化仅用于前端展示,不传给后端
    roomRevenue = formatter.format(TotalRoomRevenue.round());
    TotalRevenue = formatter.format(rawTotalRevenue.round());

    print(TotalRevenue);
    
    // 调用外部提交函数
    submitForm(
      hotel, date, totalroom, OccupiedRoom, ADR, occRate,
      TotalRoomRevenue, RevPAR, FNBRevenue, rawTotalRevenue
    ).then((_) {
      print('请求成功');
    }).catchError((error) {
      print(error);
    });
  }
});

内容的提问来源于stack exchange,提问作者unknown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 18:52:05