Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreThis browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Note
This isn't the latest version of this article. For the current release, see the .NET 9 version of this article.
Warning
This version of ASP.NET Core is no longer supported. For more information, see the .NET and .NET Core Support Policy. For the current release, see the .NET 9 version of this article.
Important
This information relates to a pre-release product that may be substantially modified before it's commercially released. Microsoft makes no warranties, express or implied, with respect to the information provided here.
For the current release, see the .NET 9 version of this article.
An IHostingStartup (hosting startup) implementation adds enhancements to an app at startup from an external assembly. For example, an external library can use a hosting startup implementation to provide additional configuration providers or services to an app.
View or download sample code (how to download)
A HostingStartup attribute indicates the presence of a hosting startup assembly to activate at runtime.
The entry assembly or the assembly containing the Startup
class is automatically scanned for the HostingStartup
attribute. The list of assemblies to search for HostingStartup
attributes is loaded at runtime from configuration in the WebHostDefaults.HostingStartupAssembliesKey. The list of assemblies to exclude from discovery is loaded from the WebHostDefaults.HostingStartupExcludeAssembliesKey.
In the following example, the namespace of the hosting startup assembly is StartupEnhancement
. The class containing the hosting startup code is StartupEnhancementHostingStartup
:
[assembly: HostingStartup(typeof(StartupEnhancement.StartupEnhancementHostingStartup))]
The HostingStartup
attribute is typically located in the hosting startup assembly's IHostingStartup
implementation class file.
To discover loaded hosting startup assemblies, enable logging and check the app's logs. Errors that occur when loading assemblies are logged. Loaded hosting startup assemblies are logged at the Debug level, and all errors are logged.
To disable automatic loading of hosting startup assemblies, use one of the following approaches:
To prevent all hosting startup assemblies from loading, set one of the following to true
or 1
:
Prevent Hosting Startup host configuration setting:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseSetting(
WebHostDefaults.PreventHostingStartupKey, "true")
.UseStartup<Startup>();
});
ASPNETCORE_PREVENTHOSTINGSTARTUP
environment variable.
To prevent specific hosting startup assemblies from loading, set one of the following to a semicolon-delimited string of hosting startup assemblies to exclude at startup:
Hosting Startup Exclude Assemblies host configuration setting:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseSetting(
WebHostDefaults.HostingStartupExcludeAssembliesKey,
"{ASSEMBLY1;ASSEMBLY2; ...}")
.UseStartup<Startup>();
});
The {ASSEMBLY1;ASSEMBLY2; ...}
placeholder represents the semicolon-separated list of assemblies.
ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
environment variable.
If both the host configuration setting and the environment variable are set, the host setting controls the behavior.
Disabling hosting startup assemblies using the host setting or environment variable disables the assembly globally and may disable several characteristics of an app.
Create a hosting startup with either of the following project types:
A hosting startup enhancement can be provided in a class library. The library contains a HostingStartup
attribute.
The sample code includes a Razor Pages app, HostingStartupApp, and a class library, HostingStartupLibrary. The class library:
ServiceKeyInjection
, which implements IHostingStartup
. ServiceKeyInjection
adds a pair of service strings to the app's configuration using the in-memory configuration provider (AddInMemoryCollection).HostingStartup
attribute that identifies the hosting startup's namespace and class.The ServiceKeyInjection
class's Configure method uses an IWebHostBuilder to add enhancements to an app.
HostingStartupLibrary/ServiceKeyInjection.cs
:
[assembly: HostingStartup(typeof(HostingStartupLibrary.ServiceKeyInjection))]
namespace HostingStartupLibrary
{
public class ServiceKeyInjection : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration(config =>
{
var dict = new Dictionary<string, string>
{
{"DevAccount_FromLibrary", "DEV_1111111-1111"},
{"ProdAccount_FromLibrary", "PROD_2222222-2222"}
};
config.AddInMemoryCollection(dict);
});
}
}
}
The app's Index page reads and renders the configuration values for the two keys set by the class library's hosting startup assembly:
HostingStartupApp/Pages/Index.cshtml.cs
:
public class IndexModel : PageModel
{
public IndexModel(IConfiguration config)
{
ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
ServiceKey_Development_Package = config["DevAccount_FromPackage"];
ServiceKey_Production_Package = config["ProdAccount_FromPackage"];
}
public string ServiceKey_Development_Library { get; private set; }
public string ServiceKey_Production_Library { get; private set; }
public string ServiceKey_Development_Package { get; private set; }
public string ServiceKey_Production_Package { get; private set; }
public void OnGet()
{
}
}
The sample code also includes a NuGet package project that provides a separate hosting startup, HostingStartupPackage. The package has the same characteristics of the class library described earlier. The package:
ServiceKeyInjection
, which implements IHostingStartup
. ServiceKeyInjection
adds a pair of service strings to the app's configuration.HostingStartup
attribute.HostingStartupPackage/ServiceKeyInjection.cs
:
[assembly: HostingStartup(typeof(HostingStartupPackage.ServiceKeyInjection))]
namespace HostingStartupPackage
{
public class ServiceKeyInjection : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration(config =>
{
var dict = new Dictionary<string, string>
{
{"DevAccount_FromPackage", "DEV_3333333-3333"},
{"ProdAccount_FromPackage", "PROD_4444444-4444"}
};
config.AddInMemoryCollection(dict);
});
}
}
}
The app's Index page reads and renders the configuration values for the two keys set by the package's hosting startup assembly:
HostingStartupApp/Pages/Index.cshtml.cs
:
public class IndexModel : PageModel
{
public IndexModel(IConfiguration config)
{
ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
ServiceKey_Development_Package = config["DevAccount_FromPackage"];
ServiceKey_Production_Package = config["ProdAccount_FromPackage"];
}
public string ServiceKey_Development_Library { get; private set; }
public string ServiceKey_Production_Library { get; private set; }
public string ServiceKey_Development_Package { get; private set; }
public string ServiceKey_Production_Package { get; private set; }
public void OnGet()
{
}
}
This approach is only available for .NET Core apps, not .NET Framework.
A dynamic hosting startup enhancement that doesn't require a compile-time reference for activation can be provided in a console app without an entry point that contains a HostingStartup
attribute. Publishing the console app produces a hosting startup assembly that can be consumed from the runtime store.
A console app without an entry point is used in this process because:
In the creation of a dynamic hosting startup:
IHostingStartup
implementation.IHostingStartup
implementation class.The console app references the Microsoft.AspNetCore.Hosting.Abstractions package:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions"
Version="3.0.0" />
</ItemGroup>
</Project>
A HostingStartup attribute identifies a class as an implementation of IHostingStartup
for loading and execution when building the IWebHost. In the following example, the namespace is StartupEnhancement
, and the class is StartupEnhancementHostingStartup
:
[assembly: HostingStartup(typeof(StartupEnhancement.StartupEnhancementHostingStartup))]
A class implements IHostingStartup
. The class's Configure method uses an IWebHostBuilder to add enhancements to an app. IHostingStartup.Configure
in the hosting startup assembly is called by the runtime before Startup.Configure
in user code, which allows user code to overwrite any configuration provided by the hosting startup assembly.
namespace StartupEnhancement
{
public class StartupEnhancementHostingStartup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
// Use the IWebHostBuilder to add app enhancements.
}
}
}
When building an IHostingStartup
project, the dependencies file (.deps.json
) sets the runtime
location of the assembly to the bin folder:
"targets": {
".NETCoreApp,Version=v3.0": {
"StartupEnhancement/1.0.0": {
"dependencies": {
"Microsoft.AspNetCore.Hosting.Abstractions": "3.0.0"
},
"runtime": {
"StartupEnhancement.dll": {}
}
}
}
}
Only part of the file is shown. The assembly name in the example is StartupEnhancement
.
There are two approaches to handling configuration depending on whether you want the hosting startup's configuration to take precedence or the app's configuration to take precedence:
public class ConfigurationInjection : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
Dictionary<string, string> dict;
builder.ConfigureAppConfiguration(config =>
{
dict = new Dictionary<string, string>
{
{"ConfigurationKey1",
"From IHostingStartup: Higher priority " +
"than the app's configuration."},
};
config.AddInMemoryCollection(dict);
});
dict = new Dictionary<string, string>
{
{"ConfigurationKey2",
"From IHostingStartup: Lower priority " +
"than the app's configuration."},
};
var builtConfig = new ConfigurationBuilder()
.AddInMemoryCollection(dict)
.Build();
builder.UseConfiguration(builtConfig);
}
}
For either a class library- or console app-supplied hosting startup, specify the hosting startup assembly's name in the ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
environment variable. The environment variable is a semicolon-delimited list of assemblies.
Only hosting startup assemblies are scanned for the HostingStartup
attribute. For the sample app, HostingStartupApp, to discover the hosting startups described earlier, the environment variable is set to the following value:
HostingStartupLibrary;HostingStartupPackage;StartupDiagnostics
A hosting startup assembly can also be set using the Hosting Startup Assemblies host configuration setting:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseSetting(
WebHostDefaults.HostingStartupAssembliesKey,
"{ASSEMBLY1;ASSEMBLY2; ...}")
.UseStartup<Startup>();
});
The {ASSEMBLY1;ASSEMBLY2; ...}
placeholder represents the semicolon-separated list of assemblies.
When multiple hosting startup assembles are present, their Configure methods are executed in the order that the assemblies are listed.
Options for hosting startup activation are:
The hosting startup implementation is placed in the runtime store. A compile-time reference to the assembly isn't required by the enhanced app.
After the hosting startup is built, a runtime store is generated using the manifest project file and the dotnet store command.
dotnet store --manifest {MANIFEST FILE} --runtime {RUNTIME IDENTIFIER} --output {OUTPUT LOCATION} --skip-optimization
In the sample app (RuntimeStore project) the following command is used:
dotnet store --manifest store.manifest.csproj --runtime win7-x64 --output ./deployment/store --skip-optimization
For the runtime to discover the runtime store, the runtime store's location is added to the DOTNET_SHARED_STORE
environment variable.
Modify and place the hosting startup's dependencies file
To activate the enhancement without a package reference to the enhancement, specify additional dependencies to the runtime with additionalDeps
. additionalDeps
allows you to:
.deps.json
files to merge with the app's own .deps.json
file on startup.The recommended approach for generating the additional dependencies file is to:
dotnet publish
on the runtime store manifest file referenced in the previous section.runtime
section of the resulting .deps.json
file.In the example project, the store.manifest/1.0.0
property is removed from the targets
and libraries
section:
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v3.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v3.0": {
"store.manifest/1.0.0": {
"dependencies": {
"StartupDiagnostics": "1.0.0"
},
"runtime": {
"store.manifest.dll": {}
}
},
"StartupDiagnostics/1.0.0": {
"runtime": {
"lib/netcoreapp3.0/StartupDiagnostics.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
}
}
},
"libraries": {
"store.manifest/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StartupDiagnostics/1.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-xrhzuNSyM5/f4ZswhooJ9dmIYLP64wMnqUJSyTKVDKDVj5T+qtzypl8JmM/aFJLLpYrf0FYpVWvGujd7/FfMEw==",
"path": "startupdiagnostics/1.0.0",
"hashPath": "startupdiagnostics.1.0.0.nupkg.sha512"
}
}
}
Place the .deps.json
file into the following location:
{ADDITIONAL DEPENDENCIES PATH}/shared/{SHARED FRAMEWORK NAME}/{SHARED FRAMEWORK VERSION}/{ENHANCEMENT ASSEMBLY NAME}.deps.json
{ADDITIONAL DEPENDENCIES PATH}
: Location added to the DOTNET_ADDITIONAL_DEPS
environment variable.{SHARED FRAMEWORK NAME}
: Shared framework required for this additional dependencies file.{SHARED FRAMEWORK VERSION}
: Minimum shared framework version.{ENHANCEMENT ASSEMBLY NAME}
: The enhancement's assembly name.In the sample app (RuntimeStore project), the additional dependencies file is placed into the following location:
deployment/additionalDeps/shared/Microsoft.AspNetCore.App/3.0.0/StartupDiagnostics.deps.json
For runtime to discover the runtime store location, the additional dependencies file location is added to the DOTNET_ADDITIONAL_DEPS
environment variable.
In the sample app (RuntimeStore project), building the runtime store and generating the additional dependencies file is accomplished using a PowerShell script.
For examples of how to set environment variables for various operating systems, see Use multiple environments.
Deployment
To facilitate the deployment of a hosting startup in a multimachine environment, the sample app creates a deployment folder in published output that contains:
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
, DOTNET_SHARED_STORE
, and DOTNET_ADDITIONAL_DEPS
to support the activation of the hosting startup. Run the script from an administrative PowerShell command prompt on the deployment system.A hosting startup enhancement can be provided in a NuGet package. The package has a HostingStartup
attribute. The hosting startup types provided by the package are made available to the app using either of the following approaches:
.deps.json
). This approach applies to a hosting startup assembly package published to nuget.org.For more information on NuGet packages and the runtime store, see the following topics:
A hosting startup enhancement can be provided by a bin-deployed assembly in the enhanced app. The hosting startup types provided by the assembly are made available to the app using one of the following approaches:
.deps.json
). This approach applies when the deployment scenario calls for making a compile-time reference to the hosting startup's assembly (.dll file) and moving the assembly to either:
The sample code (how to download) demonstrates hosting startup implementation scenarios:
To run the sample:
Activation from a NuGet package
Compile the HostingStartupPackage package with the dotnet pack command.
Add the package's assembly name of the HostingStartupPackage to the ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
environment variable.
Compile and run the app. A package reference is present in the enhanced app (a compile-time reference). A <PropertyGroup>
in the app's project file specifies the package project's output (../HostingStartupPackage/bin/Debug) as a package source. This allows the app to use the package without uploading the package to nuget.org. For more information, see the notes in the HostingStartupApp's project file.
<PropertyGroup>
<RestoreSources>$(RestoreSources);https://api.nuget.org/v3/index.json;../HostingStartupPackage/bin/Debug</RestoreSources>
</PropertyGroup>
Observe that the service configuration key values rendered by the Index page match the values set by the package's ServiceKeyInjection.Configure
method.
If you make changes to the HostingStartupPackage project and recompile it, clear the local NuGet package caches to ensure that the HostingStartupApp receives the updated package and not a stale package from the local cache. To clear the local NuGet caches, execute the following dotnet nuget locals command:
dotnet nuget locals all --clear
Activation from a class library
Compile the HostingStartupLibrary class library with the dotnet build command.
Add the class library's assembly name of HostingStartupLibrary to the ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
environment variable.
bin-deploy the class library's assembly to the app by copying the HostingStartupLibrary.dll file from the class library's compiled output to the app's bin/Debug folder.
Compile and run the app. An <ItemGroup>
in the app's project file references the class library's assembly (.\bin\Debug\netcoreapp3.0\HostingStartupLibrary.dll) (a compile-time reference). For more information, see the notes in the HostingStartupApp's project file.
<ItemGroup>
<Reference Include=".\\bin\\Debug\\netcoreapp3.0\\HostingStartupLibrary.dll">
<HintPath>.\bin\Debug\netcoreapp3.0\HostingStartupLibrary.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
</ItemGroup>
Observe that the service configuration key values rendered by the Index page match the values set by the class library's ServiceKeyInjection.Configure
method.
Activation from a runtime store-deployed assembly
StartupDiagnostics.deps.json
file. PowerShell is installed by default on Windows starting with Windows 7 SP1 and Windows Server 2008 R2 SP1. To obtain PowerShell on other platforms, see Installing various versions of PowerShell.StartupDiagnostics
package in the obj\packages folder.StartupDiagnostics
in the store folder. The dotnet store
command in the script uses the win7-x64
runtime identifier (RID) for a hosting startup deployed to Windows. When providing the hosting startup for a different runtime, substitute the correct RID on line 37 of the script. The runtime store for StartupDiagnostics
would later be moved to the user's or system's runtime store on the machine where the assembly will be consumed. The user runtime store install location for the StartupDiagnostics
assembly is .dotnet/store/x64/netcoreapp3.0/startupdiagnostics/1.0.0/lib/netcoreapp3.0/StartupDiagnostics.dll.additionalDeps
for StartupDiagnostics
in the additionalDeps folder. The additional dependencies would later be moved to the user's or system's additional dependencies. The user StartupDiagnostics
additional dependencies install location is .dotnet/x64/additionalDeps/StartupDiagnostics/shared/Microsoft.NETCore.App/3.0.0/StartupDiagnostics.deps.json
.StartupDiagnostics
to the ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
environment variable.DOTNET_ADDITIONAL_DEPS
environment variable.DOTNET_SHARED_STORE
environment variable./services
endpoint to see the app's registered services. Request the /diag
endpoint to see the diagnostic information.An IHostingStartup (hosting startup) implementation adds enhancements to an app at startup from an external assembly. For example, an external library can use a hosting startup implementation to provide additional configuration providers or services to an app.
View or download sample code (how to download)
A HostingStartup attribute indicates the presence of a hosting startup assembly to activate at runtime.
The entry assembly or the assembly containing the Startup
class is automatically scanned for the HostingStartup
attribute. The list of assemblies to search for HostingStartup
attributes is loaded at runtime from configuration in the WebHostDefaults.HostingStartupAssembliesKey. The list of assemblies to exclude from discovery is loaded from the WebHostDefaults.HostingStartupExcludeAssembliesKey. For more information, see Web Host: Hosting Startup Assemblies and Web Host: Hosting Startup Exclude Assemblies.
In the following example, the namespace of the hosting startup assembly is StartupEnhancement
. The class containing the hosting startup code is StartupEnhancementHostingStartup
:
[assembly: HostingStartup(typeof(StartupEnhancement.StartupEnhancementHostingStartup))]
The HostingStartup
attribute is typically located in the hosting startup assembly's IHostingStartup
implementation class file.
To discover loaded hosting startup assemblies, enable logging and check the app's logs. Errors that occur when loading assemblies are logged. Loaded hosting startup assemblies are logged at the Debug level, and all errors are logged.
To disable automatic loading of hosting startup assemblies, use one of the following approaches:
true
or 1
:
ASPNETCORE_PREVENTHOSTINGSTARTUP
environment variable.ASPNETCORE_HOSTINGSTARTUPEXCLUDEASSEMBLIES
environment variable.If both the host configuration setting and the environment variable are set, the host setting controls the behavior.
Disabling hosting startup assemblies using the host setting or environment variable disables the assembly globally and may disable several characteristics of an app.
Create a hosting startup with either of the following project types:
A hosting startup enhancement can be provided in a class library. The library contains a HostingStartup
attribute.
The sample code includes a Razor Pages app, HostingStartupApp, and a class library, HostingStartupLibrary. The class library:
ServiceKeyInjection
, which implements IHostingStartup
. ServiceKeyInjection
adds a pair of service strings to the app's configuration using the in-memory configuration provider (AddInMemoryCollection).HostingStartup
attribute that identifies the hosting startup's namespace and class.The ServiceKeyInjection
class's Configure method uses an IWebHostBuilder to add enhancements to an app.
HostingStartupLibrary/ServiceKeyInjection.cs
:
[assembly: HostingStartup(typeof(HostingStartupLibrary.ServiceKeyInjection))]
namespace HostingStartupLibrary
{
public class ServiceKeyInjection : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration(config =>
{
var dict = new Dictionary<string, string>
{
{"DevAccount_FromLibrary", "DEV_1111111-1111"},
{"ProdAccount_FromLibrary", "PROD_2222222-2222"}
};
config.AddInMemoryCollection(dict);
});
}
}
}
The app's Index page reads and renders the configuration values for the two keys set by the class library's hosting startup assembly:
HostingStartupApp/Pages/Index.cshtml.cs
:
public class IndexModel : PageModel
{
public IndexModel(IConfiguration config)
{
ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
ServiceKey_Development_Package = config["DevAccount_FromPackage"];
ServiceKey_Production_Package = config["ProdAccount_FromPackage"];
}
public string ServiceKey_Development_Library { get; private set; }
public string ServiceKey_Production_Library { get; private set; }
public string ServiceKey_Development_Package { get; private set; }
public string ServiceKey_Production_Package { get; private set; }
public void OnGet()
{
}
}
The sample code also includes a NuGet package project that provides a separate hosting startup, HostingStartupPackage. The package has the same characteristics of the class library described earlier. The package:
ServiceKeyInjection
, which implements IHostingStartup
. ServiceKeyInjection
adds a pair of service strings to the app's configuration.HostingStartup
attribute.HostingStartupPackage/ServiceKeyInjection.cs
:
[assembly: HostingStartup(typeof(HostingStartupPackage.ServiceKeyInjection))]
namespace HostingStartupPackage
{
public class ServiceKeyInjection : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureAppConfiguration(config =>
{
var dict = new Dictionary<string, string>
{
{"DevAccount_FromPackage", "DEV_3333333-3333"},
{"ProdAccount_FromPackage", "PROD_4444444-4444"}
};
config.AddInMemoryCollection(dict);
});
}
}
}
The app's Index page reads and renders the configuration values for the two keys set by the package's hosting startup assembly:
HostingStartupApp/Pages/Index.cshtml.cs
:
public class IndexModel : PageModel
{
public IndexModel(IConfiguration config)
{
ServiceKey_Development_Library = config["DevAccount_FromLibrary"];
ServiceKey_Production_Library = config["ProdAccount_FromLibrary"];
ServiceKey_Development_Package = config["DevAccount_FromPackage"];
ServiceKey_Production_Package = config["ProdAccount_FromPackage"];
}
public string ServiceKey_Development_Library { get; private set; }
public string ServiceKey_Production_Library { get; private set; }
public string ServiceKey_Development_Package { get; private set; }
public string ServiceKey_Production_Package { get; private set; }
public void OnGet()
{
}
}
This approach is only available for .NET Core apps, not .NET Framework.
A dynamic hosting startup enhancement that doesn't require a compile-time reference for activation can be provided in a console app without an entry point that contains a HostingStartup
attribute. Publishing the console app produces a hosting startup assembly that can be consumed from the runtime store.
A console app without an entry point is used in this process because:
In the creation of a dynamic hosting startup:
IHostingStartup
implementation.IHostingStartup
implementation class.The console app references the Microsoft.AspNetCore.Hosting.Abstractions package:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions"
Version="2.1.1" />
</ItemGroup>
</Project>
A HostingStartup attribute identifies a class as an implementation of IHostingStartup
for loading and execution when building the IWebHost. In the following example, the namespace is StartupEnhancement
, and the class is StartupEnhancementHostingStartup
:
[assembly: HostingStartup(typeof(StartupEnhancement.StartupEnhancementHostingStartup))]
A class implements IHostingStartup
. The class's Configure method uses an IWebHostBuilder to add enhancements to an app. IHostingStartup.Configure
in the hosting startup assembly is called by the runtime before Startup.Configure
in user code, which allows user code to overwrite any configuration provided by the hosting startup assembly.
namespace StartupEnhancement
{
public class StartupEnhancementHostingStartup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
// Use the IWebHostBuilder to add app enhancements.
}
}
}
When building an IHostingStartup
project, the dependencies file (.deps.json
) sets the runtime
location of the assembly to the bin folder:
"targets": {
".NETCoreApp,Version=v2.1": {
"StartupEnhancement/1.0.0": {
"dependencies": {
"Microsoft.AspNetCore.Hosting.Abstractions": "2.1.1"
},
"runtime": {
"StartupEnhancement.dll": {}
}
}
}
}
Only part of the file is shown. The assembly name in the example is StartupEnhancement
.
There are two approaches to handling configuration depending on whether you want the hosting startup's configuration to take precedence or the app's configuration to take precedence:
public class ConfigurationInjection : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
Dictionary<string, string> dict;
builder.ConfigureAppConfiguration(config =>
{
dict = new Dictionary<string, string>
{
{"ConfigurationKey1",
"From IHostingStartup: Higher priority " +
"than the app's configuration."},
};
config.AddInMemoryCollection(dict);
});
dict = new Dictionary<string, string>
{
{"ConfigurationKey2",
"From IHostingStartup: Lower priority " +
"than the app's configuration."},
};
var builtConfig = new ConfigurationBuilder()
.AddInMemoryCollection(dict)
.Build();
builder.UseConfiguration(builtConfig);
}
}
For either a class library- or console app-supplied hosting startup, specify the hosting startup assembly's name in the ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
environment variable. The environment variable is a semicolon-delimited list of assemblies.
Only hosting startup assemblies are scanned for the HostingStartup
attribute. For the sample app, HostingStartupApp, to discover the hosting startups described earlier, the environment variable is set to the following value:
HostingStartupLibrary;HostingStartupPackage;StartupDiagnostics
A hosting startup assembly can also be set using the Hosting Startup Assemblies host configuration setting.
When multiple hosting startup assembles are present, their Configure methods are executed in the order that the assemblies are listed.
Options for hosting startup activation are:
The hosting startup implementation is placed in the runtime store. A compile-time reference to the assembly isn't required by the enhanced app.
After the hosting startup is built, a runtime store is generated using the manifest project file and the dotnet store command.
dotnet store --manifest {MANIFEST FILE} --runtime {RUNTIME IDENTIFIER} --output {OUTPUT LOCATION} --skip-optimization
In the sample app (RuntimeStore project) the following command is used:
dotnet store --manifest store.manifest.csproj --runtime win7-x64 --output ./deployment/store --skip-optimization
For the runtime to discover the runtime store, the runtime store's location is added to the DOTNET_SHARED_STORE
environment variable.
Modify and place the hosting startup's dependencies file
To activate the enhancement without a package reference to the enhancement, specify additional dependencies to the runtime with additionalDeps
. additionalDeps
allows you to:
.deps.json
files to merge with the app's own .deps.json
file on startup.The recommended approach for generating the additional dependencies file is to:
dotnet publish
on the runtime store manifest file referenced in the previous section.runtime
section of the resulting .deps.json
file.In the example project, the store.manifest/1.0.0
property is removed from the targets
and libraries
section:
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v2.1",
"signature": "4ea77c7b75ad1895ae1ea65e6ba2399010514f99"
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v2.1": {
"store.manifest/1.0.0": {
"dependencies": {
"StartupDiagnostics": "1.0.0"
},
"runtime": {
"store.manifest.dll": {}
}
},
"StartupDiagnostics/1.0.0": {
"runtime": {
"lib/netcoreapp2.1/StartupDiagnostics.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
}
}
},
"libraries": {
"store.manifest/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StartupDiagnostics/1.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-oiQr60vBQW7+nBTmgKLSldj06WNLRTdhOZpAdEbCuapoZ+M2DJH2uQbRLvFT8EGAAv4TAKzNtcztpx5YOgBXQQ==",
"path": "startupdiagnostics/1.0.0",
"hashPath": "startupdiagnostics.1.0.0.nupkg.sha512"
}
}
}
Place the .deps.json
file into the following location:
{ADDITIONAL DEPENDENCIES PATH}/shared/{SHARED FRAMEWORK NAME}/{SHARED FRAMEWORK VERSION}/{ENHANCEMENT ASSEMBLY NAME}.deps.json
{ADDITIONAL DEPENDENCIES PATH}
: Location added to the DOTNET_ADDITIONAL_DEPS
environment variable.{SHARED FRAMEWORK NAME}
: Shared framework required for this additional dependencies file.{SHARED FRAMEWORK VERSION}
: Minimum shared framework version.{ENHANCEMENT ASSEMBLY NAME}
: The enhancement's assembly name.In the sample app (RuntimeStore project), the additional dependencies file is placed into the following location:
deployment/additionalDeps/shared/Microsoft.AspNetCore.App/2.1.0/StartupDiagnostics.deps.json
For runtime to discover the runtime store location, the additional dependencies file location is added to the DOTNET_ADDITIONAL_DEPS
environment variable.
In the sample app (RuntimeStore project), building the runtime store and generating the additional dependencies file is accomplished using a PowerShell script.
For examples of how to set environment variables for various operating systems, see Use multiple environments.
Deployment
To facilitate the deployment of a hosting startup in a multimachine environment, the sample app creates a deployment folder in published output that contains:
ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
, DOTNET_SHARED_STORE
, and DOTNET_ADDITIONAL_DEPS
to support the activation of the hosting startup. Run the script from an administrative PowerShell command prompt on the deployment system.A hosting startup enhancement can be provided in a NuGet package. The package has a HostingStartup
attribute. The hosting startup types provided by the package are made available to the app using either of the following approaches:
.deps.json
). This approach applies to a hosting startup assembly package published to nuget.org.For more information on NuGet packages and the runtime store, see the following topics:
A hosting startup enhancement can be provided by a bin-deployed assembly in the enhanced app. The hosting startup types provided by the assembly are made available to the app using one of the following approaches:
.deps.json
). This approach applies when the deployment scenario calls for making a compile-time reference to the hosting startup's assembly (.dll file) and moving the assembly to either:
The sample code (how to download) demonstrates hosting startup implementation scenarios:
To run the sample:
Activation from a NuGet package
Compile the HostingStartupPackage package with the dotnet pack command.
Add the package's assembly name of the HostingStartupPackage to the ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
environment variable.
Compile and run the app. A package reference is present in the enhanced app (a compile-time reference). A <PropertyGroup>
in the app's project file specifies the package project's output (../HostingStartupPackage/bin/Debug) as a package source. This allows the app to use the package without uploading the package to nuget.org. For more information, see the notes in the HostingStartupApp's project file.
<PropertyGroup>
<RestoreSources>$(RestoreSources);https://api.nuget.org/v3/index.json;../HostingStartupPackage/bin/Debug</RestoreSources>
</PropertyGroup>
Observe that the service configuration key values rendered by the Index page match the values set by the package's ServiceKeyInjection.Configure
method.
If you make changes to the HostingStartupPackage project and recompile it, clear the local NuGet package caches to ensure that the HostingStartupApp receives the updated package and not a stale package from the local cache. To clear the local NuGet caches, execute the following dotnet nuget locals command:
dotnet nuget locals all --clear
Activation from a class library
Compile the HostingStartupLibrary class library with the dotnet build command.
Add the class library's assembly name of HostingStartupLibrary to the ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
environment variable.
bin-deploy the class library's assembly to the app by copying the HostingStartupLibrary.dll file from the class library's compiled output to the app's bin/Debug folder.
Compile and run the app. An <ItemGroup>
in the app's project file references the class library's assembly (.\bin\Debug\netcoreapp2.1\HostingStartupLibrary.dll) (a compile-time reference). For more information, see the notes in the HostingStartupApp's project file.
<ItemGroup>
<Reference Include=".\\bin\\Debug\\netcoreapp2.1\\HostingStartupLibrary.dll">
<HintPath>.\bin\Debug\netcoreapp2.1\HostingStartupLibrary.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
</ItemGroup>
Observe that the service configuration key values rendered by the Index page match the values set by the class library's ServiceKeyInjection.Configure
method.
Activation from a runtime store-deployed assembly
StartupDiagnostics.deps.json
file. PowerShell is installed by default on Windows starting with Windows 7 SP1 and Windows Server 2008 R2 SP1. To obtain PowerShell on other platforms, see Installing various versions of PowerShell.StartupDiagnostics
package in the obj\packages folder.StartupDiagnostics
in the store folder. The dotnet store
command in the script uses the win7-x64
runtime identifier (RID) for a hosting startup deployed to Windows. When providing the hosting startup for a different runtime, substitute the correct RID on line 37 of the script. The runtime store for StartupDiagnostics
would later be moved to the user's or system's runtime store on the machine where the assembly will be consumed. The user runtime store install location for the StartupDiagnostics
assembly is .dotnet/store/x64/netcoreapp2.2/startupdiagnostics/1.0.0/lib/netcoreapp2.2/StartupDiagnostics.dll.additionalDeps
for StartupDiagnostics
in the additionalDeps folder. The additional dependencies would later be moved to the user's or system's additional dependencies. The user StartupDiagnostics
additional dependencies install location is .dotnet/x64/additionalDeps/StartupDiagnostics/shared/Microsoft.NETCore.App/2.2.0/StartupDiagnostics.deps.json
.StartupDiagnostics
to the ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
environment variable.DOTNET_ADDITIONAL_DEPS
environment variable.DOTNET_SHARED_STORE
environment variable./services
endpoint to see the app's registered services. Request the /diag
endpoint to see the diagnostic information.ASP.NET Core feedback
ASP.NET Core is an open source project. Select a link to provide feedback:
Events
Power BI DataViz World Championships
Feb 14, 4 PM - Mar 31, 4 PM
With 4 chances to enter, you could win a conference package and make it to the LIVE Grand Finale in Las Vegas
Learn moreTraining
Module
Configure services with dependency injection in ASP.NET Core - Training
Understand and implement dependency injection in an ASP.NET Core app. Use ASP.NET Core's built-in service container to manage dependencies. Register services with the service container.