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

Swift(iOS)调用带[FromForm]参数的.NET WebAPI的正确方式

解决.NET WebAPI [FromForm]参数绑定的Swift调用方案

核心原因

你的.NET WebAPI方法用了[FromForm]特性,这要求请求必须以multipart/form-data格式提交参数——和JavaScript中FormData的提交格式完全一致。之前尝试的application/x-www-form-urlencoded、URLQueryItem、JSON编码都不符合[FromForm]的绑定规则,所以会触发参数缺失的错误。

原生Swift实现方案

直接构建符合multipart/form-data规范的请求,模拟JS的FormData提交逻辑:

import Foundation

func setScreenName(guid: String, screenName: String, completion: @escaping (Result<Void, Error>) -> Void) {
    // 替换为你的API实际地址
    guard let apiUrl = URL(string: "https://your-api-host/api/your-controller/SetScreenName") else {
        let invalidURLError = NSError(domain: "SetScreenNameError", code: -1, userInfo: [NSLocalizedDescriptionKey: "API地址无效"])
        completion(.failure(invalidURLError))
        return
    }
    
    var request = URLRequest(url: apiUrl)
    request.httpMethod = "POST"
    
    // 生成唯一的边界字符串,用于分隔表单字段
    let boundary = UUID().uuidString
    request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    
    var formData = Data()
    
    // 添加guid参数
    formData.append("--\(boundary)\r\n".data(using: .utf8)!)
    formData.append("Content-Disposition: form-data; name=\"guid\"\r\n\r\n".data(using: .utf8)!)
    formData.append("\(guid)\r\n".data(using: .utf8)!)
    
    // 添加screenName参数
    formData.append("--\(boundary)\r\n".data(using: .utf8)!)
    formData.append("Content-Disposition: form-data; name=\"screenName\"\r\n\r\n".data(using: .utf8)!)
    formData.append("\(screenName)\r\n".data(using: .utf8)!)
    
    // 结束表单边界
    formData.append("--\(boundary)--\r\n".data(using: .utf8)!)
    
    request.httpBody = formData
    
    URLSession.shared.dataTask(with: request) { _, response, error in
        if let err = error {
            completion(.failure(err))
            return
        }
        
        guard let httpResp = response as? HTTPURLResponse, (200...299).contains(httpResp.statusCode) else {
            let statusCode = (response as? HTTPURLResponse)?.statusCode ?? -1
            let apiError = NSError(domain: "SetScreenNameError", code: statusCode, userInfo: [NSLocalizedDescriptionKey: "请求未成功"])
            completion(.failure(apiError))
            return
        }
        
        completion(.success(()))
    }.resume()
}

Alamofire简化实现

如果你的项目已经使用Alamofire,可以用框架封装的方法快速实现:

import Alamofire

func setScreenNameWithAlamofire(guid: String, screenName: String) {
    AF.upload(
        multipartFormData: { formData in
            formData.append(guid.data(using: .utf8)!, withName: "guid")
            formData.append(screenName.data(using: .utf8)!, withName: "screenName")
        },
        to: "https://your-api-host/api/your-controller/SetScreenName",
        method: .post
    ).responseData { response in
        switch response.result {
        case .success:
            print("设置成功")
        case .failure(let error):
            print("请求失败: \(error)")
        }
    }
}

关键注意事项

  • 参数名称guid和screenName必须与WebAPI控制器方法的参数名完全一致(区分大小写)
  • 不要手动设置Content-Length,URLSession/Alamofire会自动计算并添加
  • 边界字符串必须唯一,用UUID生成是最稳妥的方式

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 23:52:48