在 ASP.NET 5 应用程序中使用 Service






3.63/5 (6投票s)
在 ASP.NET 5 应用程序中使用 Service
引言
我们知道在 ASP.NET 5 中,整个框架都被重写了。 ASP.NET 5 不依赖于旧的庞大的 System.Web.dll。 这意味着它不依赖于特定的托管环境。 现在 (ASP.NET 5) 框架变得非常精简和可插拔。 那么这意味着什么呢? 它的意思是,ASP.NET 5 中将只附带非常有限的功能,如果用户需要更多功能,他们可以轻松地插入框架。 默认情况下,MVC 框架不随 ASP.NET 5 一起提供,如果我们想使用 MVC,我们必须在 ASP.NET 5 上插入 MVC service。 这种机制非常简单,你只需要在 Startup.cs 和 project.json 文件中添加几行代码即可。 如果你打开任何脚手架 Startup.cs 文件,它将包含两个方法,分别是 ConfigureService
和 Configure
方法。
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); } public void Configure(IApplicationBuilder app) { app.UseMvc(); }
我们可以从 ConfigureService
和 Configure
函数中调用 AddMvc()
和 UseMvc()
扩展方法来在应用程序中钩住 MVC。 在本文中,我们将深入研究 AddMvc()
函数,并讨论 MvcServiceCollectionExtensions
类,该类包含 AddMvc()
和一些有用的方法,用于在 ASP.NET 5 应用程序中钩住和配置 MVC。
MvcServiceCollectionExtensions
类的位置在 Microsoft.Framework.DependencyInjection
命名空间中
namespace Microsoft.Framework.DependencyInjection { public static class MvcServiceCollectionExtensions { } }
并且该类包含以下方法。
其中 AddMvcServices()
和 ConfigureDefaultServices()
是内部且私有的。 如果你只是在 Visual Studio 中打开该类,那么默认情况下你可能看不到这些函数,但它对某些反汇编工具是可见的。 现在我们已经看到我们使用 AddMvc()
函数在 ASP.NET 应用程序中添加 MVC services,让我们检查一下 AddMvc()
函数的定义,看看当我们向 ASP.NET 应用程序添加 MVC 框架时到底发生了什么。 这是 AddMvc()
函数的定义。
public static IServiceCollection AddMvc(this [NotNull] IServiceCollection services) { ConfigureDefaultServices(services); AddMvcServices(services); return services; }
我们看到,在内部,AddMvc()
扩展方法调用了 ConfigureDefaultService()
和 AddMvcServices()
这两个内部和私有函数。 所以让我们检查一下这两个函数的定义。 这是 ConfigureDefaultServices()
函数的定义。
private static void ConfigureDefaultServices(IServiceCollection services) { OptionsServiceCollectionExtensions.AddOptions(services); DataProtectionServiceCollectionExtensions.AddDataProtection(services); RoutingServices.AddRouting(services); CorsServiceCollectionExtensions.AddCors(services); ServiceCollectionExtensions.AddAuthorization(services); EncoderServiceCollectionExtensions.AddWebEncoders(services); OptionsServiceCollectionExtensions.Configure<RouteOptions>(services, routeOptions => routeOptions.get_ConstraintMap().Add("exists", typeof(KnownRouteValueConstraint)), 0, ""); }
我们看到,在这个函数中,MVC 框架的一些默认服务,如路由、CORS、授权,都被添加到了应用程序中。 这些是使用有限功能的 MVC 应用程序启动和运行的最小服务。 然后它调用 AddServices()
函数来添加其他 MVC 功能。 它包含大量 MVC 功能。
internal static void AddMvcServices(IServiceCollection services) { ServiceCollectionExtensions.AddTransient<IConfigureOptions<MvcOptions>, MvcOptionsSetup>(services); ServiceCollectionExtensions.AddTransient<IConfigureOptions<RazorViewEngineOptions>, RazorViewEngineOptionsSetup>(services); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IAssemblyProvider, DefaultAssemblyProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<MvcMarkerService, MvcMarkerService>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ITypeActivatorCache, DefaultTypeActivatorCache>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped(typeof(IScopedInstance<>), typeof(ScopedInstance<>))); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IControllerTypeProvider, DefaultControllerTypeProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IControllerModelBuilder, DefaultControllerModelBuilder>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IActionModelBuilder, DefaultActionModelBuilder>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IControllerFactory, DefaultControllerFactory>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IControllerActivator, DefaultControllerActivator>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IActionInvokerFactory, ActionInvokerFactory>()); ServiceCollectionExtensions.AddTransient<IActionConstraintProvider, DefaultActionConstraintProvider>(services); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IActionSelectorDecisionTreeProvider, ActionSelectorDecisionTreeProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IActionSelector, DefaultActionSelector>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IControllerActionArgumentBinder, DefaultControllerActionArgumentBinder>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IObjectModelValidator>(serviceProvider => new DefaultObjectValidator(ServiceProviderExtensions.GetRequiredService<IOptions<MvcOptions>>(serviceProvider).get_Options().get_ValidationExcludeFilters(), ServiceProviderExtensions.GetRequiredService<IModelMetadataProvider>(serviceProvider)))); ServiceCollectionExtensions.AddTransient<IActionDescriptorProvider, ControllerActionDescriptorProvider>(services); ServiceCollectionExtensions.AddTransient<IActionInvokerProvider, ControllerActionInvokerProvider>(services); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IActionDescriptorsCollectionProvider, DefaultActionDescriptorsCollectionProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IGlobalFilterProvider, DefaultGlobalFilterProvider>()); ServiceCollectionExtensions.AddTransient<IFilterProvider, DefaultFilterProvider>(services); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<FormatFilter, FormatFilter>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<CorsAuthorizationFilter, CorsAuthorizationFilter>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IModelMetadataProvider, DefaultModelMetadataProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<ICompositeMetadataDetailsProvider>(serviceProvider => new DefaultCompositeMetadataDetailsProvider(ServiceProviderExtensions.GetRequiredService<IOptions<MvcOptions>>(serviceProvider).get_Options().get_ModelMetadataDetailsProviders()))); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<JsonOutputFormatter>(serviceProvider => new JsonOutputFormatter(ServiceProviderExtensions.GetRequiredService<IOptions<MvcOptions>>(serviceProvider).get_Options().get_SerializerSettings()))); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<ICompositeViewEngine, CompositeViewEngine>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IViewLocationCache, DefaultViewLocationCache>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ICodeTreeCache>(serviceProvider => new DefaultCodeTreeCache(ServiceProviderExtensions.GetRequiredService<IOptions<RazorViewEngineOptions>>(serviceProvider).get_Options().get_FileProvider()))); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IMvcRazorHost, MvcRazorHost>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ICompilerCache, CompilerCache>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ICompilationService, RoslynCompilationService>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IRazorCompilationService, RazorCompilationService>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<IViewStartProvider, ViewStartProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IRazorViewFactory, RazorViewFactory>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IRazorPageActivator, RazorPageActivator>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<IRazorPageFactory, VirtualPathRazorPageFactory>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IHtmlHelper, HtmlHelper>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>))); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IJsonHelper, JsonHelper>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<IUrlHelper, UrlHelper>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ITagHelperActivator, DefaultTagHelperActivator>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IMemoryCache, MemoryCache>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IHtmlGenerator, DefaultHtmlGenerator>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IViewComponentSelector, DefaultViewComponentSelector>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IViewComponentActivator, DefaultViewComponentActivator>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IViewComponentDescriptorCollectionProvider, DefaultViewComponentDescriptorCollectionProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IViewComponentDescriptorProvider, DefaultViewComponentDescriptorProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IViewComponentInvokerFactory, DefaultViewComponentInvokerFactory>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Transient<IViewComponentHelper, DefaultViewComponentHelper>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IClaimUidExtractor, DefaultClaimUidExtractor>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<AntiForgery, AntiForgery>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IAntiForgeryAdditionalDataProvider, DefaultAntiForgeryAdditionalDataProvider>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<IApiDescriptionGroupCollectionProvider, ApiDescriptionGroupCollectionProvider>()); ServiceCollectionExtensions.AddTransient<IApiDescriptionProvider, DefaultApiDescriptionProvider>(services); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Scoped<ITempDataDictionary, TempDataDictionary>()); ServiceCollectionExtensions.TryAdd(services, ServiceDescriptor.Singleton<ITempDataProvider, SessionStateTempDataProvider>()); }
然后它返回 IServiceCollection
的同一个实例。 所以现在很清楚的是,当我们调用 AddMvc()
函数时,所有与 MVC 相关的功能都会被添加到 ASP.NET 5 应用程序中。 现在可能出现的问题是,如果我们想更改任何 MVC 功能呢? MvcServiceCollectionExtensions
类包含 ConfigureMvc()
函数,我们可以在其中更改已添加到应用程序中的任何 MVC 功能。 在此示例中,我们将尝试在视图引擎中进行更改,并了解 ConfigureMvc()
函数的功能。 这是修改后的 ConfigureServices()
函数,我们在 ConfigureMvc()
部分中删除了默认的视图引擎。
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.ConfigureMvc(f => { f.ViewEngines.RemoveAt(0); }); }
这意味着在当前应用程序中没有视图引擎来处理视图。 现在让我们向某个控制器执行一个 HTTP 请求,我们将遇到以下错误。
我相信并验证了所有路由相关的东西、控制器和视图,而且都已经就位,错误是由于在 ConfigureMvc()
部分中删除了视图引擎。 现在,你只需要更改现有的行为,就可以在同一部分中注册自定义过滤器和服务。 以下是我们可以更改默认行为的几个属性。
结论
在本文中,我们学习了在 ASP.NET 5 应用程序中设置 MVC 和默认 MVC services。 这些设置和行为是纯粹面向需求和特定于应用程序的。 请记住,仅添加 MVC services 并不能在应用程序中启用 MVC,我们需要在 Configure()
中调用 UseMvc()
扩展方法。