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

.NET MAUI 7依赖注入出现NullReferenceException问题求助

.NET MAUI 7依赖注入导致NullReferenceException的解决方法

问题根源

你遇到的NullReferenceException由两个核心问题导致:

  1. 未注册HttpClient到DI容器:HttpService的构造函数依赖HttpClient,但你的MauiProgram中没有注册该服务,DI容器无法创建合法的HttpService实例。
  2. 错误使用DependencyService获取服务:.NET MAUI的内置DI容器与Xamarin的DependencyService不属于同一体系,用DependencyService.Get<IHttpService>()无法获取到MAUI DI容器中注册的服务,返回值为null,最终导致ViewModel中的_httpService为空。

解决步骤

步骤1:在DI容器中注册HttpClient

修改MauiProgram.cs,添加HttpClient的注册(推荐使用AddHttpClient配置基础地址等参数):

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();

        // 注册HttpClient并绑定到IHttpService
        builder.Services.AddHttpClient<IHttpService, HttpService>(client =>
        {
            client.BaseAddress = new Uri("https://localhost:44386/");
        });
    
        builder
            .UseMauiApp<App>()
            .UseMauiCommunityToolkit()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
            });
            
#if DEBUG
        builder.Logging.AddDebug();
#endif

        // 注册ViewModel和页面到DI容器
        builder.Services.AddTransient<LoginPageViewModel>();
        builder.Services.AddTransient<LoginPage>();

        return builder.Build();
    }
}

步骤2:通过构造函数注入获取服务

放弃DependencyService,使用构造函数注入的方式获取ViewModel,这是MAUI DI的标准用法:

public partial class LoginPage : ContentPage
{
    private string uText, pText;
    private readonly LoginPageViewModel _viewModel;

    // 构造函数注入ViewModel
    public LoginPage(LoginPageViewModel viewModel)
    { 
        InitializeComponent();
        _viewModel = viewModel;
        BindingContext = _viewModel;
    }

    // 其他文本变更、返回按钮逻辑保持不变

    private async void OnLoginClicked(object sender, EventArgs e)
    {
        string loginUsername = uText.Trim();
        string loginPassword = pText.Trim();

        // 注意:OAuth/token接口通常使用POST方法,而非GET
        var request = new HttpRequestMessage(
            HttpMethod.Post, "token");
        var collection = new List<KeyValuePair<string, string>>();
        collection.Add(new("grant_type", "password"));
        collection.Add(new("username", loginUsername));
        collection.Add(new("password", loginPassword));
        var content = new FormUrlEncodedContent(collection);
        request.Content = content;
        
        // 直接使用注入的ViewModel,避免类型转换
        var response = await _viewModel.HttpService.SendAsync(request);
        
        await Task.Delay(3000);
        if (response.IsSuccessStatusCode)
        {
            var token = await response.Content.ReadFromJsonAsync<Token>();
    
            await SecureStorage.Default.SetAsync(
                "accessTokenKey", token.access_token);
       
            await Shell.Current.GoToAsync("///home");
        }
        else
        {
            await DisplayAlert("Error", response.StatusCode.ToString(), "Retry");
        }
    }

    private async void OnRegisterPageClicked(object sender, EventArgs e)
    {
        await Shell.Current.GoToAsync("///register");
    }
}

额外说明

直接实例化HttpClient能正常工作,是因为这种方式绕开了DI容器,不需要依赖注入提供实例,但不符合DI规范,也不利于后续的统一配置、拦截和测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:20:53