Renames IHostingEnvironmentLifetime to IApplicationShutdownRegistry

This commit is contained in:
Shannon
2020-03-26 15:39:20 +11:00
parent 29293bd25a
commit f24cae51d8
24 changed files with 50 additions and 63 deletions
@@ -1,6 +1,6 @@
namespace Umbraco.Core.Hosting
{
public interface IHostingEnvironmentLifetime
public interface IApplicationShutdownRegistry
{
void RegisterObject(IRegisteredObject registeredObject);
void UnregisterObject(IRegisteredObject registeredObject);
+1 -1
View File
@@ -26,7 +26,7 @@ namespace Umbraco.Core
/// </summary>
/// <param name="hostingEnvironment"></param>
/// <returns></returns>
bool Acquire(IHostingEnvironmentLifetime hostingEnvironment);
bool Acquire(IApplicationShutdownRegistry hostingEnvironment);
/// <summary>
/// Registers a resource that requires the current AppDomain to be the main domain to function.
+5 -4
View File
@@ -21,7 +21,7 @@ namespace Umbraco.Core.Runtime
#region Vars
private readonly ILogger _logger;
private IHostingEnvironmentLifetime _hostingEnvironment;
private IApplicationShutdownRegistry _hostingEnvironment;
private readonly IMainDomLock _mainDomLock;
// our own lock for local consistency
@@ -50,9 +50,10 @@ namespace Umbraco.Core.Runtime
#endregion
public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment)
public bool Acquire(IApplicationShutdownRegistry hostingEnvironment)
{
_hostingEnvironment = hostingEnvironment;
_hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
return LazyInitializer.EnsureInitialized(ref _isMainDom, ref _isInitialized, ref _locko, () =>
{
hostingEnvironment.RegisterObject(this);
@@ -199,7 +200,7 @@ namespace Umbraco.Core.Runtime
// The web app is stopping, need to wind down
Dispose(true);
_hostingEnvironment.UnregisterObject(this);
_hostingEnvironment?.UnregisterObject(this);
}
#region IDisposable Support
+1 -1
View File
@@ -18,7 +18,7 @@ namespace Umbraco.Core
public bool IsMainDom { get; private set; } = true;
// always acquire
public bool Acquire(IHostingEnvironmentLifetime hostingEnvironment) => true;
public bool Acquire(IApplicationShutdownRegistry hostingEnvironment) => true;
/// <inheritdoc />
public bool Register(Action release, int weight = 100)
@@ -99,7 +99,7 @@ namespace Umbraco.Web.Compose
IServerMessenger serverMessenger,
IServerRegistrationService registrationService,
ILogger logger,
IHostingEnvironmentLifetime hostingEnvironment,
IApplicationShutdownRegistry hostingEnvironment,
IRequestAccessor requestAccessor)
{
_runtime = runtime;
@@ -28,21 +28,6 @@ namespace Umbraco.Core.Runtime
private readonly IGlobalSettings _globalSettings;
private readonly IConnectionStrings _connectionStrings;
/// <summary>
/// Constructor
/// </summary>
/// <param name="configs"></param>
/// <param name="umbracoVersion"></param>
/// <param name="ioHelper"></param>
/// <param name="logger"></param>
/// <param name="profiler"></param>
/// <param name="umbracoBootPermissionChecker"></param>
/// <param name="hostingEnvironment"></param>
/// <param name="backOfficeInfo"></param>
/// <param name="dbProviderFactoryCreator"></param>
/// <param name="mainDom"></param>
/// <param name="typeFinder"></param>
public CoreRuntime(
Configs configs,
IUmbracoVersion umbracoVersion,
@@ -251,12 +236,12 @@ namespace Umbraco.Core.Runtime
// run handlers
RuntimeOptions.DoRuntimeEssentials(_factory);
var hostingEnvironmentLifetime = _factory.TryGetInstance<IHostingEnvironmentLifetime>();
var hostingEnvironmentLifetime = _factory.TryGetInstance<IApplicationShutdownRegistry>();
if (hostingEnvironmentLifetime == null)
throw new InvalidOperationException($"An instance of {typeof(IHostingEnvironmentLifetime)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}");
throw new InvalidOperationException($"An instance of {typeof(IApplicationShutdownRegistry)} could not be resolved from the container, ensure that one if registered in your runtime before calling {nameof(IRuntime)}.{nameof(Start)}");
// acquire the main domain - if this fails then anything that should be registered with MainDom will not operate
AcquireMainDom(MainDom, _factory.GetInstance<IHostingEnvironmentLifetime>());
AcquireMainDom(MainDom, _factory.GetInstance<IApplicationShutdownRegistry>());
// create & initialize the components
_components = _factory.GetInstance<ComponentCollection>();
@@ -287,13 +272,13 @@ namespace Umbraco.Core.Runtime
IOHelper.SetRootDirectory(path);
}
private bool AcquireMainDom(IMainDom mainDom, IHostingEnvironmentLifetime hostingEnvironmentLifetime)
private bool AcquireMainDom(IMainDom mainDom, IApplicationShutdownRegistry applicationShutdownRegistry)
{
using (var timer = ProfilingLogger.DebugDuration<CoreRuntime>("Acquiring MainDom.", "Acquired."))
{
try
{
return mainDom.Acquire(hostingEnvironmentLifetime);
return mainDom.Acquire(applicationShutdownRegistry);
}
catch
{
@@ -81,7 +81,7 @@ namespace Umbraco.Web.Scheduling
private readonly string _logPrefix;
private readonly BackgroundTaskRunnerOptions _options;
private readonly ILogger _logger;
private readonly IHostingEnvironmentLifetime _hostingEnvironment;
private readonly IApplicationShutdownRegistry _hostingEnvironment;
private readonly object _locker = new object();
private readonly BufferBlock<T> _tasks = new BufferBlock<T>(new DataflowBlockOptions());
@@ -105,7 +105,7 @@ namespace Umbraco.Web.Scheduling
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null)
public BackgroundTaskRunner(ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null)
: this(typeof(T).FullName, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook)
{ }
@@ -116,7 +116,7 @@ namespace Umbraco.Web.Scheduling
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(string name, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null)
public BackgroundTaskRunner(string name, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null)
: this(name, new BackgroundTaskRunnerOptions(), logger, hostingEnvironment, hook)
{ }
@@ -127,7 +127,7 @@ namespace Umbraco.Web.Scheduling
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null)
public BackgroundTaskRunner(BackgroundTaskRunnerOptions options, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null)
: this(typeof(T).FullName, options, logger, hostingEnvironment, hook)
{ }
@@ -139,7 +139,7 @@ namespace Umbraco.Web.Scheduling
/// <param name="logger">A logger.</param>
/// <param name="hostingEnvironment">The hosting environment</param>
/// <param name="hook">An optional main domain hook.</param>
public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IHostingEnvironmentLifetime hostingEnvironment, MainDomHook hook = null)
public BackgroundTaskRunner(string name, BackgroundTaskRunnerOptions options, ILogger logger, IApplicationShutdownRegistry hostingEnvironment, MainDomHook hook = null)
{
_options = options ?? throw new ArgumentNullException(nameof(options));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
@@ -31,7 +31,7 @@ namespace Umbraco.Web.Scheduling
private readonly IContentService _contentService;
private readonly IAuditService _auditService;
private readonly IProfilingLogger _logger;
private readonly IHostingEnvironmentLifetime _hostingEnvironment;
private readonly IApplicationShutdownRegistry _hostingEnvironment;
private readonly IScopeProvider _scopeProvider;
private readonly HealthCheckCollection _healthChecks;
private readonly HealthCheckNotificationMethodCollection _notifications;
@@ -57,7 +57,7 @@ namespace Umbraco.Web.Scheduling
IContentService contentService, IAuditService auditService,
HealthCheckCollection healthChecks, HealthCheckNotificationMethodCollection notifications,
IScopeProvider scopeProvider, IUmbracoContextFactory umbracoContextFactory, IProfilingLogger logger,
IHostingEnvironmentLifetime hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig,
IApplicationShutdownRegistry hostingEnvironment, IHealthChecksSettings healthChecksSettingsConfig,
IIOHelper ioHelper, IServerMessenger serverMessenger, IRequestAccessor requestAccessor,
ILoggingSettings loggingSettings, IKeepAliveSettings keepAliveSettings)
{
@@ -18,10 +18,10 @@ namespace Umbraco.Web.Search
private readonly IndexRebuilder _indexRebuilder;
private readonly IMainDom _mainDom;
private readonly IProfilingLogger _logger;
private readonly IHostingEnvironmentLifetime _hostingEnvironment;
private readonly IApplicationShutdownRegistry _hostingEnvironment;
private static BackgroundTaskRunner<IBackgroundTask> _rebuildOnStartupRunner;
public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IHostingEnvironmentLifetime hostingEnvironment, IndexRebuilder indexRebuilder)
public BackgroundIndexRebuilder(IMainDom mainDom, IProfilingLogger logger, IApplicationShutdownRegistry hostingEnvironment, IndexRebuilder indexRebuilder)
{
_mainDom = mainDom;
_logger = logger;
@@ -42,7 +42,7 @@ namespace Umbraco.ModelsBuilder.Embedded
private static readonly string[] OurFiles = { "models.hash", "models.generated.cs", "all.generated.cs", "all.dll.path", "models.err" };
private readonly IModelsBuilderConfig _config;
private readonly IHostingEnvironmentLifetime _hostingLifetime;
private readonly IApplicationShutdownRegistry _hostingLifetime;
private readonly IIOHelper _ioHelper;
private readonly ModelsGenerationError _errors;
@@ -51,7 +51,7 @@ namespace Umbraco.ModelsBuilder.Embedded
IProfilingLogger logger,
IModelsBuilderConfig config,
IHostingEnvironment hostingEnvironment,
IHostingEnvironmentLifetime hostingLifetime,
IApplicationShutdownRegistry hostingLifetime,
IIOHelper ioHelper)
{
_umbracoServices = umbracoServices;
+1 -1
View File
@@ -128,7 +128,7 @@ namespace Umbraco.Tests.Common
}
public abstract IHostingEnvironment GetHostingEnvironment();
public abstract IHostingEnvironmentLifetime GetHostingEnvironmentLifetime();
public abstract IApplicationShutdownRegistry GetHostingEnvironmentLifetime();
public abstract IIpResolver GetIpResolver();
@@ -5,6 +5,7 @@ using System.Data.SqlClient;
using System.IO;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Umbraco.Core;
using Umbraco.Tests.Integration.Testing;
namespace Umbraco.Tests.Integration.Implementations
@@ -24,7 +24,7 @@ namespace Umbraco.Tests.Integration.Implementations
{
private IBackOfficeInfo _backOfficeInfo;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IHostingEnvironmentLifetime _hostingLifetime;
private readonly IApplicationShutdownRegistry _hostingLifetime;
private readonly IIpResolver _ipResolver;
private readonly IWebHostEnvironment _hostEnvironment;
private readonly IHttpContextAccessor _httpContextAccessor;
@@ -46,7 +46,7 @@ namespace Umbraco.Tests.Integration.Implementations
_hostEnvironment,
_httpContextAccessor);
_hostingLifetime = new AspNetCoreHostingEnvironmentLifetime(Mock.Of<IHostApplicationLifetime>());
_hostingLifetime = new AspNetCoreApplicationShutdownRegistry(Mock.Of<IHostApplicationLifetime>());
Logger = new ProfilingLogger(new ConsoleLogger(new MessageTemplates()), Profiler);
}
@@ -77,7 +77,7 @@ namespace Umbraco.Tests.Integration.Implementations
}
public override IHostingEnvironment GetHostingEnvironment() => _hostingEnvironment;
public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _hostingLifetime;
public override IApplicationShutdownRegistry GetHostingEnvironmentLifetime() => _hostingLifetime;
public override IIpResolver GetIpResolver() => _ipResolver;
@@ -41,7 +41,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
private readonly IEntityXmlSerializer _entitySerializer;
private readonly IVariationContextAccessor _variationContextAccessor;
private readonly IUmbracoContextAccessor _umbracoContextAccessor;
private readonly IHostingEnvironmentLifetime _hostingLifetime;
private readonly IApplicationShutdownRegistry _hostingLifetime;
private readonly IHostingEnvironment _hostingEnvironment;
#region Constructors
@@ -58,7 +58,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
ILogger logger,
IGlobalSettings globalSettings,
IHostingEnvironment hostingEnvironment,
IHostingEnvironmentLifetime hostingLifetime,
IApplicationShutdownRegistry hostingLifetime,
IShortStringHelper shortStringHelper,
ISiteDomainHelper siteDomainHelper,
IEntityXmlSerializer entitySerializer,
@@ -86,7 +86,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
ILogger logger,
IGlobalSettings globalSettings,
IHostingEnvironment hostingEnvironment,
IHostingEnvironmentLifetime hostingLifetime,
IApplicationShutdownRegistry hostingLifetime,
IShortStringHelper shortStringHelper,
ISiteDomainHelper siteDomainHelper,
IEntityXmlSerializer entitySerializer,
@@ -46,7 +46,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
private readonly IMediaRepository _mediaRepository;
private readonly IMemberRepository _memberRepository;
private readonly IEntityXmlSerializer _entitySerializer;
private readonly IHostingEnvironmentLifetime _hostingLifetime;
private readonly IApplicationShutdownRegistry _hostingLifetime;
private readonly IShortStringHelper _shortStringHelper;
private readonly IPublishedSnapshotAccessor _publishedSnapshotAccessor;
private readonly PublishedContentTypeCache _contentTypeCache;
@@ -65,7 +65,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
/// </summary>
/// <remarks>The default constructor will boot the cache, load data from file or database, /// wire events in order to manage changes, etc.</remarks>
public XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache,
IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper)
IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper)
: this(contentTypeService, contentService, scopeProvider, routesCache, contentTypeCache, publishedSnapshotAccessor, mainDom, false, false, documentRepository, mediaRepository, memberRepository, entitySerializer, hostingEnvironment, hostingLifetime, shortStringHelper)
{ }
@@ -74,7 +74,7 @@ namespace Umbraco.Tests.LegacyXmlPublishedCache
// TODO: er, we DO have a DB?
internal XmlStore(IContentTypeService contentTypeService, IContentService contentService, IScopeProvider scopeProvider, RoutesCache routesCache, PublishedContentTypeCache contentTypeCache,
IPublishedSnapshotAccessor publishedSnapshotAccessor, MainDom mainDom,
bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IHostingEnvironmentLifetime hostingLifetime, IShortStringHelper shortStringHelper)
bool testing, bool enableRepositoryEvents, IDocumentRepository documentRepository, IMediaRepository mediaRepository, IMemberRepository memberRepository, IEntityXmlSerializer entitySerializer, IHostingEnvironment hostingEnvironment, IApplicationShutdownRegistry hostingLifetime, IShortStringHelper shortStringHelper)
{
if (testing == false)
EnsureConfigurationIsValid();
@@ -133,7 +133,7 @@ namespace Umbraco.Tests.Runtimes
public override IFactory Configure(IRegister container)
{
container.Register<IHostingEnvironmentLifetime, AspNetHostingLifetime>(Lifetime.Singleton);
container.Register<IApplicationShutdownRegistry, AspNetApplicationShutdownRegistry>(Lifetime.Singleton);
var factory = base.Configure(container);
return factory;
@@ -19,7 +19,7 @@ namespace Umbraco.Tests.Scheduling
public class BackgroundTaskRunnerTests
{
private ILogger _logger;
private IHostingEnvironmentLifetime _hostingEnvironment;
private IApplicationShutdownRegistry _hostingEnvironment;
[OneTimeSetUp]
public void InitializeFixture()
+3 -3
View File
@@ -62,8 +62,8 @@ namespace Umbraco.Tests.TestHelpers
public override IHostingEnvironment GetHostingEnvironment()
=> new AspNetHostingEnvironment(SettingsForTests.GetDefaultHostingSettings());
public override IHostingEnvironmentLifetime GetHostingEnvironmentLifetime()
=> new AspNetHostingLifetime();
public override IApplicationShutdownRegistry GetHostingEnvironmentLifetime()
=> new AspNetApplicationShutdownRegistry();
public override IIpResolver GetIpResolver()
=> new AspNetIpResolver();
@@ -323,7 +323,7 @@ namespace Umbraco.Tests.TestHelpers
public static IHostingEnvironment GetHostingEnvironment() => _testHelperInternal.GetHostingEnvironment();
public static IHostingEnvironmentLifetime GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime();
public static IApplicationShutdownRegistry GetHostingEnvironmentLifetime() => _testHelperInternal.GetHostingEnvironmentLifetime();
public static IIpResolver GetIpResolver() => _testHelperInternal.GetIpResolver();
+1 -1
View File
@@ -140,7 +140,7 @@ namespace Umbraco.Tests.Testing
protected virtual IProfilingLogger ProfilingLogger => Factory.GetInstance<IProfilingLogger>();
protected IHostingEnvironment HostingEnvironment { get; } = new AspNetHostingEnvironment(TestHelpers.SettingsForTests.GetDefaultHostingSettings());
protected IHostingEnvironmentLifetime HostingLifetime { get; } = new AspNetHostingLifetime();
protected IApplicationShutdownRegistry HostingLifetime { get; } = new AspNetApplicationShutdownRegistry();
protected IIpResolver IpResolver => Factory.GetInstance<IIpResolver>();
protected IBackOfficeInfo BackOfficeInfo => Factory.GetInstance<IBackOfficeInfo>();
protected AppCaches AppCaches => Factory.GetInstance<AppCaches>();
@@ -7,13 +7,13 @@ using Umbraco.Core.Hosting;
namespace Umbraco.Web.BackOffice.AspNetCore
{
public class AspNetCoreHostingEnvironmentLifetime : IHostingEnvironmentLifetime
public class AspNetCoreApplicationShutdownRegistry : IApplicationShutdownRegistry
{
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper> _registeredObjects =
new ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper>();
public AspNetCoreHostingEnvironmentLifetime(IHostApplicationLifetime hostApplicationLifetime)
public AspNetCoreApplicationShutdownRegistry(IHostApplicationLifetime hostApplicationLifetime)
{
_hostApplicationLifetime = hostApplicationLifetime;
}
@@ -21,7 +21,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
// Our own netcore implementations
composition.RegisterUnique<IUmbracoApplicationLifetime, AspNetCoreUmbracoApplicationLifetime>();
composition.RegisterUnique<IHostingEnvironmentLifetime, AspNetCoreHostingEnvironmentLifetime>();
composition.RegisterUnique<IApplicationShutdownRegistry, AspNetCoreApplicationShutdownRegistry>();
}
}
}
@@ -27,7 +27,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
if (app == null) throw new ArgumentNullException(nameof(app));
// Register a listener for application shutdown in order to terminate the runtime
var hostLifetime = app.ApplicationServices.GetRequiredService<IHostingEnvironmentLifetime>();
var hostLifetime = app.ApplicationServices.GetRequiredService<IApplicationShutdownRegistry>();
var runtime = app.ApplicationServices.GetRequiredService<IRuntime>();
var runtimeShutdown = new CoreRuntimeShutdown(runtime, hostLifetime);
hostLifetime.RegisterObject(runtimeShutdown);
@@ -43,7 +43,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
/// </summary>
private class CoreRuntimeShutdown : IRegisteredObject
{
public CoreRuntimeShutdown(IRuntime runtime, IHostingEnvironmentLifetime hostLifetime)
public CoreRuntimeShutdown(IRuntime runtime, IApplicationShutdownRegistry hostLifetime)
{
_runtime = runtime;
_hostLifetime = hostLifetime;
@@ -51,7 +51,7 @@ namespace Umbraco.Web.BackOffice.AspNetCore
private bool _completed = false;
private readonly IRuntime _runtime;
private readonly IHostingEnvironmentLifetime _hostLifetime;
private readonly IApplicationShutdownRegistry _hostLifetime;
public void Stop(bool immediate)
{
@@ -6,7 +6,7 @@ using IRegisteredObject = Umbraco.Core.IRegisteredObject;
namespace Umbraco.Web.Hosting
{
public class AspNetHostingLifetime : IHostingEnvironmentLifetime
public class AspNetApplicationShutdownRegistry : IApplicationShutdownRegistry
{
private readonly ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper> _registeredObjects =
new ConcurrentDictionary<IRegisteredObject, RegisteredObjectWrapper>();
+1 -1
View File
@@ -134,7 +134,7 @@
<Compile Include="AppBuilderExtensions.cs" />
<Compile Include="AreaRegistrationContextExtensions.cs" />
<Compile Include="AspNet\AspNetHostingEnvironment.cs" />
<Compile Include="AspNet\AspNetHostingLifetime.cs" />
<Compile Include="AspNet\AspNetApplicationShutdownRegistry.cs" />
<Compile Include="AspNet\AspNetRequestAccessor.cs" />
<Compile Include="AspNet\AspNetSessionManager.cs" />
<Compile Include="AspNet\AspNetUserAgentProvider.cs" />