public CustomCompilationService(ApplicationPartManager partManager, IOptions<RazorViewEngineOptions> optionsAccessor, IRazorViewEngineFileProviderAccessor fileProviderAccessor, ILoggerFactory loggerFactory) : base(partManager, optionsAccessor, fileProviderAccessor, loggerFactory) { }
public AssemblyNode ReadApplicationPart(ApplicationPartManager applicationPartManager) { var feature = new ControllerFeature(); applicationPartManager.PopulateFeature(feature); var converter = new Converter(); var controllerTypes = feature.Controllers.Select(c => c.AsType()); return ReadControllers(controllerTypes); }
/// <summary> /// Creates a new <see cref="DefaultViewComponentDescriptorProvider"/>. /// </summary> /// <param name="partManager">The <see cref="ApplicationPartManager"/>.</param> public DefaultViewComponentDescriptorProvider(ApplicationPartManager partManager) { if (partManager == null) { throw new ArgumentNullException(nameof(partManager)); } _partManager = partManager; }
public ExtensionLibraryService( ApplicationPartManager applicationPartManager, IOrchardFileSystem fileSystem, IAppDataFolder appDataFolder, ILogger<ExtensionLibraryService> logger) { _applicationPartManager = applicationPartManager; _fileSystem = fileSystem; _appDataFolder = appDataFolder; _probingFolderPath = _appDataFolder.MapPath(ProbingDirectoryName); _logger = logger; T = NullLocalizer.Instance; }
/// <summary> /// Initializes a new <see cref="MvcBuilder"/> instance. /// </summary> /// <param name="services">The <see cref="IServiceCollection" /> to add services to.</param> /// <param name="manager">The <see cref="ApplicationPartManager"/> of the application.</param> public MvcBuilder(IServiceCollection services, ApplicationPartManager manager) { if (services == null) { throw new ArgumentNullException(nameof(services)); } if (manager == null) { throw new ArgumentNullException(nameof(manager)); } Services = services; PartManager = manager; }
public void GetDescriptor_WithAttribute() { // Arrange var manager = new ApplicationPartManager(); manager.ApplicationParts.Add(new TestPart(typeof(AttributeViewComponent))); manager.FeatureProviders.Add(new ViewComponentFeatureProvider()); var feature = new ViewComponentFeature(); // Act manager.PopulateFeature(feature); // Assert Assert.Equal(new[] { typeof(AttributeViewComponent).GetTypeInfo() }, feature.ViewComponents.ToArray()); }
public void AddApplicationPart_AddsAnApplicationPart_ToTheListOfPartsOnTheBuilder() { // Arrange var manager = new ApplicationPartManager(); var builder = new MvcCoreBuilder(Mock.Of<IServiceCollection>(), manager); var assembly = typeof(MvcCoreBuilder).GetTypeInfo().Assembly; // Act var result = builder.AddApplicationPart(assembly); // Assert Assert.Same(result, builder); var part = Assert.Single(builder.PartManager.ApplicationParts); var assemblyPart = Assert.IsType<AssemblyPart>(part); Assert.Equal(assembly, assemblyPart.Assembly); }
public void AddControllerAsServices_MultipleCalls_RetainsPreviouslyAddedTypes() { // Arrange var services = new ServiceCollection(); var manager = new ApplicationPartManager(); manager.ApplicationParts.Add(new TestApplicationPart(typeof(ControllerOne), typeof(ControllerTwo))); manager.FeatureProviders.Add(new TestFeatureProvider()); var builder = new MvcBuilder(services, manager); builder.AddControllersAsServices(); // Act builder.AddControllersAsServices(); // Assert 2 var collection = services.ToList(); Assert.Equal(3, collection.Count); Assert.Single(collection, d => d.ServiceType.Equals(typeof(ControllerOne))); Assert.Single(collection, d => d.ServiceType.Equals(typeof(ControllerTwo))); }
public static void AddTagHelpersAsServices(ApplicationPartManager manager, IServiceCollection services) { if (manager == null) { throw new ArgumentNullException(nameof(manager)); } if (services == null) { throw new ArgumentNullException(nameof(services)); } var feature = new TagHelperFeature(); manager.PopulateFeature(feature); foreach (var type in feature.TagHelpers.Select(t => t.AsType())) { services.TryAddTransient(type, type); } services.Replace(ServiceDescriptor.Transient<ITagHelperActivator, ServiceBasedTagHelperActivator>()); services.Replace(ServiceDescriptor.Transient<ITagHelperTypeResolver, FeatureTagHelperTypeResolver>()); }
public ControllerActionDescriptorProvider( ApplicationPartManager partManager, IEnumerable<IApplicationModelProvider> applicationModelProviders, IOptions<MvcOptions> optionsAccessor) { if (partManager == null) { throw new ArgumentNullException(nameof(partManager)); } if (applicationModelProviders == null) { throw new ArgumentNullException(nameof(applicationModelProviders)); } if (optionsAccessor == null) { throw new ArgumentNullException(nameof(optionsAccessor)); } _partManager = partManager; _applicationModelProviders = applicationModelProviders.OrderBy(p => p.Order).ToArray(); _conventions = optionsAccessor.Value.Conventions; }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IFolkeConnection connection, RoleManager <Role> roleManager, UserManager <User> userManager, ApplicationPartManager applicationPartManager) { // Default admin credentials must be specified here because they interact with ASP.NET Identity app.UseFolkeCore(connection, env, roleManager, userManager, applicationPartManager, options => { options.AdministratorEmail = Configuration["Data:DefaultAdministratorUserName"]; options.AdministratorPassword = Configuration["Data:DefaultAdministratorPassword"]; }); // Elm updates database schema connection.UpdateSchema(typeof(Adjective).GetTypeInfo().Assembly); loggerFactory.AddConsole(Configuration.GetSection("Logging")); loggerFactory.AddDebug(); app.UseMvc(); if (env.IsDevelopment()) { CreateTypeScriptServices(applicationPartManager); } }
private void AddModularFrameworkParts(IServiceProvider services, ApplicationPartManager manager) { var httpContextAccessor = services.GetRequiredService <IHttpContextAccessor>(); manager.ApplicationParts.Add(new ShellFeatureApplicationPart(httpContextAccessor)); }
/// <summary> /// Initializes a new instance of the WebApiAssembliesResolver class. /// </summary> /// <param name="applicationPartManager">The inner manager.</param> public WebApiAssembliesResolver(ApplicationPartManager applicationPartManager) { this.innerManager = applicationPartManager; }
/// <summary> /// Initialize /// </summary> /// <param name="applicationPartManager">Application part manager</param> /// <param name="config">Config</param> public static void Initialize(ApplicationPartManager applicationPartManager) { if (applicationPartManager == null) { throw new ArgumentNullException(nameof(applicationPartManager)); } using (new WriteLockDisposable(Locker)) { var pluginFolder = _fileProvider.MapPath(PluginDefaults.Path); _shadowCopyFolder = _fileProvider.MapPath(PluginDefaults.ShadowCopyPath); var referencedPlugins = new List <PluginInfoParser>(); var incompatiblePlugins = new List <string>(); try { var installedPluginSystemNames = GetInstalledPluginNames(_fileProvider.MapPath(PluginDefaults.InstalledPluginsFilePath)); _fileProvider.CreateDirectory(pluginFolder); _fileProvider.CreateDirectory(_shadowCopyFolder); var binFiles = _fileProvider.GetFiles(_shadowCopyFolder, "*", false); //remove all old files in altrnative bin folder foreach (var f in binFiles) { try { var fileName = _fileProvider.GetFileName(f); _fileProvider.DeleteFile(f); } catch (Exception exc) { Debug.WriteLine("Error deleting file " + f + ". Exception: " + exc); } } //load info files foreach (var dfd in GetDescriptionFilesAndDescriptors(pluginFolder)) { var descriptionFile = dfd.Key; var pluginDescriptor = dfd.Value; //some validation if (string.IsNullOrWhiteSpace(pluginDescriptor.Name)) { throw new Exception($"A plugin '{descriptionFile}' has no system name. Try assigning the plugin a unique name and recompiling."); } if (referencedPlugins.Contains(pluginDescriptor)) { throw new Exception($"A plugin with '{pluginDescriptor.Name}' system name is already defined"); } //set 'Installed' property pluginDescriptor.IsInstalled = installedPluginSystemNames .FirstOrDefault(x => x.Equals(pluginDescriptor.Name, StringComparison.InvariantCultureIgnoreCase)) != null; try { var directoryName = _fileProvider.GetDirectoryName(descriptionFile); if (string.IsNullOrEmpty(directoryName)) { throw new Exception($"Directory cannot be resolved for '{_fileProvider.GetFileName(descriptionFile)}' description file"); } //get list of all DLLs in plugins (not in bin!) var pluginFiles = _fileProvider.GetFiles(directoryName, "*.dll", false) .Where(x => !binFiles.Select(q => q).Contains(x)) .ToList(); //other plugin description info var mainPluginFile = pluginFiles .FirstOrDefault(x => _fileProvider.GetFileName(x).Equals(pluginDescriptor.AssemblyFileName, StringComparison.InvariantCultureIgnoreCase)); //plugin have wrong directory if (mainPluginFile == null) { incompatiblePlugins.Add(pluginDescriptor.Name); continue; } pluginDescriptor.AssemblyFileName = mainPluginFile; //shadow copy main plugin file pluginDescriptor.RefrancedPlugin = PerformFileDeploy(mainPluginFile, applicationPartManager); //load all other referenced assemblies now foreach (var plugin in pluginFiles .Where(x => !_fileProvider.GetFileName(x).Equals(_fileProvider.GetFileName(mainPluginFile), StringComparison.InvariantCultureIgnoreCase)) .Where(x => !IsAlreadyLoaded(x))) { PerformFileDeploy(plugin, applicationPartManager); } //init plugin type (only one plugin per assembly is allowed) foreach (var t in pluginDescriptor.RefrancedPlugin.GetTypes()) { if (typeof(IPlugin).IsAssignableFrom(t)) { if (!t.IsInterface) { if (t.IsClass && !t.IsAbstract) { pluginDescriptor.Plugin = t; break; } } } } referencedPlugins.Add(pluginDescriptor); } catch (ReflectionTypeLoadException ex) { //add a plugin name. this way we can easily identify a problematic plugin var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. "; foreach (var e in ex.LoaderExceptions) { msg += e.Message + Environment.NewLine; } var fail = new Exception(msg, ex); throw fail; } catch (Exception ex) { //add a plugin name. this way we can easily identify a problematic plugin var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. {ex.Message}"; var fail = new Exception(msg, ex); throw fail; } } } catch (Exception ex) { var msg = string.Empty; for (var e = ex; e != null; e = e.InnerException) { msg += e.Message + Environment.NewLine; } var fail = new Exception(msg, ex); throw fail; } ReferencedPlugins = referencedPlugins; IncompatiblePlugins = incompatiblePlugins; } }
public HealthController(ApplicationPartManager applicationPartManager) { _applicationPartManager = applicationPartManager; }
private static void AddDefaultFrameworkParts(ApplicationPartManager partManager) { var mvcTagHelpersAssembly = typeof(InputTagHelper).GetTypeInfo().Assembly; if(!partManager.ApplicationParts.OfType<AssemblyPart>().Any(p => p.Assembly == mvcTagHelpersAssembly)) { partManager.ApplicationParts.Add(new AssemblyPart(mvcTagHelpersAssembly)); } var mvcRazorAssembly = typeof(UrlResolutionTagHelper).GetTypeInfo().Assembly; if(!partManager.ApplicationParts.OfType<AssemblyPart>().Any(p => p.Assembly == mvcRazorAssembly)) { partManager.ApplicationParts.Add(new AssemblyPart(mvcRazorAssembly)); } }
public LiquidTagHelperFactory(ApplicationPartManager partManager, ITagHelperFactory factory) { _partManager = partManager; _factory = factory; }
static void AddModelConfigurationsAsServices(this IServiceCollection services, ApplicationPartManager partManager) { var feature = new ModelConfigurationFeature(); var modelConfigurationType = typeof(IModelConfiguration); partManager.PopulateFeature(feature); foreach (var modelConfiguration in feature.ModelConfigurations.Select(t => t.AsType())) { services.TryAddEnumerable(Transient(modelConfigurationType, modelConfiguration)); } }
public void PopulateFeature(IEnumerable <ApplicationPart> parts, ViewsFeature feature) { // The scope is null when this code is called through a 'ChangeToken' callback, e.g to recompile razor pages. // So, here we resolve and cache tenant level singletons, application singletons can be resolved in the ctor. if (_services != null && _featureProviders == null) { lock (this) { if (_featureProviders == null) { _applicationPartManager = _services.GetRequiredService <ApplicationPartManager>(); _featureProviders = _services.GetServices <IApplicationFeatureProvider <ViewsFeature> >(); } } } // Module compiled views are not served while in dev. if (!_hostingEnvironment.IsDevelopment()) { // Retrieve mvc views feature providers but not this one. var mvcFeatureProviders = _applicationPartManager.FeatureProviders .OfType <IApplicationFeatureProvider <ViewsFeature> >() .Where(p => p.GetType() != typeof(ModuleViewFeatureProvider)); var moduleFeature = new ViewsFeature(); var modules = _moduleManager.LoadModulesAsync().Result; foreach (var module in modules) { var precompiledAssemblyPath = Path.Combine(Path.GetDirectoryName(module.Assembly.Location), module.Assembly.GetName().Name + ".Views.dll"); if (File.Exists(precompiledAssemblyPath)) { try { var assembly = Assembly.LoadFile(precompiledAssemblyPath); var applicationPart = new ApplicationPart[] { new CompiledRazorAssemblyPart(assembly) }; foreach (var provider in mvcFeatureProviders) { provider.PopulateFeature(applicationPart, moduleFeature); } // Razor views are precompiled in the context of their modules, but at runtime // their paths need to be relative to the application root. foreach (var descriptor in moduleFeature.ViewDescriptors) { descriptor.RelativePath = _moduleRoot + module.Descriptor.Id + descriptor.RelativePath; feature.ViewDescriptors.Add(descriptor); } moduleFeature.ViewDescriptors.Clear(); } catch (FileLoadException) { // Don't throw if assembly cannot be loaded. // This can happen if the file is not a managed assembly. } } } } // Apply views feature providers registered at the tenant level. foreach (var provider in _featureProviders) { provider.PopulateFeature(parts, feature); } }
public FeaturesController(ApplicationPartManager partManager) { _partManager = partManager; }
protected override IEnumerable <CompiledViewDescriptor> GetViewDescriptors(ApplicationPartManager applicationManager) => _descriptors;
/// <summary> /// Autofac属性注入 /// 接口项目以.Contracts结尾,实现接口项目以.Service结尾 /// 调用此方法不需要继承也不需要配置,即可属性注入调用 /// </summary> /// <param name="services"></param> /// <returns></returns> public static IServiceProvider RegisterAutofac(IServiceCollection services, EnumAutoInject autoInject = EnumAutoInject.指定接口与实现程序集) { //说明:ConfigureServices返回IServiceProvider,通过接口属性来获取,自动获取Controller的属性 services.Replace(ServiceDescriptor.Transient <IControllerActivator, ServiceBasedControllerActivator>()); var assembly = Assembly.GetEntryAssembly(); var manager = new ApplicationPartManager(); manager.ApplicationParts.Add(new AssemblyPart(assembly)); manager.FeatureProviders.Add(new ControllerFeatureProvider()); var feature = new ControllerFeature(); manager.PopulateFeature(feature); var builder = new ContainerBuilder(); builder.RegisterType <ApplicationPartManager>().AsSelf().SingleInstance(); builder.RegisterTypes(feature.Controllers.Select(ti => ti.AsType()).ToArray()).PropertiesAutowired(); builder.Populate(services);//将services中的服务填充到Autofac中 if (autoInject == EnumAutoInject.指定接口与实现程序集) { #region 指定接口与实现程序集 string serviceName = AppDomain.CurrentDomain.FriendlyName.Replace(".Api", "").Replace("Api", "").Replace(".API", "").Replace("API", ""); Console.WriteLine($"RegisterAutofac:serviceName={serviceName}"); string iserviceName = serviceName; if (serviceName.EndsWith('.')) { iserviceName += "Contracts"; serviceName += "Service"; } else { iserviceName += ".Contracts"; serviceName += ".Service"; } Assembly iservice = Assembly.Load(iserviceName); Assembly service = Assembly.Load(serviceName); builder.RegisterAssemblyTypes(iservice, service) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces() .InstancePerLifetimeScope(); return(new AutofacServiceProvider(builder.Build())); #endregion } else if (autoInject == EnumAutoInject.指定IAutoInject与实现程序集) { #region 指定IAutoInject与实现程序集 string serviceName = AppDomain.CurrentDomain.FriendlyName.Replace(".Api", "").Replace("Api", "").Replace(".API", "").Replace("API", ""); Console.WriteLine($"RegisterAutofac:serviceName={serviceName}"); if (serviceName.EndsWith('.')) { serviceName += "Service"; } else { serviceName += ".Service"; } var assemblys = Assembly.Load(serviceName); //Service是继承接口的实现方法类库名称 var baseType = typeof(IAutoInject); //IDependency 是一个接口(所有要实现依赖注入的接口都要继承该接口) builder.RegisterAssemblyTypes(assemblys) .Where(m => baseType.IsAssignableFrom(m) && m != baseType) .AsImplementedInterfaces() .InstancePerLifetimeScope(); return(new AutofacServiceProvider(builder.Build())); #endregion } else { #region 自动加载接口与实现 var assemblys = AppDomain.CurrentDomain.GetAssemblies().ToArray(); //var assemblys = AppDomain.CurrentDomain.GetAssemblies().Where(q => q.FullName.Contains(".Service")).FirstOrDefault(); builder.RegisterAssemblyTypes(assemblys) .Where(t => t.Name.EndsWith("Service")) .AsImplementedInterfaces() .InstancePerLifetimeScope(); return(new AutofacServiceProvider(builder.Build())); #endregion } }
/// <summary> /// Initialize /// </summary> /// <param name="applicationPartManager">Application part manager</param> /// <param name="config">Config</param> public static void Initialize(ApplicationPartManager applicationPartManager, NopConfig config) { if (applicationPartManager == null) { throw new ArgumentNullException(nameof(applicationPartManager)); } if (config == null) { throw new ArgumentNullException(nameof(config)); } using (new WriteLockDisposable(Locker)) { // TODO: Add verbose exception handling / raising here since this is happening on app startup and could // prevent app from starting altogether var pluginFolder = _fileProvider.MapPath(NopPluginDefaults.Path); _shadowCopyFolder = _fileProvider.MapPath(NopPluginDefaults.ShadowCopyPath); _reserveShadowCopyFolder = _fileProvider.Combine(_fileProvider.MapPath(NopPluginDefaults.ShadowCopyPath), $"{NopPluginDefaults.ReserveShadowCopyPathName}{DateTime.Now.ToFileTimeUtc()}"); var referencedPlugins = new List <PluginDescriptor>(); var incompatiblePlugins = new List <string>(); try { var installedPluginSystemNames = GetInstalledPluginNames(_fileProvider.MapPath(NopPluginDefaults.InstalledPluginsFilePath)); Debug.WriteLine("Creating shadow copy folder and querying for DLLs"); //ensure folders are created _fileProvider.CreateDirectory(pluginFolder); _fileProvider.CreateDirectory(_shadowCopyFolder); //get list of all files in bin var binFiles = _fileProvider.GetFiles(_shadowCopyFolder, "*", false); if (config.ClearPluginShadowDirectoryOnStartup) { //clear out shadow copied plugins foreach (var f in binFiles) { if (_fileProvider.GetFileName(f).Equals("placeholder.txt", StringComparison.InvariantCultureIgnoreCase)) { continue; } Debug.WriteLine("Deleting " + f); try { //ignore index.htm var fileName = _fileProvider.GetFileName(f); if (fileName.Equals("index.htm", StringComparison.InvariantCultureIgnoreCase)) { continue; } _fileProvider.DeleteFile(f); } catch (Exception exc) { Debug.WriteLine("Error deleting file " + f + ". Exception: " + exc); } } //delete all reserve folders foreach (var directory in _fileProvider.GetDirectories(_shadowCopyFolder, NopPluginDefaults.ReserveShadowCopyPathNamePattern)) { try { _fileProvider.DeleteDirectory(directory); } catch { //do nothing } } } //load description files foreach (var dfd in GetDescriptionFilesAndDescriptors(pluginFolder)) { var descriptionFile = dfd.Key; var pluginDescriptor = dfd.Value; //ensure that version of plugin is valid if (!pluginDescriptor.SupportedVersions.Contains(NopVersion.CurrentVersion, StringComparer.InvariantCultureIgnoreCase)) { incompatiblePlugins.Add(pluginDescriptor.SystemName); continue; } //some validation if (string.IsNullOrWhiteSpace(pluginDescriptor.SystemName)) { throw new Exception($"A plugin '{descriptionFile}' has no system name. Try assigning the plugin a unique name and recompiling."); } if (referencedPlugins.Contains(pluginDescriptor)) { throw new Exception($"A plugin with '{pluginDescriptor.SystemName}' system name is already defined"); } //set 'Installed' property pluginDescriptor.Installed = installedPluginSystemNames .FirstOrDefault(x => x.Equals(pluginDescriptor.SystemName, StringComparison.InvariantCultureIgnoreCase)) != null; try { var directoryName = _fileProvider.GetDirectoryName(descriptionFile); if (string.IsNullOrEmpty(directoryName)) { throw new Exception($"Directory cannot be resolved for '{_fileProvider.GetFileName(descriptionFile)}' description file"); } //get list of all DLLs in plugins (not in bin!) var pluginFiles = _fileProvider.GetFiles(directoryName, "*.dll", false) //just make sure we're not registering shadow copied plugins .Where(x => !binFiles.Select(q => q).Contains(x)) .Where(x => IsPackagePluginFolder(_fileProvider.GetDirectoryName(x))) .ToList(); //other plugin description info var mainPluginFile = pluginFiles .FirstOrDefault(x => _fileProvider.GetFileName(x).Equals(pluginDescriptor.AssemblyFileName, StringComparison.InvariantCultureIgnoreCase)); //plugin have wrong directory if (mainPluginFile == null) { incompatiblePlugins.Add(pluginDescriptor.SystemName); continue; } pluginDescriptor.OriginalAssemblyFile = mainPluginFile; //shadow copy main plugin file pluginDescriptor.ReferencedAssembly = PerformFileDeploy(mainPluginFile, applicationPartManager, config); //load all other referenced assemblies now foreach (var plugin in pluginFiles .Where(x => !_fileProvider.GetFileName(x).Equals(_fileProvider.GetFileName(mainPluginFile), StringComparison.InvariantCultureIgnoreCase)) .Where(x => !IsAlreadyLoaded(x))) { PerformFileDeploy(plugin, applicationPartManager, config); } //init plugin type (only one plugin per assembly is allowed) foreach (var t in pluginDescriptor.ReferencedAssembly.GetTypes()) { if (typeof(IPlugin).IsAssignableFrom(t)) { if (!t.IsInterface) { if (t.IsClass && !t.IsAbstract) { pluginDescriptor.PluginType = t; break; } } } } referencedPlugins.Add(pluginDescriptor); } catch (ReflectionTypeLoadException ex) { //add a plugin name. this way we can easily identify a problematic plugin var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. "; foreach (var e in ex.LoaderExceptions) { msg += e.Message + Environment.NewLine; } var fail = new Exception(msg, ex); throw fail; } catch (Exception ex) { //add a plugin name. this way we can easily identify a problematic plugin var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. {ex.Message}"; var fail = new Exception(msg, ex); throw fail; } } } catch (Exception ex) { var msg = string.Empty; for (var e = ex; e != null; e = e.InnerException) { msg += e.Message + Environment.NewLine; } var fail = new Exception(msg, ex); throw fail; } ReferencedPlugins = referencedPlugins; IncompatiblePlugins = incompatiblePlugins; } }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { var conn = Configuration.GetConnectionString("DefaultConnection"); var userStore = new UserStore(conn); var roleStore = new RoleStore(conn); var manager = new ApplicationPartManager(); manager.ApplicationParts.Add(new AssemblyPart(typeof(Startup).Assembly)); services.AddSingleton(manager); services.AddSingleton <IUserStore <ApplicationUser> >(userStore); services.AddSingleton <IRoleStore <ApplicationRole> >(roleStore); services.AddMvcCore(); // Add framework services. services.AddDbContext <ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddDbContext <MardisContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); var sessionTimeOut = Configuration.GetValue <int>("SessionTimeOut"); services.AddIdentity <ApplicationUser, ApplicationRole>(config => { config.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromMinutes(sessionTimeOut); config.Lockout = new LockoutOptions() { DefaultLockoutTimeSpan = TimeSpan.FromHours(2) }; }) .AddEntityFrameworkStores <ApplicationDbContext>() .AddDefaultTokenProviders(); services.Configure <IdentityOptions>(options => { // Password settings options.Password.RequireDigit = true; options.Password.RequiredLength = 8; options.Password.RequireNonAlphanumeric = false; options.Password.RequireUppercase = true; options.Password.RequireLowercase = false; //options.SecurityStampValidationInterval = new TimeSpan(1, 12, 23, 62); options.SecurityStampValidationInterval = TimeSpan.FromMinutes(sessionTimeOut); // Cookie settings options.Cookies.ApplicationCookie.LoginPath = "/Account/Login"; options.Cookies.ApplicationCookie.LogoutPath = "/Account/Login"; // User settings options.User.RequireUniqueEmail = true; //services.AddCors(); }); services.Configure <FormOptions>(x => x.ValueCountLimit = 8192); services.AddDataProtection() .SetApplicationName("M@rdisEngin3") .SetDefaultKeyLifetime(TimeSpan.FromDays(14)); services.AddCors(o => o.AddPolicy("MPT", builder => { builder.AllowAnyOrigin() .AllowAnyMethod() .AllowAnyHeader(); })); // Add framework services. services.AddMvc() .AddJsonOptions(options => { options.SerializerSettings.ContractResolver = new DefaultContractResolver(); options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; } ); services.Configure <MvcOptions>(options => { options.Filters.Add(new CorsAuthorizationFilterFactory("MPT")); }); services.AddDistributedMemoryCache(); services.AddMemoryCache(); services.AddSession(options => { // Set a short timeout for easy testing. }); services.AddSingleton <RedisCache, RedisCache>(); //Add context to controllers services.AddDbContext <MardisContext>(opc => opc.UseSqlServer(conn)); services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>(); // Add application services. services.AddTransient <IEmailSender, AuthMessageSender>(); services.AddTransient <ISmsSender, AuthMessageSender>(); services.AddScoped <IMenuService, MenuService>(); //.WithOrigins("https://localhost:44306"))); }
protected virtual void OnConfigurePartManager(ApplicationPartManager partManager) => partManager.ApplicationParts.Add(new TestApplicationPart(FilteredControllerTypes));
public ODataActionDescriptorProvider(IODataRouteCollectionProvider routeCollectionProvider, ApplicationPartManager partManager) { Contract.Requires(routeCollectionProvider != null); Contract.Requires(partManager != null); this.routeCollectionProvider = routeCollectionProvider; this.partManager = partManager; }
public PluginControllerManager(ApplicationPartManager applicationPartManager) { _applicationPartManager = applicationPartManager; }
private static ApplicationPartManager GetApplicationPartManager(params TypeInfo[] types) { var manager = new ApplicationPartManager(); manager.ApplicationParts.Add(new TestApplicationPart(types)); manager.FeatureProviders.Add(new ControllerFeatureProvider()); return manager; }
/// <summary> /// Initialize the module manager /// </summary> /// <param name="applicationPartManager"></param> public static void Initialize(ApplicationPartManager applicationPartManager) { if (applicationPartManager == null) { throw new ArgumentNullException(nameof(applicationPartManager)); } using (new WriteLockDisposable(_locker)) { var loadedModules = new List <ModuleInfo>(); var fileProvider = IocContainer.Current.Resolve <ICustomFileProvider>(); //gets the module folder info fileProvider.CreateDirectory(fileProvider.MapPath(ModulesPath));//create if not exist var moduleFolder = new DirectoryInfo(fileProvider.MapPath(ModulesPath)); //gets the module.json files var moduleInfoFiles = moduleFolder.GetFiles(ModuleInfoFileName, SearchOption.AllDirectories).ToList(); //gets the installed module system names var installedModules = GetInstalledFile(fileProvider.MapPath(InstalledModuleFilePath)); foreach (var moduleInfoFile in moduleInfoFiles) { //deserialize module information file to ModuleInfo object var moduleInfo = JsonConvert.DeserializeObject <ModuleInfo>(File.ReadAllText(moduleInfoFile.FullName)); //gets the module dll files var moduleBinaryFiles = moduleInfoFile.Directory.GetFiles("*.dll", SearchOption.AllDirectories); //gets the main binary file var mainModuleFile = moduleBinaryFiles.FirstOrDefault(x => x.Name.Equals(moduleInfo.AssemblyFileName, StringComparison.InvariantCultureIgnoreCase)); //set the installed moduleInfo.Installed = installedModules.Any(x => x.Equals(moduleInfo.SystemName, StringComparison.InvariantCultureIgnoreCase)); //set the module assembly moduleInfo.Assembly = DeployModule(applicationPartManager, mainModuleFile); moduleInfo.AssemblyFileInfo = mainModuleFile; //exclude the main module in module binary files var readyToDeployModules = moduleBinaryFiles .Where(m => !m.Name.Equals(mainModuleFile.Name, StringComparison.InvariantCultureIgnoreCase)); //deploy the module files foreach (var moduleFileInfo in readyToDeployModules) { DeployModule(applicationPartManager, moduleFileInfo); } var type = moduleInfo.Assembly.GetTypes().FirstOrDefault(t => typeof(IModule).IsAssignableFrom(t)); if (!type.IsInterface && !type.IsAbstract && type.IsClass) { moduleInfo.ModuleType = type; } loadedModules.Add(moduleInfo); } LoadedModules = loadedModules; } }
private static void AddViewComponentApplicationPartsProviders(ApplicationPartManager manager) { if (!manager.FeatureProviders.OfType<ViewComponentFeatureProvider>().Any()) { manager.FeatureProviders.Add(new ViewComponentFeatureProvider()); } }
public MvcHelper(ApplicationPartManager partManager) { _partManager = partManager; }
internal static void AddModularFrameworkParts(IServiceProvider services, ApplicationPartManager manager) { manager.ApplicationParts.Insert(0, new ShellFeatureApplicationPart()); manager.FeatureProviders.Add(new ShellViewFeatureProvider(services)); }
public static IServiceCollection AddPlatoModularAppParts(this IServiceCollection services, ApplicationPartManager partManager) { var serviceProvider = services.BuildServiceProvider(); partManager.ApplicationParts.Insert(0, new ModularFeatureApplicationPart(serviceProvider)); partManager.FeatureProviders.Add(new ModuleViewFeatureProvider(serviceProvider)); return(services); }
/// <summary> /// Initializes a new instance of the WebApiAssembliesResolver class. /// </summary> public WebApiAssembliesResolver() { this.innerManager = null; }
public async Task SendAsync_CorrectlyCopiesHeadersToIndividualRequests( IEnumerable <string> batchPreferHeaderValues, string getRequest, string deleteRequest, string postRequest) { var batchRef = $"batch_{Guid.NewGuid()}"; var changesetRef = $"changeset_{Guid.NewGuid()}"; var endpoint = "http://localhost/odata"; var acceptJsonFullMetadata = "application/json;odata.metadata=minimal"; var postPayload = "Bar"; Type[] controllers = new[] { typeof(BatchTestHeadersCustomersController) }; var builder = new WebHostBuilder() .ConfigureServices(services => { var builder = new ODataConventionModelBuilder(); builder.EntitySet <BatchTestHeadersCustomer>("BatchTestHeadersCustomers"); IEdmModel model = builder.GetEdmModel(); services.AddOData(opt => opt.AddModel("odata", model, new DefaultODataBatchHandler()).Expand()); }) .Configure(app => { ApplicationPartManager applicationPartManager = app.ApplicationServices.GetRequiredService <ApplicationPartManager>(); applicationPartManager.ApplicationParts.Clear(); if (controllers != null) { AssemblyPart part = new AssemblyPart(new MockAssembly(controllers)); applicationPartManager.ApplicationParts.Add(part); } app.UseODataBatching(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }); var server = new TestServer(builder); var client = server.CreateClient(); var batchRequest = new HttpRequestMessage(HttpMethod.Post, $"{endpoint}/$batch"); batchRequest.Headers.Accept.Add(MediaTypeWithQualityHeaderValue.Parse("multipart/mixed")); batchRequest.Headers.Add("Prefer", batchPreferHeaderValues); var batchContent = $@" --{batchRef} Content-Type: application/http Content-Transfer-Encoding: binary GET {endpoint}/BatchTestHeadersCustomers HTTP/1.1 OData-Version: 4.0 OData-MaxVersion: 4.0 Accept: application/json;odata.metadata=minimal Accept-Charset: UTF-8 --{batchRef} Content-Type: application/http Content-Transfer-Encoding: binary DELETE {endpoint}/BatchTestHeadersCustomers(1) HTTP/1.1 OData-Version: 4.0 OData-MaxVersion: 4.0 Accept: application/json;odata.metadata=minimal Accept-Charset: UTF-8 Prefer: wait=100,handling=lenient --{batchRef} Content-Type: application/http Content-Transfer-Encoding: binary POST {endpoint}/BatchTestHeadersCustomers HTTP/1.1 OData-Version: 4.0;NetFx OData-MaxVersion: 4.0;NetFx Content-Type: text/plain; charset=utf-8 Content-Length: {postPayload.Length} Accept: {acceptJsonFullMetadata} Accept-Charset: UTF-8 {postPayload} --{batchRef}-- "; var httpContent = new StringContent(batchContent); httpContent.Headers.ContentType = MediaTypeHeaderValue.Parse($"multipart/mixed; boundary={batchRef}"); httpContent.Headers.ContentLength = batchContent.Length; batchRequest.Content = httpContent; var response = await client.SendAsync(batchRequest); ExceptionAssert.DoesNotThrow(() => response.EnsureSuccessStatusCode()); var responseContent = await response.Content.ReadAsStringAsync(); Assert.Contains(getRequest, responseContent); Assert.Contains(deleteRequest, responseContent); Assert.Contains(postRequest, responseContent); }
/// <summary> /// 初始化 /// </summary> /// <param name="applicationPartManager">Application part manager</param> public static void Initialize(ApplicationPartManager applicationPartManager) { if (applicationPartManager == null) { throw new ArgumentNullException(nameof(applicationPartManager)); } using (new WriteLockDisposable(Locker)) { // TODO: 在此添加详细的异常处理/引发,因为这是在应用程序启动时发生的,可能会阻止应用程序完全启动。 var pluginFolder = _fileProvider.MapPath(NGPPluginDefaults.Path); _shadowCopyFolder = _fileProvider.MapPath(NGPPluginDefaults.ShadowCopyPath); _reserveShadowCopyFolder = _fileProvider.Combine(_fileProvider.MapPath(NGPPluginDefaults.ShadowCopyPath), $"{NGPPluginDefaults.ReserveShadowCopyPathName}{DateTime.Now.ToFileTimeUtc()}"); var referencedPlugins = new List <PluginDescriptor>(); try { var installedPluginSystemNames = _fileProvider.GetFileContent <List <string> >( _fileProvider.MapPath(NGPPluginDefaults.InstalledPluginsFilePath)); // 确保创建文件夹 _fileProvider.CreateDirectory(pluginFolder); _fileProvider.CreateDirectory(_shadowCopyFolder); // 获取bin中所有文件的列表 var binFiles = _fileProvider.GetFiles(_shadowCopyFolder, "*", false); foreach (var f in binFiles) { if (_fileProvider.GetFileName(f).Equals("placeholder.txt", StringComparison.InvariantCultureIgnoreCase)) { continue; } try { //ignore index.htm var fileName = _fileProvider.GetFileName(f); _fileProvider.DeleteFile(f); } catch { // TODO:书写异常 } } // 删除所有保留文件夹 foreach (var directory in _fileProvider.GetDirectories(_shadowCopyFolder, NGPPluginDefaults.ReserveShadowCopyPathNamePattern)) { try { _fileProvider.DeleteDirectory(directory); } catch { // TODO:书写异常 } } // 加载描述文件 foreach (var dfd in GetDescriptionFilesAndDescriptors(pluginFolder)) { var descriptionFile = dfd.Key; var pluginDescriptor = dfd.Value; // 一些验证 if (string.IsNullOrWhiteSpace(pluginDescriptor.SystemName)) { throw new Exception($"A plugin '{descriptionFile}' has no system name. Try assigning the plugin a unique name and recompiling."); } if (referencedPlugins.Contains(pluginDescriptor)) { throw new Exception($"A plugin with '{pluginDescriptor.SystemName}' system name is already defined"); } // 设定是否加载属性 pluginDescriptor.Installed = installedPluginSystemNames .FirstOrDefault(x => x.Equals(pluginDescriptor.SystemName, StringComparison.InvariantCultureIgnoreCase)) != null; try { var directoryName = _fileProvider.GetDirectoryName(descriptionFile); if (string.IsNullOrEmpty(directoryName)) { throw new Exception($"Directory cannot be resolved for '{_fileProvider.GetFileName(descriptionFile)}' description file"); } // 获取插件中所有DLL的列表(不在bin中!) var pluginFiles = _fileProvider.GetFiles(directoryName, "*.dll", false) .Where(x => !binFiles.Select(q => q).Contains(x)) .Where(x => IsPackagePluginFolder(_fileProvider.GetDirectoryName(x))) .ToList(); // 其他插件的描述信息 var mainPluginFile = pluginFiles .FirstOrDefault(x => _fileProvider.GetFileName(x).Equals(pluginDescriptor.AssemblyFileName, StringComparison.InvariantCultureIgnoreCase)); // 插件目录错误 if (mainPluginFile == null) { continue; } pluginDescriptor.OriginalAssemblyFile = mainPluginFile; // 实际加载程序集 pluginDescriptor.ReferencedAssembly = PerformFileDeploy(mainPluginFile, applicationPartManager); // 加载所有其他引用的程序集 foreach (var plugin in pluginFiles .Where(x => !_fileProvider.GetFileName(x).Equals(_fileProvider.GetFileName(mainPluginFile), StringComparison.InvariantCultureIgnoreCase)) .Where(x => !IsAlreadyLoaded(x))) { PerformFileDeploy(plugin, applicationPartManager); } // init插件类型(每个程序集只允许一个插件) foreach (var t in pluginDescriptor.ReferencedAssembly.GetTypes()) { if (typeof(IPlugin).IsAssignableFrom(t)) { if (!t.IsInterface) { if (t.IsClass && !t.IsAbstract) { pluginDescriptor.PluginType = t; break; } } } } referencedPlugins.Add(pluginDescriptor); } catch (ReflectionTypeLoadException ex) { // 添加插件名称。并从新抛出异常 var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. "; foreach (var e in ex.LoaderExceptions) { msg += e.Message + Environment.NewLine; } var fail = new Exception(msg, ex); throw fail; } catch (Exception ex) { // 添加插件名称。并从新抛出异常 var msg = $"Plugin '{pluginDescriptor.FriendlyName}'. {ex.Message}"; var fail = new Exception(msg, ex); throw fail; } } } catch (Exception ex) { var msg = string.Empty; for (var e = ex; e != null; e = e.InnerException) { msg += e.Message + Environment.NewLine; } var fail = new Exception(msg, ex); throw fail; } ReferencedPlugins = referencedPlugins; } }
public void AddMvcCore_ReusesExistingApplicationPartManagerInstance_IfFoundOnServiceCollection() { // Arrange var services = new ServiceCollection(); var manager = new ApplicationPartManager(); services.AddSingleton(manager); // Act services.AddMvc(); // Assert var descriptor = Assert.Single(services, d => d.ServiceType == typeof(ApplicationPartManager)); Assert.Same(manager, descriptor.ImplementationInstance); }
private static void ConfigureApplicationParts(ApplicationPartManager partManager) { partManager.ApplicationParts.Add(new AssemblyPart(Assembly.GetExecutingAssembly())); }
private static void RegisterFeatures(ApplicationPartManager partManager) { partManager.FeatureProviders.Add(new MetadataReferenceFeatureProvider()); }
/// <summary> /// Initialize /// </summary> public static void Initialize(ApplicationPartManager applicationPartManager, YimiConfig config) { if (applicationPartManager == null) { throw new ArgumentNullException("applicationPartManager"); } if (config == null) { throw new ArgumentNullException("config"); } using (new WriteLockDisposable(Locker)) { // TODO: Add verbose exception handling / raising here since this is happening on app startup and could // prevent app from starting altogether var pluginFolder = new DirectoryInfo(CommonHelper.MapPath(PluginsPath)); _shadowCopyFolder = new DirectoryInfo(CommonHelper.MapPath(ShadowCopyPath)); var referencedPlugins = new List <PluginDescriptor>(); var incompatiblePlugins = new List <string>(); try { var installedPluginSystemNames = PluginFileParser.ParseInstalledPluginsFile(GetInstalledPluginsFilePath()); Debug.WriteLine("Creating shadow copy folder and querying for dlls"); //ensure folders are created Directory.CreateDirectory(pluginFolder.FullName); Directory.CreateDirectory(_shadowCopyFolder.FullName); //get list of all files in bin var binFiles = _shadowCopyFolder.GetFiles("*", SearchOption.AllDirectories); if (config.ClearPluginShadowDirectoryOnStartup) { //clear out shadow copied plugins foreach (var f in binFiles) { Debug.WriteLine("Deleting " + f.Name); try { //ignore index.htm var fileName = Path.GetFileName(f.FullName); if (fileName.Equals("index.htm", StringComparison.OrdinalIgnoreCase)) { continue; } File.Delete(f.FullName); } catch (Exception exc) { Debug.WriteLine("Error deleting file " + f.Name + ". Exception: " + exc); } } } //load description files foreach (var dfd in GetDescriptionFilesAndDescriptors(pluginFolder)) { var descriptionFile = dfd.Key; var pluginDescriptor = dfd.Value; //ensure that version of plugin is valid if (!pluginDescriptor.SupportedVersions.Contains(YimiVersion.CurrentVersion, StringComparer.OrdinalIgnoreCase)) { incompatiblePlugins.Add(pluginDescriptor.SystemName); continue; } //some validation if (String.IsNullOrWhiteSpace(pluginDescriptor.SystemName)) { throw new Exception(string.Format("A plugin '{0}' has no system name. Try assigning the plugin a unique name and recompiling.", descriptionFile.FullName)); } if (referencedPlugins.Contains(pluginDescriptor)) { throw new Exception(string.Format("A plugin with '{0}' system name is already defined", pluginDescriptor.SystemName)); } //set 'Installed' property pluginDescriptor.Installed = installedPluginSystemNames .FirstOrDefault(x => x.Equals(pluginDescriptor.SystemName, StringComparison.OrdinalIgnoreCase)) != null; try { if (descriptionFile.Directory == null) { throw new Exception(string.Format("Directory cannot be resolved for '{0}' description file", descriptionFile.Name)); } //get list of all DLLs in plugins (not in bin!) var pluginFiles = descriptionFile.Directory.GetFiles("*.dll", SearchOption.AllDirectories) //just make sure we're not registering shadow copied plugins .Where(x => !binFiles.Select(q => q.FullName).Contains(x.FullName)) .Where(x => IsPackagePluginFolder(x.Directory)) .ToList(); //TO DO - copy files only from plugins - description.txt ? //other plugin description info var mainPluginFile = pluginFiles .FirstOrDefault(x => x.Name.Equals(pluginDescriptor.PluginFileName, StringComparison.OrdinalIgnoreCase)); pluginDescriptor.OriginalAssemblyFile = mainPluginFile; //shadow copy main plugin file pluginDescriptor.ReferencedAssembly = PerformFileDeploy(mainPluginFile, applicationPartManager); //load all other referenced assemblies now foreach (var plugin in pluginFiles .Where(x => !x.Name.Equals(mainPluginFile.Name, StringComparison.OrdinalIgnoreCase)) .Where(x => !IsAlreadyLoaded(x))) { PerformFileDeploy(plugin, applicationPartManager); } //init plugin type (only one plugin per assembly is allowed) foreach (var t in pluginDescriptor.ReferencedAssembly.GetTypes()) { if (typeof(IPlugin).IsAssignableFrom(t)) { if (!t.GetTypeInfo().IsInterface) { if (t.GetTypeInfo().IsClass&& !t.GetTypeInfo().IsAbstract) { pluginDescriptor.PluginType = t; break; } } } } referencedPlugins.Add(pluginDescriptor); } catch (ReflectionTypeLoadException ex) { //add a plugin name. this way we can easily identify a problematic plugin var msg = string.Format("Plugin '{0}'. ", pluginDescriptor.FriendlyName); foreach (var e in ex.LoaderExceptions) { msg += e.Message + Environment.NewLine; } var fail = new Exception(msg, ex); throw fail; } catch (Exception ex) { //add a plugin name. this way we can easily identify a problematic plugin var msg = string.Format("Plugin '{0}'. {1}", pluginDescriptor.FriendlyName, ex.Message); var fail = new Exception(msg, ex); throw fail; } } } catch (Exception ex) { var msg = string.Empty; for (var e = ex; e != null; e = e.InnerException) { msg += e.Message + Environment.NewLine; } var fail = new Exception(msg, ex); throw fail; } ReferencedPlugins = referencedPlugins; IncompatiblePlugins = incompatiblePlugins; } }
private static ApplicationPartManager GetApplicationManager(List<TypeInfo> controllerTypes) { var manager = new ApplicationPartManager(); manager.ApplicationParts.Add(new TestApplicationPart(controllerTypes)); manager.FeatureProviders.Add(new TestFeatureProvider()); return manager; }
private static bool HasPart(ApplicationPartManager apm, string name) { return(apm.ApplicationParts .Any(p => p is CompiledRazorAssemblyPart cp && cp.Assembly.GetName().Name == "Microsoft.AspNetCore.Identity.UI.Views." + name)); }
public ServerTestBase() { var builder = new WebHostBuilder().UseContentRoot("..\\..\\..\\..\\OpenIddict698\\") .ConfigureAppConfiguration( (hostingContext, config) => { config.AddInMemoryCollection(new Dictionary <string, string> { { "InMemoryDatabaseName", Guid.NewGuid().ToString("N") } }); }) .ConfigureServices(services => { var startupAssembly = typeof(Startup).GetTypeInfo().Assembly; // Inject a custom application part manager. Overrides AddMvcCore() because that uses TryAdd(). var manager = new ApplicationPartManager(); manager.ApplicationParts.Add(new AssemblyPart(startupAssembly)); manager.FeatureProviders.Add(new ControllerFeatureProvider()); manager.FeatureProviders.Add(new ViewComponentFeatureProvider()); services.AddSingleton(manager); services.PostConfigure( JwtBearerDefaults.AuthenticationScheme, (Action <JwtBearerOptions>)(options => { options.ConfigurationManager = new ConfigurationManager <OpenIdConnectConfiguration> ( Startup.ConfigurationPath, new OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever(Client) { RequireHttps = false } ); })); }) .UseEnvironment("test") .UseStartup <Startup>(); TestServer = new TestServer(builder); var serviceProvider = TestServer.Host.Services; _contextOptions = serviceProvider.GetRequiredService <DbContextOptions <ApplicationDbContext> >(); using (var context = CreateContext()) { var userRole = new IdentityRole { Name = ApplicationRole, NormalizedName = ApplicationRole.ToUpper() }; context.Add(userRole); context.SaveChanges(); var user = new ApplicationUser { NormalizedUserName = UserName.ToUpper(), UserName = UserName, SecurityStamp = Guid.NewGuid().ToString() }; user.PasswordHash = serviceProvider.GetRequiredService <IPasswordHasher <ApplicationUser> >().HashPassword(user, Password); context.Add(user); context.Add(new IdentityUserRole <string> { RoleId = userRole.Id, UserId = user.Id }); context.SaveChanges(); } Client = TestServer.CreateClient(); }
public MvcModuleSetup(ApplicationPartManager partManager) { _partManager = partManager; }
public ApplicationPartsLogger(ILogger <ApplicationPartsLogger> logger, ApplicationPartManager partManager) { _logger = logger; _partManager = partManager; }