.NET MAUI 7依赖注入出现NullReferenceException问题求助
.NET MAUI 7依赖注入导致NullReferenceException的解决方法
问题根源
你遇到的NullReferenceException由两个核心问题导致:
- 未注册
HttpClient到DI容器:HttpService的构造函数依赖HttpClient,但你的MauiProgram中没有注册该服务,DI容器无法创建合法的HttpService实例。 - 错误使用
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
相关产品推荐
相关产品推荐

