.NET Core 的版本是 3.1
遇到的问题是 Action 中 return View() 的时候报错
An unhandled exception occurred while processing the request.
InvalidOperationException: No service for type 'Microsoft.AspNetCore.Mvc.ViewFeatures.ITempDataDictionaryFactory' has been registered.Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
错误内容的字面意思是 ITempDataDictionaryFactory 这玩意没有注册。
解决方案一:
修改 Startup.cs 中的 ConfigureServices方法
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); }
解决方案二:
修改 Startup.cs 中的 ConfigureServices方法
public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); }
查看AspNetCore.Mvc 的源码
public static IMvcBuilder AddMvc(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } services.AddControllersWithViews(); return services.AddRazorPages(); }
AddMvc 方法中包含了 AddControllersWithViews
public static IMvcBuilder AddControllersWithViews(this IServiceCollection services) { if (services == null) { throw new ArgumentNullException(nameof(services)); } var builder = AddControllersWithViewsCore(services); return new MvcBuilder(builder.Services, builder.PartManager); }
跳转到 AddControllersWithViewsCore
private static IMvcCoreBuilder AddControllersWithViewsCore(IServiceCollection services) { var builder = AddControllersCore(services) .AddViews() .AddRazorViewEngine() .AddCacheTagHelper(); AddTagHelpersFrameworkParts(builder.PartManager); return builder; }
跳转到 AddViews
public static IMvcCoreBuilder AddViews(this IMvcCoreBuilder builder) { if (builder == null) { throw new ArgumentNullException(nameof(builder)); } builder.AddDataAnnotations(); AddViewComponentApplicationPartsProviders(builder.PartManager); AddViewServices(builder.Services); return builder; }
跳转到 AddViewServices
internal static void AddViewServices(IServiceCollection services) { services.AddDataProtection(); services.AddAntiforgery(); services.AddWebEncoders(); services.TryAddEnumerable( ServiceDescriptor.Transient<IConfigureOptions<MvcViewOptions>, MvcViewOptionsSetup>()); services.TryAddEnumerable( ServiceDescriptor.Transient<IConfigureOptions<MvcOptions>, TempDataMvcOptionsSetup>()); // // View Engine and related infrastructure // services.TryAddSingleton<ICompositeViewEngine, CompositeViewEngine>(); services.TryAddSingleton<IActionResultExecutor<ViewResult>, ViewResultExecutor>(); services.TryAddSingleton<IActionResultExecutor<PartialViewResult>, PartialViewResultExecutor>(); // Support for activating ViewDataDictionary services.TryAddEnumerable( ServiceDescriptor .Transient<IControllerPropertyActivator, ViewDataDictionaryControllerPropertyActivator>()); // // HTML Helper // services.TryAddTransient<IHtmlHelper, HtmlHelper>(); services.TryAddTransient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>)); services.TryAddSingleton<IHtmlGenerator, DefaultHtmlGenerator>(); services.TryAddSingleton<ModelExpressionProvider>(); // ModelExpressionProvider caches results. Ensure that it's re-used when the requested type is IModelExpressionProvider. services.TryAddSingleton<IModelExpressionProvider>(s => s.GetRequiredService<ModelExpressionProvider>()); services.TryAddSingleton<ValidationHtmlAttributeProvider, DefaultValidationHtmlAttributeProvider>(); services.TryAddSingleton<IJsonHelper, SystemTextJsonHelper>(); // Component services for Blazor server-side interop services.TryAddSingleton<ServerComponentSerializer>(); // // View Components // // These do caching so they should stay singleton services.TryAddSingleton<IViewComponentSelector, DefaultViewComponentSelector>(); services.TryAddSingleton<IViewComponentFactory, DefaultViewComponentFactory>(); services.TryAddSingleton<IViewComponentActivator, DefaultViewComponentActivator>(); services.TryAddSingleton< IViewComponentDescriptorCollectionProvider, DefaultViewComponentDescriptorCollectionProvider>(); services.TryAddSingleton<IActionResultExecutor<ViewComponentResult>, ViewComponentResultExecutor>(); services.TryAddSingleton<ViewComponentInvokerCache>(); services.TryAddTransient<IViewComponentDescriptorProvider, DefaultViewComponentDescriptorProvider>(); services.TryAddSingleton<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>(); services.TryAddTransient<IViewComponentHelper, DefaultViewComponentHelper>(); // // Temp Data // services.TryAddEnumerable( ServiceDescriptor.Transient<IApplicationModelProvider, TempDataApplicationModelProvider>()); services.TryAddEnumerable( ServiceDescriptor.Transient<IApplicationModelProvider, ViewDataAttributeApplicationModelProvider>()); services.TryAddSingleton<SaveTempDataFilter>(); // // Component rendering // services.TryAddScoped<IComponentRenderer, ComponentRenderer>(); services.TryAddScoped<StaticComponentRenderer>(); services.TryAddScoped<NavigationManager, HttpNavigationManager>(); services.TryAddScoped<IJSRuntime, UnsupportedJavaScriptRuntime>(); services.TryAddScoped<INavigationInterception, UnsupportedNavigationInterception>(); services.TryAddTransient<ControllerSaveTempDataPropertyFilter>(); // This does caching so it should stay singleton services.TryAddSingleton<ITempDataProvider, CookieTempDataProvider>(); services.TryAddSingleton<TempDataSerializer, DefaultTempDataSerializer>(); // // Antiforgery // services.TryAddSingleton<ValidateAntiforgeryTokenAuthorizationFilter>(); services.TryAddSingleton<AutoValidateAntiforgeryTokenAuthorizationFilter>(); // These are stateless so their lifetime isn't really important. services.TryAddSingleton<ITempDataDictionaryFactory, TempDataDictionaryFactory>(); services.TryAddSingleton(ArrayPool<ViewBufferValue>.Shared); services.TryAddScoped<IViewBufferScope, MemoryPoolViewBufferScope>(); }
找到了 services.TryAddSingleton<ITempDataDictionaryFactory, TempDataDictionaryFactory>();
这一段绑定的代码。