如何在.NET MAUI 中正确使用 DI 和 IHttpClientFactory

问题描述 投票:0回答:2

我在.NET MAUI 中没有找到任何关于 HttpClient 的信息。

有谁知道这项服务:

builder.Services.AddHttpClient<IMyService, MyService>();
可以在MAUI的启动MauiProgram.cs中吗?然后将 HttpClient 注入到要使用它的地方。我已经尝试了一切,但似乎不起作用。只有 HttpClient 的 AddSingleton 对我有用,但它似乎不是最佳的。

PS.:我必须安装 nuget 包 Microsoft.Extensions.Http 才能使用 AddHttpClient 服务。

更新

工作代码:

MauiProgram.cs

builder.Services.AddTransient<Service<Display>, DisplayService>();
builder.Services.AddTransient<Service<Video>, VideoService>();
builder.Services.AddTransient<Service<Image>, ImageService>();
builder.Services.AddTransient<Service<Log>, LogService>();

builder.Services.AddSingleton(sp => new HttpClient() { BaseAddress = new Uri("https://api.myapi.com") });

使用服务的 VideosViewModel.cs 示例

[INotifyPropertyChanged]
public partial class VideosViewModel
{
    readonly Service<Video> videoService;
    
    [ObservableProperty]
    ObservableCollection<Video> videos;

    [ObservableProperty]
    bool isEmpty;
    
    [ObservableProperty]
    bool isRefreshing;
    
    public VideosViewModel(Service<Video> videoService)
    {
        this.videoService = videoService;
    }

    [ICommand]
    internal async Task LoadVideosAsync()
    {
#if ANDROID || IOS || tvOS || Tizen
        UserDialogs.Instance.ShowLoading("Henter videoer fra databasen...");
#endif
        await Task.Delay(2000);
        
        Videos = new();

        try
        {
            await foreach (Video video in videoService.GetAllAsync().OrderBy(x => x.Id))
            {
                Videos.Add(video);
            }
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
        finally
        {
            IsRefreshing = false;
#if ANDROID || IOS || tvOS
            UserDialogs.Instance.HideLoading();
#endif

            if (Videos.Count is 0)
            {
                IsEmpty = true;
            }
            else
            {
                IsEmpty = false;
            }
        }
    }
    
    [ICommand]
    async Task UploadVideoAsync()
    {
        await Shell.Current.DisplayAlert("Upload en video", "Under opbygning - kommer senere!", "OK");
    }
}

无法运行代码:

MauiProgram.cs

builder.Services.AddHttpClient<Service<Display>, DisplayService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Video>, VideoService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Image>, ImageService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));
builder.Services.AddHttpClient<Service<Log>, LogService>(sp => sp.BaseAddress = new Uri("https://api.myapi.com"));

VideosViewModel.cs 与上面的工作代码相同。

具体不起作用的是我在 OrderBy(x => x.Id) 上遇到对象引用异常,特别是在 ViewModel 中突出显示了 x.Id。删除 OrderBy 方法不再出现异常,但视图除了一个随机的空框架之外不显示任何数据。

httpclient maui .net-maui
2个回答
2
投票

请勿在 MAUI 中使用 builder.Services.AddHttpClient。 使用一个实例。


1
投票

builder.Services.AddHttpClient 对我有用。这是我的设置方式:在主程序中,我添加了 .AddHttpClient()

public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
    var builder = MauiApp.CreateBuilder();
    builder.Services.AddHttpClient();
    builder
        .UseMauiApp<App>()
        .ConfigureFonts(fonts =>
        {
            fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
        });

 #if DEBUG
    builder.Logging.AddDebug();
 #endif

    return builder.Build();
}
}

在 AppShell.xaml 中,我删除了 DataTemplate 定义,使其成为准系统:

<Shell
    x:Class="MAUIMultiPage.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:MAUIMultiPage"
    Shell.FlyoutBehavior="Disabled">

    <TabBar>
        <ShellContent
        x:Name="homepage"
        Title="Home"
         />
        <ShellContent
        x:Name="specialOpsPage"
        Title="Special Ops"
         />

    </TabBar>

</Shell>

请注意,我为 ShellContents 指定了 x:Name。 DataTemplates 在 AppShell.xaml 后面的代码中定义,我可以在其中传递一个带有 IHttpClientFactory 的 Func 对象作为 DI 参数,如下所示:

public partial class AppShell : Shell
{
    public AppShell(IHttpClientFactory httpClientFactory)
    {
        InitializeComponent();

        homepage.ContentTemplate = new DataTemplate(() => new MainPage(httpClientFactory));
        specialOpsPage.ContentTemplate = new DataTemplate(() => new SpecialOps(httpClientFactory));
    }
}

对于App类,我们可以注入IHttpClientFactory,它被传递给AppShell:

public partial class App : Application
{
    public App(IHttpClientFactory httpClientFactory)
    {
        InitializeComponent();

        MainPage = new AppShell(httpClientFactory);
    }
}

在每个单独的页面中,我都会从 PageCollection 类中获得 iHttpClientFactory

  public partial class SpecialOps : ContentPage
   {
    private readonly IHttpClientFactory _httpClientFactory;

        public SpecialOps(IHttpClientFactory httpClientFactory)
        {
            InitializeComponent();
            this._httpClientFactory = httpClientFactory;
        }
    
        private async void Button_Clicked(object sender, EventArgs e)
        {
            var httpClient = _httpClientFactory.CreateClient();
            var result = await httpClient.GetAsync("https://dummy.restapiexample.com/api/v1/employees");
            txtResult.Text = await result.Content.ReadAsStringAsync();
        }
    }

此示例的完整解决方案位于我的 GitHub 存储库中:https://github.com/yogigrantz/MAUIWithHttpClientFactory

© www.soinside.com 2019 - 2024. All rights reserved.