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

Android模拟器无法向本地XAMPP站点发送.NET MAUI POST请求

解决.NET MAUI向本地XAMPP Apache发送POST请求失败的问题

针对你遇到的连接失败、XAMPP日志无连接记录的问题,按以下步骤排查:

1. 验证基础连通性

  • 模拟器/浏览器测试:
    • 安卓模拟器用10.0.2.2映射主机localhost,先在电脑浏览器访问http://localhost/GuppyTown_CISP316/php/submit.php,确认页面能正常访问(哪怕返回错误,只要有响应就说明Apache服务正常)。
    • iOS模拟器直接用http://localhost/...或主机局域网IP;物理设备必须使用电脑的局域网IP(如192.168.1.100),且设备与电脑在同一WiFi下。
  • 防火墙检查:暂时关闭电脑防火墙,测试是否能连通,若能则需配置防火墙允许Apache的80端口(默认)接收外部连接。

2. 修正Apache配置

  • 打开httpd.conf,确保:
    • Listen 80未被注释,若修改过端口需同步URL中的端口号。
    • 网站根目录的<Directory>配置允许外部访问,将Require local改为Require all granted:
      <Directory "C:/xampp/htdocs/GuppyTown_CISP316/">
          AllowOverride All
          Require all granted
      </Directory>
      
  • 若使用虚拟主机,检查httpd-vhosts.conf,确保虚拟主机配置包含正确的IP绑定和访问权限。

3. 配置.NET MAUI网络权限

  • Android:
    在Platforms/Android/AndroidManifest.xml中添加:
    <uses-permission android:name="android.permission.INTERNET" />
    <application android:usesCleartextTraffic="true">...</application>
    
    (usesCleartextTraffic用于允许明文HTTP请求,Android 9+默认禁止)
  • iOS:
    在Platforms/iOS/Info.plist中添加App Transport Security配置:
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    
  • Windows:
    在Platforms/Windows/Package.appxmanifest中启用Internet (Client)权限。

4. 代码优化与错误排查

  • HttpClient单例化:
    在MauiProgram.cs中注册ApiService为单例,避免频繁创建HttpClient导致连接耗尽:
    builder.Services.AddSingleton<ApiService>();
    
    之后在MainPage构造函数通过依赖注入获取实例,而非手动new。
  • 捕获详细错误:
    修改catch块,打印内部异常信息以获取更具体的失败原因:
    catch (HttpRequestException httpEx)
    {
        upload_status.Text = $"请求错误: {httpEx.Message},内部错误: {httpEx.InnerException?.Message}";
    }
    
  • 先测试Get请求:
    新增Get请求方法,测试能否获取服务器响应,排除POST序列化问题:
    public async Task<string> SendGetRequestAsync(string url)
    {
        var response = await _httpClient.GetAsync(url);
        return response.IsSuccessStatusCode ? await response.Content.ReadAsStringAsync() : null;
    }
    

5. 日志分析

  • 查看XAMPP的access.log(而非仅error.log),如果请求到达服务器,这里会有记录;若无记录,说明请求未发送到服务器,重点排查网络连通性和权限。

你的代码整理:

using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace AppSiteTest;

public class ApiService
{
    private readonly HttpClient _httpClient;

    public ApiService()
    {
        _httpClient = new HttpClient();
    }

    // POST方法,用于第二个点击事件
    public async Task<string> SendPostRequestAsync(string url, object data)
    {
        var jsonData = JsonSerializer.Serialize(data);
        var content = new StringContent(jsonData, Encoding.UTF8, "application/json");

        var response = await _httpClient.PostAsync(url, content);

        if (response.IsSuccessStatusCode)
        {
            var responseString = await response.Content.ReadAsStringAsync();
            return responseString;
        }

        return null;
    }
}

public partial class MainPage : ContentPage
{
    private readonly ApiService _apiService;

    private int rowCount = 0;
    private int columnCount = 0;

    private string _photoPath;
    public string PhotoPath
    {
        get => _photoPath;
        set
        {
            _photoPath = value;
            OnPropertyChanged(nameof(PhotoPath));
        }
    }

    public MainPage()
    {
        InitializeComponent();
        BindingContext = this;
        photo_grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(100) });
        _apiService = new ApiService();
    }

    // 忽略此点击事件
    public async void Button_Clicked(object sender, EventArgs args)
    {
        if (MediaPicker.Default.IsCaptureSupported)
        {
            FileResult photo = await MediaPicker.Default.CapturePhotoAsync();

            if (photo != null)
            {
                // 保存文件到本地存储
                string localFilePath = Path.Combine(FileSystem.CacheDirectory, photo.FileName);

                using Stream sourceStream = await photo.OpenReadAsync();
                using FileStream localFileStream = File.OpenWrite(localFilePath);

                await sourceStream.CopyToAsync(localFileStream);

                if (PhotoPath != null)
                {
                    photo_grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(75) });
                    columnCount++;

                    var gridPhoto = new Image
                    {
                        Source = PhotoPath,
                        BackgroundColor = Colors.AliceBlue,
                        HorizontalOptions = LayoutOptions.Center,
                        VerticalOptions = LayoutOptions.Center
                    };

                    photo_grid.Add(gridPhoto, columnCount, rowCount);
                }

                PhotoPath = localFilePath;
            }
        }
    }

    // 尝试发送POST请求
    public async void btn_Post_Clicked(object sender, EventArgs args)
    {
        upload_status.Text = "尝试连接中";
        var url = "http://10.0.2.2/GuppyTown_CISP316/php/submit.php";
        var data = new { fname = "John", lname = "Smith", email = "email@gmail.com", phone = "000-000-0000", tip = "From .net Maui" };
        upload_status.Text = "数据和URL已加载";
        try
        {
            var response = await _apiService.SendPostRequestAsync(url, data);
            upload_status.Text = response ?? "无服务器响应";
        }
        catch (HttpRequestException httpEx)
        {
            upload_status.Text = $"请求错误: {httpEx.Message} {url}";
        }
        catch (Exception e)
        {
            upload_status.Text = $"通用错误: {e.Message}";
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 07:14:53