MAUI开发笔记(二)

发布时间 2023-12-19 19:51:27作者: wzwyc

今天试了一下,在MAUI上调用WEB API。经常一番努力,终于调用成功。不过这里面还是有很多的坑。

MAUI分了好几个平台,一般来说,最容易成功的是Windows平台。

坑1:HttpClient的方法

总体来说,其实是用HttpClient来调用。
但是HttpClient的方法使用上,也有坑。
最开始我使用的是下面的一些接口:

await _client.GetFromJsonAsync<TodoItem>($"Todo/{id}");
HttpResponseMessage response = await _client.PostAsJsonAsync("Todo", info);
HttpResponseMessage response = await _client.PutAsJsonAsync($"Todo/{info.Id}", info);

这些接口在Windows上执行没有问题的,但是跑Android虚拟机的时候,直接报错了。
应该是这些接口都是属于扩展接口,只支持Windows平台的。

所以最终的接口都换成了下面这种形式:

Uri uri = new Uri(string.Format(Constants.RestUrl, string.Empty));
HttpResponseMessage response = await _client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
    string content = await response.Content.ReadAsStringAsync();
    return JsonSerializer.Deserialize<List<TodoItem>>(content, _serializerOptions);
}

完整TodoService类代码:

using System.Diagnostics;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using TodoMaui.Models;

namespace TodoMaui.Services;

public class TodoService : ITodoService
{
    private HttpClient _client;
    private JsonSerializerOptions _serializerOptions;
    private IHttpsClientHandlerService _httpsClientHandlerService;

    public TodoService(IHttpsClientHandlerService service)
    {
#if DEBUG
        _httpsClientHandlerService = service;
        HttpMessageHandler handler = _httpsClientHandlerService.GetPlatformMessageHandler();
        if (handler != null)
            _client = new HttpClient(handler);
        else
            _client = new HttpClient();
#else
            _client = new HttpClient();
#endif
        _serializerOptions = new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = true
        };

        _client.BaseAddress = new Uri("http://192.168.126.149:5000/");
        _client.DefaultRequestHeaders.Accept.Clear();
        _client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }

    public async Task<TodoItem> GetTodoItem(long id)
    {
        try
        {
            Uri uri = new Uri(string.Format(Constants.RestUrl, id));
            HttpResponseMessage response = await _client.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                string content = await response.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<TodoItem>(content, _serializerOptions);
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }

        return null;
    }

    public async Task<List<TodoItem>> GetTodoItems()
    {
        try
        {
            Uri uri = new Uri(string.Format(Constants.RestUrl, string.Empty));
            HttpResponseMessage response = await _client.GetAsync(uri);
            if (response.IsSuccessStatusCode)
            {
                string content = await response.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<List<TodoItem>>(content, _serializerOptions);
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }

        return null;
    }

    public async Task<TodoItem> AddTodoItem(TodoItem item)
    {
        try
        {
            string json = JsonSerializer.Serialize<TodoItem>(item, _serializerOptions);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");

            Uri uri = new Uri(string.Format(Constants.RestUrl, string.Empty));
            HttpResponseMessage response = await _client.PostAsync(uri, content);
            if (response.IsSuccessStatusCode)
            {
                json = await response.Content.ReadAsStringAsync();
                return JsonSerializer.Deserialize<TodoItem>(json, _serializerOptions);
            }
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }

        return null;
    }

    public async Task UpdateTodoItem(TodoItem item)
    {
        try
        {
            string json = JsonSerializer.Serialize<TodoItem>(item, _serializerOptions);
            StringContent content = new StringContent(json, Encoding.UTF8, "application/json");

            Uri uri = new Uri(string.Format(Constants.RestUrl, item.Id));
            HttpResponseMessage response = await _client.PutAsync(uri, content);
            response.EnsureSuccessStatusCode();
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }

    public async Task DeleteTodoItem(long id)
    {
        try
        {
            Uri uri = new Uri(string.Format(Constants.RestUrl, id));
            HttpResponseMessage response = await _client.DeleteAsync(uri);
            response.EnsureSuccessStatusCode();
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }
}

坑2:Android权限

因为用到了联网的功能,需要添加权限。我的AndroidManifest.xml文件内容:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
	<application android:allowBackup="true" android:icon="@mipmap/appicon" android:supportsRtl="true"></application>
	<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
	<uses-permission android:name="android.permission.INTERNET" />
	<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
	<uses-sdk />
</manifest>

好久没玩Android系统了,忘了这货还有权限的设置。关键提示太不明显了。

坑3:禁用Http协议

Android默认是禁用HTTP协议的,如果要启用,要设置一下。我懒得去设置,就直接把WEB API改成HTTPS协议了。