diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 3722308..37bd7fd 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -15,3 +15,6 @@ ccd9b352d4066839cbe2dff010df6ab464ea871e # Apply dotnet format across the solution. 2fea688003a3947a656d91e0532cd2dff2a737c6 + +# Convert to file-scoped namespaces and drop redundant usings. +f089e7856c50b437f6583ba069a3ed553d1f7d61 diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 0000000..5d022ce --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,14 @@ + + + + latest + enable + latest-recommended + true + $(MSBuildThisFileDirectory)build/Source.ruleset + + + + true + + diff --git a/build/AspNet.ruleset b/build/AspNet.ruleset new file mode 100644 index 0000000..616489e --- /dev/null +++ b/build/AspNet.ruleset @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + diff --git a/build/Source.ruleset b/build/Source.ruleset new file mode 100644 index 0000000..5e7bde7 --- /dev/null +++ b/build/Source.ruleset @@ -0,0 +1,7 @@ + + + + diff --git a/src/AspNetCoreChildLifetimeScope/AspNetCoreChildLifetimeScope.csproj b/src/AspNetCoreChildLifetimeScope/AspNetCoreChildLifetimeScope.csproj index 3bd734b..19edf59 100644 --- a/src/AspNetCoreChildLifetimeScope/AspNetCoreChildLifetimeScope.csproj +++ b/src/AspNetCoreChildLifetimeScope/AspNetCoreChildLifetimeScope.csproj @@ -1,6 +1,7 @@ + ../../build/AspNet.ruleset net10.0 enable diff --git a/src/AspNetCoreExample/AspNetCoreExample.csproj b/src/AspNetCoreExample/AspNetCoreExample.csproj index 3bd734b..19edf59 100644 --- a/src/AspNetCoreExample/AspNetCoreExample.csproj +++ b/src/AspNetCoreExample/AspNetCoreExample.csproj @@ -1,6 +1,7 @@ + ../../build/AspNet.ruleset net10.0 enable diff --git a/src/AspNetCoreExample/Services/IValuesService.cs b/src/AspNetCoreExample/Services/IValuesService.cs index 856028a..d33376e 100644 --- a/src/AspNetCoreExample/Services/IValuesService.cs +++ b/src/AspNetCoreExample/Services/IValuesService.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; - -namespace AspNetCoreExample.Services; +namespace AspNetCoreExample.Services; public interface IValuesService { diff --git a/src/AspNetCoreExample/Services/ValuesService.cs b/src/AspNetCoreExample/Services/ValuesService.cs index 26180cb..6b250b6 100644 --- a/src/AspNetCoreExample/Services/ValuesService.cs +++ b/src/AspNetCoreExample/Services/ValuesService.cs @@ -1,7 +1,4 @@ -using System.Collections.Generic; -using Microsoft.Extensions.Logging; - -namespace AspNetCoreExample.Services; +namespace AspNetCoreExample.Services; public class ValuesService : IValuesService { @@ -14,14 +11,14 @@ public ValuesService(ILogger logger) public IEnumerable FindAll() { - _logger.LogDebug("{method} called", nameof(FindAll)); + _logger.LogDebug("{Method} called", nameof(FindAll)); return new[] { "value1", "value2" }; } public string Find(int id) { - _logger.LogDebug("{method} called with {id}", nameof(Find), id); + _logger.LogDebug("{Method} called with {Id}", nameof(Find), id); return $"value{id}"; } diff --git a/src/AspNetCoreNoStartupExample/AspNetCoreNoStartupExample.csproj b/src/AspNetCoreNoStartupExample/AspNetCoreNoStartupExample.csproj index 3bd734b..19edf59 100644 --- a/src/AspNetCoreNoStartupExample/AspNetCoreNoStartupExample.csproj +++ b/src/AspNetCoreNoStartupExample/AspNetCoreNoStartupExample.csproj @@ -1,6 +1,7 @@ + ../../build/AspNet.ruleset net10.0 enable diff --git a/src/AspNetCoreNoStartupExample/AutofacModule.cs b/src/AspNetCoreNoStartupExample/AutofacModule.cs index 4f48707..3f6cd58 100644 --- a/src/AspNetCoreNoStartupExample/AutofacModule.cs +++ b/src/AspNetCoreNoStartupExample/AutofacModule.cs @@ -1,6 +1,5 @@ using AspNetCoreNoStartupExample.Services; using Autofac; -using Microsoft.Extensions.Logging; namespace AspNetCoreNoStartupExample; diff --git a/src/AspNetCoreNoStartupExample/Services/ValuesService.cs b/src/AspNetCoreNoStartupExample/Services/ValuesService.cs index 9ea4e62..6bfae60 100644 --- a/src/AspNetCoreNoStartupExample/Services/ValuesService.cs +++ b/src/AspNetCoreNoStartupExample/Services/ValuesService.cs @@ -1,6 +1,4 @@ -using Microsoft.Extensions.Logging; - -namespace AspNetCoreNoStartupExample.Services; +namespace AspNetCoreNoStartupExample.Services; public class ValuesService : IValuesService { diff --git a/src/AttributeMetadataExample/AppenderMetadata.cs b/src/AttributeMetadataExample/AppenderMetadata.cs index 879e0e8..6803637 100644 --- a/src/AttributeMetadataExample/AppenderMetadata.cs +++ b/src/AttributeMetadataExample/AppenderMetadata.cs @@ -2,7 +2,7 @@ public class AppenderMetadata { - public string AppenderName + public string? AppenderName { get; set; } diff --git a/src/AttributeMetadataExample/AppenderNameAttribute.cs b/src/AttributeMetadataExample/AppenderNameAttribute.cs index 84b255e..bb8e648 100644 --- a/src/AttributeMetadataExample/AppenderNameAttribute.cs +++ b/src/AttributeMetadataExample/AppenderNameAttribute.cs @@ -1,5 +1,4 @@ -using System; -using System.ComponentModel.Composition; +using System.ComponentModel.Composition; namespace AttributeMetadataExample; diff --git a/src/AttributeMetadataExample/AttributeMetadataAppender.cs b/src/AttributeMetadataExample/AttributeMetadataAppender.cs index d7153aa..191f5ab 100644 --- a/src/AttributeMetadataExample/AttributeMetadataAppender.cs +++ b/src/AttributeMetadataExample/AttributeMetadataAppender.cs @@ -1,6 +1,4 @@ -using System; - -namespace AttributeMetadataExample; +namespace AttributeMetadataExample; [AppenderName("attributed")] public class AttributeMetadataAppender : ILogAppender diff --git a/src/AttributeMetadataExample/InterfaceManualMetadataAdapter.cs b/src/AttributeMetadataExample/InterfaceManualMetadataAdapter.cs index 7b3069e..48ff950 100644 --- a/src/AttributeMetadataExample/InterfaceManualMetadataAdapter.cs +++ b/src/AttributeMetadataExample/InterfaceManualMetadataAdapter.cs @@ -1,6 +1,4 @@ -using System; - -namespace AttributeMetadataExample; +namespace AttributeMetadataExample; public class InterfaceManualMetadataAdapter : ILogAppender { diff --git a/src/AttributeMetadataExample/Log.cs b/src/AttributeMetadataExample/Log.cs index 97feb25..52c0c31 100644 --- a/src/AttributeMetadataExample/Log.cs +++ b/src/AttributeMetadataExample/Log.cs @@ -1,6 +1,4 @@ -using System.Collections.Generic; -using System.Linq; -using Autofac.Features.Metadata; +using Autofac.Features.Metadata; namespace AttributeMetadataExample; @@ -15,7 +13,7 @@ public Log(IEnumerable> appenders) public void Write(string destination, string message) { - var appender = _appenders.First(a => a.Metadata["AppenderName"].Equals(destination)); + var appender = _appenders.First(a => destination.Equals(a.Metadata["AppenderName"])); appender.Value.Write(message); } } diff --git a/src/AttributeMetadataExample/Program.cs b/src/AttributeMetadataExample/Program.cs index 5e03821..653eb10 100644 --- a/src/AttributeMetadataExample/Program.cs +++ b/src/AttributeMetadataExample/Program.cs @@ -1,5 +1,4 @@ -using System; -using System.Diagnostics; +using System.Diagnostics; using Autofac; using Autofac.Extras.AttributeMetadata; using Autofac.Features.AttributeFilters; diff --git a/src/AttributeMetadataExample/StringManualMetadataAppender.cs b/src/AttributeMetadataExample/StringManualMetadataAppender.cs index f94015c..a4ae935 100644 --- a/src/AttributeMetadataExample/StringManualMetadataAppender.cs +++ b/src/AttributeMetadataExample/StringManualMetadataAppender.cs @@ -1,6 +1,4 @@ -using System; - -namespace AttributeMetadataExample; +namespace AttributeMetadataExample; public class StringManualMetadataAppender : ILogAppender { diff --git a/src/AttributeMetadataExample/TypedManualMetadataAppender.cs b/src/AttributeMetadataExample/TypedManualMetadataAppender.cs index 9396c01..ebbee62 100644 --- a/src/AttributeMetadataExample/TypedManualMetadataAppender.cs +++ b/src/AttributeMetadataExample/TypedManualMetadataAppender.cs @@ -1,6 +1,4 @@ -using System; - -namespace AttributeMetadataExample; +namespace AttributeMetadataExample; public class TypedManualMetadataAppender : ILogAppender { diff --git a/src/ConfigurationExample/Program.cs b/src/ConfigurationExample/Program.cs index a032989..4bbbccd 100644 --- a/src/ConfigurationExample/Program.cs +++ b/src/ConfigurationExample/Program.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; +using System.Diagnostics; using System.Reflection; using System.Runtime.Loader; using Autofac; @@ -35,7 +32,7 @@ public static void Main() // https://github.com/dotnet/core-setup/blob/master/Documentation/design-docs/corehost.md // // To verify, try commenting this out and you'll see that the config system can't load the external plugin type. - var executionFolder = Path.GetDirectoryName(typeof(Program).Assembly.Location); + var executionFolder = Path.GetDirectoryName(typeof(Program).Assembly.Location) ?? AppContext.BaseDirectory; AssemblyLoadContext.Default.Resolving += (AssemblyLoadContext context, AssemblyName assembly) => context.LoadFromAssemblyPath(Path.Combine(executionFolder, $"{assembly.Name}.dll")); var config = new ConfigurationBuilder() diff --git a/src/ConfigurationExampleInterface/IPlugin.cs b/src/ConfigurationExampleInterface/IPlugin.cs index 3bb6f82..63bf83b 100644 --- a/src/ConfigurationExampleInterface/IPlugin.cs +++ b/src/ConfigurationExampleInterface/IPlugin.cs @@ -1,20 +1,19 @@ -namespace ConfigurationExampleInterface +namespace ConfigurationExampleInterface; + +/// +/// Simple plugin interface used to illustrate assembly loading/plugin handling +/// via configuration. See the "ConfigurationExample" project for usage. +/// +public interface IPlugin { /// - /// Simple plugin interface used to illustrate assembly loading/plugin handling - /// via configuration. See the "ConfigurationExample" project for usage. + /// Gets the name of the plugin. /// - public interface IPlugin + /// + /// A with the plugin name. Likely just the type name for illustrative purposes. + /// + string Name { - /// - /// Gets the name of the plugin. - /// - /// - /// A with the plugin name. Likely just the type name for illustrative purposes. - /// - string Name - { - get; - } + get; } } diff --git a/src/ConfigurationExamplePlugin/ExternalPlugin.cs b/src/ConfigurationExamplePlugin/ExternalPlugin.cs index f77aea6..47c54ca 100644 --- a/src/ConfigurationExamplePlugin/ExternalPlugin.cs +++ b/src/ConfigurationExamplePlugin/ExternalPlugin.cs @@ -1,25 +1,24 @@ using ConfigurationExampleInterface; -namespace ConfigurationExamplePlugin +namespace ConfigurationExamplePlugin; + +/// +/// Implementation of the plugin interface that will be loaded from an external assembly. See the "ConfigurationExample" +/// project for more details. +/// +public class ExternalPlugin : IPlugin { /// - /// Implementation of the plugin interface that will be loaded from an external assembly. See the "ConfigurationExample" - /// project for more details. + /// Gets the name of the plugin. /// - public class ExternalPlugin : IPlugin + /// + /// Always returns ExternalPlugin. + /// + public string Name { - /// - /// Gets the name of the plugin. - /// - /// - /// Always returns ExternalPlugin. - /// - public string Name + get { - get - { - return "ExternalPlugin"; - } + return "ExternalPlugin"; } } } diff --git a/src/GenericHostBuilderExample/HostedService.cs b/src/GenericHostBuilderExample/HostedService.cs index 764fa59..37fc84e 100644 --- a/src/GenericHostBuilderExample/HostedService.cs +++ b/src/GenericHostBuilderExample/HostedService.cs @@ -1,14 +1,11 @@ -using System.Threading; -using System.Threading.Tasks; -using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Hosting; namespace GenericHostBuilderExample; -internal class HostedService : IHostedService +internal sealed class HostedService : IHostedService { private readonly ILogger _logger; - // ReSharper disable once UnusedMember.Global public HostedService(ILogger logger) { _logger = logger; diff --git a/src/GenericHostBuilderExample/ILogger.cs b/src/GenericHostBuilderExample/ILogger.cs index 163e00f..db7d410 100644 --- a/src/GenericHostBuilderExample/ILogger.cs +++ b/src/GenericHostBuilderExample/ILogger.cs @@ -1,6 +1,4 @@ -using System.Threading.Tasks; - -namespace GenericHostBuilderExample; +namespace GenericHostBuilderExample; internal interface ILogger { diff --git a/src/GenericHostBuilderExample/Logger.cs b/src/GenericHostBuilderExample/Logger.cs index 386fe3d..de0ee4b 100644 --- a/src/GenericHostBuilderExample/Logger.cs +++ b/src/GenericHostBuilderExample/Logger.cs @@ -1,9 +1,6 @@ -using System; -using System.Threading.Tasks; +namespace GenericHostBuilderExample; -namespace GenericHostBuilderExample; - -internal class Logger : ILogger +internal sealed class Logger : ILogger { public async Task Log(string value) { diff --git a/src/GenericHostBuilderExample/Program.cs b/src/GenericHostBuilderExample/Program.cs index ab016e5..96a3c1d 100644 --- a/src/GenericHostBuilderExample/Program.cs +++ b/src/GenericHostBuilderExample/Program.cs @@ -1,5 +1,4 @@ -using System.Threading.Tasks; -using Autofac; +using Autofac; using Autofac.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; diff --git a/src/MultitenantExample.ConsoleApplication/BaseDependency.cs b/src/MultitenantExample.ConsoleApplication/BaseDependency.cs index 80ff211..40208ab 100644 --- a/src/MultitenantExample.ConsoleApplication/BaseDependency.cs +++ b/src/MultitenantExample.ConsoleApplication/BaseDependency.cs @@ -1,6 +1,4 @@ -using System; - -namespace MultitenantExample.ConsoleApplication; +namespace MultitenantExample.ConsoleApplication; /// /// Base class for dependencies. Used simply to avoid redundant code; it's not diff --git a/src/MultitenantExample.ConsoleApplication/IDependency.cs b/src/MultitenantExample.ConsoleApplication/IDependency.cs index 3ee933b..3337134 100644 --- a/src/MultitenantExample.ConsoleApplication/IDependency.cs +++ b/src/MultitenantExample.ConsoleApplication/IDependency.cs @@ -1,6 +1,4 @@ -using System; - -namespace MultitenantExample.ConsoleApplication; +namespace MultitenantExample.ConsoleApplication; /// /// Demonstration dependency interface that allows you to inspect the unique diff --git a/src/MultitenantExample.ConsoleApplication/ManualTenantIdentificationStrategy.cs b/src/MultitenantExample.ConsoleApplication/ManualTenantIdentificationStrategy.cs index 0aadfeb..14a9fa7 100644 --- a/src/MultitenantExample.ConsoleApplication/ManualTenantIdentificationStrategy.cs +++ b/src/MultitenantExample.ConsoleApplication/ManualTenantIdentificationStrategy.cs @@ -25,7 +25,7 @@ public class ManualTenantIdentificationStrategy : ITenantIdentificationStrategy /// /// when the current tenant ID is requested. /// - public object CurrentTenantId + public object? CurrentTenantId { get; set; } @@ -38,9 +38,9 @@ public object CurrentTenantId /// /// This implementation always returns . /// - public bool TryIdentifyTenant(out object tenantId) + public bool TryIdentifyTenant(out object? tenantId) { - if (CurrentTenantId.ToString() == "0") + if (CurrentTenantId?.ToString() == "0") { // 0 is the "default tenant ID" tenantId = null; diff --git a/src/MultitenantExample.ConsoleApplication/Program.cs b/src/MultitenantExample.ConsoleApplication/Program.cs index f7c2059..f735316 100644 --- a/src/MultitenantExample.ConsoleApplication/Program.cs +++ b/src/MultitenantExample.ConsoleApplication/Program.cs @@ -1,5 +1,4 @@ -using System; -using Autofac; +using Autofac; using Autofac.Multitenant; namespace MultitenantExample.ConsoleApplication; @@ -18,26 +17,20 @@ namespace MultitenantExample.ConsoleApplication; public class Program { /// - /// The container from which dependencies will be resolved. + /// Strategy used for identifying the current tenant with multitenant DI. /// - private static IContainer _container; + private static readonly ManualTenantIdentificationStrategy _tenantIdentifier = new(); /// - /// Strategy used for identifying the current tenant with multitenant DI. + /// The container from which dependencies will be resolved. /// - private static ManualTenantIdentificationStrategy _tenantIdentifier; + private static readonly MultitenantContainer _container = ConfigureDependencies(_tenantIdentifier); /// /// Demo program entry point. /// public static void Main() { - // Initialize the tenant identification strategy. - _tenantIdentifier = new ManualTenantIdentificationStrategy(); - - // Set the application container to the multitenant container. - _container = ConfigureDependencies(); - // Explain what you're looking at. WriteInstructions(); @@ -48,7 +41,7 @@ public static void Main() /// /// Configures the multitenant dependency container. /// - private static IContainer ConfigureDependencies() + private static MultitenantContainer ConfigureDependencies(ManualTenantIdentificationStrategy tenantIdentifier) { // Register default dependencies in the application container. var builder = new ContainerBuilder(); @@ -57,7 +50,7 @@ private static IContainer ConfigureDependencies() var appContainer = builder.Build(); // Create the multitenant container. - var mtc = new MultitenantContainer(_tenantIdentifier, appContainer); + var mtc = new MultitenantContainer(tenantIdentifier, appContainer); // Configure overrides for tenant 1. Tenant 1 registers their dependencies // as instance-per-dependency. diff --git a/src/MultitenantExample.MvcApplication/Controllers/HomeController.cs b/src/MultitenantExample.MvcApplication/Controllers/HomeController.cs index 85ff789..2d11d75 100644 --- a/src/MultitenantExample.MvcApplication/Controllers/HomeController.cs +++ b/src/MultitenantExample.MvcApplication/Controllers/HomeController.cs @@ -5,72 +5,73 @@ using MultitenantExample.MvcApplication.WcfMetadataConsumer; using MultitenantExample.MvcApplication.WcfService; -namespace MultitenantExample.MvcApplication.Controllers +namespace MultitenantExample.MvcApplication.Controllers; + +[HandleError] +public class HomeController : Controller { - [HandleError] - public class HomeController : Controller + public HomeController(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy, IMultitenantService standardService, IMetadataConsumer metadataService) { - public HomeController(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy, IMultitenantService standardService, IMetadataConsumer metadataService) - { - Dependency = dependency; - TenantIdentificationStrategy = tenantIdStrategy; - StandardServiceProxy = standardService; - MetadataServiceProxy = metadataService; - } + Dependency = dependency; + TenantIdentificationStrategy = tenantIdStrategy; + StandardServiceProxy = standardService; + MetadataServiceProxy = metadataService; + } - public IDependency Dependency - { - get; set; - } + public IDependency Dependency + { + get; set; + } - public IMetadataConsumer MetadataServiceProxy - { - get; set; - } + public IMetadataConsumer MetadataServiceProxy + { + get; set; + } - public IMultitenantService StandardServiceProxy - { - get; set; - } + public IMultitenantService StandardServiceProxy + { + get; set; + } - public ITenantIdentificationStrategy TenantIdentificationStrategy - { - get; set; - } + public ITenantIdentificationStrategy TenantIdentificationStrategy + { + get; set; + } - public ActionResult About() - { - return View(); - } + [HttpGet] + public ActionResult About() + { + return View(); + } - public virtual ActionResult Index() - { - var model = BuildIndexModel(); - return View(model); - } + [HttpGet] + public virtual ActionResult Index() + { + var model = BuildIndexModel(); + return View(model); + } - protected virtual IndexModel BuildIndexModel() + protected virtual IndexModel BuildIndexModel() + { + var model = new IndexModel() { - var model = new IndexModel() - { - ControllerTypeName = GetType().Name, - DependencyInstanceId = Dependency.InstanceId, - DependencyTypeName = Dependency.GetType().Name, - TenantId = GetTenantId(), - StandardServiceInfo = StandardServiceProxy.GetServiceInfo(new MultitenantExample.MvcApplication.WcfService.GetServiceInfoRequest()), - MetadataServiceInfo = MetadataServiceProxy.GetServiceInfo(new MultitenantExample.MvcApplication.WcfMetadataConsumer.GetServiceInfoRequest()) - }; - return model; - } + ControllerTypeName = GetType().Name, + DependencyInstanceId = Dependency.InstanceId, + DependencyTypeName = Dependency.GetType().Name, + TenantId = GetTenantId(), + StandardServiceInfo = StandardServiceProxy.GetServiceInfo(new MultitenantExample.MvcApplication.WcfService.GetServiceInfoRequest()), + MetadataServiceInfo = MetadataServiceProxy.GetServiceInfo(new MultitenantExample.MvcApplication.WcfMetadataConsumer.GetServiceInfoRequest()) + }; + return model; + } - private object GetTenantId() + private object GetTenantId() + { + var success = TenantIdentificationStrategy.TryIdentifyTenant(out var tenantId); + if (!success || tenantId == null) { - var success = TenantIdentificationStrategy.TryIdentifyTenant(out var tenantId); - if (!success || tenantId == null) - { - return "[Default Tenant]"; - } - return tenantId; + return "[Default Tenant]"; } + return tenantId; } } diff --git a/src/MultitenantExample.MvcApplication/Controllers/Tenant1Controller.cs b/src/MultitenantExample.MvcApplication/Controllers/Tenant1Controller.cs index 6571c53..bc25954 100644 --- a/src/MultitenantExample.MvcApplication/Controllers/Tenant1Controller.cs +++ b/src/MultitenantExample.MvcApplication/Controllers/Tenant1Controller.cs @@ -3,29 +3,28 @@ using MultitenantExample.MvcApplication.WcfMetadataConsumer; using MultitenantExample.MvcApplication.WcfService; -namespace MultitenantExample.MvcApplication.Controllers +namespace MultitenantExample.MvcApplication.Controllers; + +/// +/// Example of a tenant-specific controller for Tenant 1. +/// +/// +/// +/// You have to derive custom controllers from the original controller because +/// you have to register them as the base controller type. +/// +/// +public class Tenant1Controller : HomeController { - /// - /// Example of a tenant-specific controller for Tenant 1. - /// - /// - /// - /// You have to derive custom controllers from the original controller because - /// you have to register them as the base controller type. - /// - /// - public class Tenant1Controller : HomeController + public Tenant1Controller(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy, IMultitenantService standardService, IMetadataConsumer metadataService) + : base(dependency, tenantIdStrategy, standardService, metadataService) { - public Tenant1Controller(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy, IMultitenantService standardService, IMetadataConsumer metadataService) - : base(dependency, tenantIdStrategy, standardService, metadataService) - { - } + } - protected override Models.IndexModel BuildIndexModel() - { - var model = base.BuildIndexModel(); - model.ControllerTypeName += " [This is custom text inserted by the Tenant 1 controller.]"; - return model; - } + protected override Models.IndexModel BuildIndexModel() + { + var model = base.BuildIndexModel(); + model.ControllerTypeName += " [This is custom text inserted by the Tenant 1 controller.]"; + return model; } } diff --git a/src/MultitenantExample.MvcApplication/Controllers/Tenant2Controller.cs b/src/MultitenantExample.MvcApplication/Controllers/Tenant2Controller.cs index 710db16..112fdc6 100644 --- a/src/MultitenantExample.MvcApplication/Controllers/Tenant2Controller.cs +++ b/src/MultitenantExample.MvcApplication/Controllers/Tenant2Controller.cs @@ -3,29 +3,28 @@ using MultitenantExample.MvcApplication.WcfMetadataConsumer; using MultitenantExample.MvcApplication.WcfService; -namespace MultitenantExample.MvcApplication.Controllers +namespace MultitenantExample.MvcApplication.Controllers; + +/// +/// Example of a tenant-specific controller for Tenant 2. +/// +/// +/// +/// You have to derive custom controllers from the original controller because +/// you have to register them as the base controller type. +/// +/// +public class Tenant2Controller : HomeController { - /// - /// Example of a tenant-specific controller for Tenant 2. - /// - /// - /// - /// You have to derive custom controllers from the original controller because - /// you have to register them as the base controller type. - /// - /// - public class Tenant2Controller : HomeController + public Tenant2Controller(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy, IMultitenantService standardService, IMetadataConsumer metadataService) + : base(dependency, tenantIdStrategy, standardService, metadataService) { - public Tenant2Controller(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy, IMultitenantService standardService, IMetadataConsumer metadataService) - : base(dependency, tenantIdStrategy, standardService, metadataService) - { - } + } - protected override Models.IndexModel BuildIndexModel() - { - var model = base.BuildIndexModel(); - model.ControllerTypeName += " [Here is something custom done by the Tenant 2 controller.]"; - return model; - } + protected override Models.IndexModel BuildIndexModel() + { + var model = base.BuildIndexModel(); + model.ControllerTypeName += " [Here is something custom done by the Tenant 2 controller.]"; + return model; } } diff --git a/src/MultitenantExample.MvcApplication/Dependencies/BaseDependency.cs b/src/MultitenantExample.MvcApplication/Dependencies/BaseDependency.cs index 5345c87..4ab154b 100644 --- a/src/MultitenantExample.MvcApplication/Dependencies/BaseDependency.cs +++ b/src/MultitenantExample.MvcApplication/Dependencies/BaseDependency.cs @@ -1,31 +1,30 @@ using System; -namespace MultitenantExample.MvcApplication.Dependencies +namespace MultitenantExample.MvcApplication.Dependencies; + +/// +/// Base class for dependencies. Used simply to avoid redundant code; it's not +/// actually required to have a common derivation chain. +/// +public class BaseDependency : IDependency { /// - /// Base class for dependencies. Used simply to avoid redundant code; it's not - /// actually required to have a common derivation chain. + /// Initializes a new instance of the class. /// - public class BaseDependency : IDependency + public BaseDependency() { - /// - /// Initializes a new instance of the class. - /// - public BaseDependency() - { - InstanceId = Guid.NewGuid(); - } + InstanceId = Guid.NewGuid(); + } - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - public Guid InstanceId - { - get; private set; - } + /// + /// Gets the unique instance ID for the dependency. + /// + /// + /// A that indicates the unique ID for the + /// instance. + /// + public Guid InstanceId + { + get; private set; } } diff --git a/src/MultitenantExample.MvcApplication/Dependencies/DefaultTenantDependency.cs b/src/MultitenantExample.MvcApplication/Dependencies/DefaultTenantDependency.cs index 7fc09cc..f4e175a 100644 --- a/src/MultitenantExample.MvcApplication/Dependencies/DefaultTenantDependency.cs +++ b/src/MultitenantExample.MvcApplication/Dependencies/DefaultTenantDependency.cs @@ -1,9 +1,8 @@ -namespace MultitenantExample.MvcApplication.Dependencies +namespace MultitenantExample.MvcApplication.Dependencies; + +/// +/// Tenant-specific dependency for the default tenant. +/// +public class DefaultTenantDependency : BaseDependency { - /// - /// Tenant-specific dependency for the default tenant. - /// - public class DefaultTenantDependency : BaseDependency - { - } } diff --git a/src/MultitenantExample.MvcApplication/Dependencies/IDependency.cs b/src/MultitenantExample.MvcApplication/Dependencies/IDependency.cs index 9905a33..22bc6bc 100644 --- a/src/MultitenantExample.MvcApplication/Dependencies/IDependency.cs +++ b/src/MultitenantExample.MvcApplication/Dependencies/IDependency.cs @@ -1,23 +1,22 @@ using System; -namespace MultitenantExample.MvcApplication.Dependencies +namespace MultitenantExample.MvcApplication.Dependencies; + +/// +/// Demonstration dependency interface that allows you to inspect the unique +/// ID on a specific resolved instance of the dependency. +/// +public interface IDependency { /// - /// Demonstration dependency interface that allows you to inspect the unique - /// ID on a specific resolved instance of the dependency. + /// Gets the unique instance ID for the dependency. /// - public interface IDependency + /// + /// A that indicates the unique ID for the + /// instance. + /// + Guid InstanceId { - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - Guid InstanceId - { - get; - } + get; } } diff --git a/src/MultitenantExample.MvcApplication/Dependencies/Tenant1Dependency.cs b/src/MultitenantExample.MvcApplication/Dependencies/Tenant1Dependency.cs index 1c980dd..2c5f341 100644 --- a/src/MultitenantExample.MvcApplication/Dependencies/Tenant1Dependency.cs +++ b/src/MultitenantExample.MvcApplication/Dependencies/Tenant1Dependency.cs @@ -1,9 +1,8 @@ -namespace MultitenantExample.MvcApplication.Dependencies +namespace MultitenantExample.MvcApplication.Dependencies; + +/// +/// Tenant-specific dependency for Tenant 1. +/// +public class Tenant1Dependency : BaseDependency { - /// - /// Tenant-specific dependency for Tenant 1. - /// - public class Tenant1Dependency : BaseDependency - { - } } diff --git a/src/MultitenantExample.MvcApplication/Dependencies/Tenant2Dependency.cs b/src/MultitenantExample.MvcApplication/Dependencies/Tenant2Dependency.cs index 9abee16..3d91d98 100644 --- a/src/MultitenantExample.MvcApplication/Dependencies/Tenant2Dependency.cs +++ b/src/MultitenantExample.MvcApplication/Dependencies/Tenant2Dependency.cs @@ -1,9 +1,8 @@ -namespace MultitenantExample.MvcApplication.Dependencies +namespace MultitenantExample.MvcApplication.Dependencies; + +/// +/// Tenant-specific dependency for Tenant 2. +/// +public class Tenant2Dependency : BaseDependency { - /// - /// Tenant-specific dependency for Tenant 2. - /// - public class Tenant2Dependency : BaseDependency - { - } } diff --git a/src/MultitenantExample.MvcApplication/Global.asax.cs b/src/MultitenantExample.MvcApplication/Global.asax.cs index 794daa9..4cffc2e 100644 --- a/src/MultitenantExample.MvcApplication/Global.asax.cs +++ b/src/MultitenantExample.MvcApplication/Global.asax.cs @@ -11,124 +11,123 @@ using MultitenantExample.MvcApplication.WcfMetadataConsumer; using MultitenantExample.MvcApplication.WcfService; -namespace MultitenantExample.MvcApplication +namespace MultitenantExample.MvcApplication; + +/// +/// Global application class for the multitenant MVC example application. +/// +public class MvcApplication : HttpApplication { /// - /// Global application class for the multitenant MVC example application. + /// Registers the application routes with a route collection. + /// + /// + /// The route collection with which to register routes. + /// + /// + /// + /// This is part of standard MVC application setup. + /// + /// + public static void RegisterRoutes(RouteCollection routes) + { + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + + routes.MapRoute( + "Default", // Route name + "{controller}/{action}/{id}", // URL with parameters + new + { + controller = "Home", + action = "Index", + id = UrlParameter.Optional + } // Parameter defaults + ); + + } + + /// + /// Handles the global application startup event. /// - public class MvcApplication : HttpApplication + protected static void Application_Start() { - /// - /// Registers the application routes with a route collection. - /// - /// - /// The route collection with which to register routes. - /// - /// - /// - /// This is part of standard MVC application setup. - /// - /// - public static void RegisterRoutes(RouteCollection routes) + // Register application-level dependencies and controllers. Note that + // we are manually registering controllers rather than all at the same + // time because some of the controllers in this sample application + // are for specific tenants. + var builder = new ContainerBuilder(); + builder.RegisterType(); + builder.RegisterType().As(); + + // Create the tenant ID strategy. Required for multitenant integration. + var tenantIdStrategy = new RequestParameterStrategy(); + + // Adding the tenant ID strategy into the container so controllers + // can display output about the current tenant. + builder.RegisterInstance(tenantIdStrategy).As(); + + // The next couple of registrations - for the channel factory and channel + // to WCF services - show how to consume multitenant WCF services. + + // The service client is not different per tenant because + // the service itself is multitenant - one client for all + // the tenants and the service implementation switches. + builder.Register(c => new ChannelFactory(new BasicHttpBinding(), new EndpointAddress("http://localhost:63578/MultitenantService.svc"))).SingleInstance(); + builder.Register(c => new ChannelFactory(new WSHttpBinding(), new EndpointAddress("http://localhost:63578/MetadataConsumer.svc"))).SingleInstance(); + + // Register an endpoint behavior on the client channel factory that + // will propagate the tenant ID across the wire in a message header. + // On the service side, you'll need to read the header from incoming + // message headers to reconstitute the incoming tenant ID. + builder.Register(c => { - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); - - routes.MapRoute( - "Default", // Route name - "{controller}/{action}/{id}", // URL with parameters - new - { - controller = "Home", - action = "Index", - id = UrlParameter.Optional - } // Parameter defaults - ); - - } - - /// - /// Handles the global application startup event. - /// - protected void Application_Start() + var factory = c.Resolve>(); + factory.Opening += (sender, args) => factory.Endpoint.Behaviors.Add(new TenantPropagationBehavior(tenantIdStrategy)); + return factory.CreateChannel(); + }).InstancePerRequest(); + builder.Register(c => { - // Register application-level dependencies and controllers. Note that - // we are manually registering controllers rather than all at the same - // time because some of the controllers in this sample application - // are for specific tenants. - var builder = new ContainerBuilder(); - builder.RegisterType(); - builder.RegisterType().As(); - - // Create the tenant ID strategy. Required for multitenant integration. - var tenantIdStrategy = new RequestParameterStrategy(); - - // Adding the tenant ID strategy into the container so controllers - // can display output about the current tenant. - builder.RegisterInstance(tenantIdStrategy).As(); - - // The next couple of registrations - for the channel factory and channel - // to WCF services - show how to consume multitenant WCF services. - - // The service client is not different per tenant because - // the service itself is multitenant - one client for all - // the tenants and the service implementation switches. - builder.Register(c => new ChannelFactory(new BasicHttpBinding(), new EndpointAddress("http://localhost:63578/MultitenantService.svc"))).SingleInstance(); - builder.Register(c => new ChannelFactory(new WSHttpBinding(), new EndpointAddress("http://localhost:63578/MetadataConsumer.svc"))).SingleInstance(); - - // Register an endpoint behavior on the client channel factory that - // will propagate the tenant ID across the wire in a message header. - // On the service side, you'll need to read the header from incoming - // message headers to reconstitute the incoming tenant ID. - builder.Register(c => + var factory = c.Resolve>(); + factory.Opening += (sender, args) => factory.Endpoint.Behaviors.Add(new TenantPropagationBehavior(tenantIdStrategy)); + return factory.CreateChannel(); + }).InstancePerRequest(); + + // Create the multitenant container based on the application + // defaults - here's where the multitenant bits truly come into play. + var mtc = new MultitenantContainer(tenantIdStrategy, builder.Build()); + + // Notice we configure tenant IDs as strings below because the tenant + // identification strategy retrieves string values from the request + // context. To use strongly-typed tenant IDs, create a custom tenant + // identification strategy that returns the appropriate type. + + // Configure overrides for tenant 1 - dependencies, controllers, etc. + mtc.ConfigureTenant("1", + b => { - var factory = c.Resolve>(); - factory.Opening += (sender, args) => factory.Endpoint.Behaviors.Add(new TenantPropagationBehavior(tenantIdStrategy)); - return factory.CreateChannel(); - }).InstancePerRequest(); - builder.Register(c => + b.RegisterType().As().InstancePerDependency(); + b.RegisterType().As(); + }); + + // Configure overrides for tenant 2 - dependencies, controllers, etc. + mtc.ConfigureTenant("2", + b => { - var factory = c.Resolve>(); - factory.Opening += (sender, args) => factory.Endpoint.Behaviors.Add(new TenantPropagationBehavior(tenantIdStrategy)); - return factory.CreateChannel(); - }).InstancePerRequest(); - - // Create the multitenant container based on the application - // defaults - here's where the multitenant bits truly come into play. - var mtc = new MultitenantContainer(tenantIdStrategy, builder.Build()); - - // Notice we configure tenant IDs as strings below because the tenant - // identification strategy retrieves string values from the request - // context. To use strongly-typed tenant IDs, create a custom tenant - // identification strategy that returns the appropriate type. - - // Configure overrides for tenant 1 - dependencies, controllers, etc. - mtc.ConfigureTenant("1", - b => - { - b.RegisterType().As().InstancePerDependency(); - b.RegisterType().As(); - }); - - // Configure overrides for tenant 2 - dependencies, controllers, etc. - mtc.ConfigureTenant("2", - b => - { - b.RegisterType().As().SingleInstance(); - b.RegisterType().As(); - }); - - // Configure overrides for the default tenant. That means the default - // tenant will have some different dependencies than other unconfigured - // tenants. - mtc.ConfigureTenant(null, b => b.RegisterType().As().SingleInstance()); - - // Create the dependency resolver using the - // multitenant container instead of the application container. - DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc)); - - // Perform the standard MVC setup requirements. - AreaRegistration.RegisterAllAreas(); - RegisterRoutes(RouteTable.Routes); - } + b.RegisterType().As().SingleInstance(); + b.RegisterType().As(); + }); + + // Configure overrides for the default tenant. That means the default + // tenant will have some different dependencies than other unconfigured + // tenants. + mtc.ConfigureTenant(null, b => b.RegisterType().As().SingleInstance()); + + // Create the dependency resolver using the + // multitenant container instead of the application container. + DependencyResolver.SetResolver(new AutofacDependencyResolver(mtc)); + + // Perform the standard MVC setup requirements. + AreaRegistration.RegisterAllAreas(); + RegisterRoutes(RouteTable.Routes); } } diff --git a/src/MultitenantExample.MvcApplication/Models/IndexModel.cs b/src/MultitenantExample.MvcApplication/Models/IndexModel.cs index 7476401..63921a2 100644 --- a/src/MultitenantExample.MvcApplication/Models/IndexModel.cs +++ b/src/MultitenantExample.MvcApplication/Models/IndexModel.cs @@ -1,81 +1,80 @@ using System; -namespace MultitenantExample.MvcApplication.Models +namespace MultitenantExample.MvcApplication.Models; + +/// +/// Model used on the main index view to display information about the current +/// dependency settings. +/// +public class IndexModel { /// - /// Model used on the main index view to display information about the current - /// dependency settings. + /// Gets or sets the tenant ID to display. /// - public class IndexModel + /// + /// A that represents the current tenant ID. + /// + public object? TenantId { - /// - /// Gets or sets the tenant ID to display. - /// - /// - /// A that represents the current tenant ID. - /// - public object TenantId - { - get; set; - } + get; set; + } - /// - /// Gets or sets the controller type name. - /// - /// - /// A with the controller type name to display. - /// - public string ControllerTypeName - { - get; set; - } + /// + /// Gets or sets the controller type name. + /// + /// + /// A with the controller type name to display. + /// + public string? ControllerTypeName + { + get; set; + } - /// - /// Gets or sets the dependency type name. - /// - /// - /// A with the dependency type name to display. - /// - public string DependencyTypeName - { - get; set; - } + /// + /// Gets or sets the dependency type name. + /// + /// + /// A with the dependency type name to display. + /// + public string? DependencyTypeName + { + get; set; + } - /// - /// Gets or sets the dependency instance ID. - /// - /// - /// A that indicates the unique ID for the dependency instance. - /// - public Guid DependencyInstanceId - { - get; set; - } + /// + /// Gets or sets the dependency instance ID. + /// + /// + /// A that indicates the unique ID for the dependency instance. + /// + public Guid DependencyInstanceId + { + get; set; + } - /// - /// Gets or sets the WCF service information for the service that consumes - /// a metadata buddy class. - /// - /// - /// A - /// containing information retrieved from the multitenant WCF service. - /// - public WcfMetadataConsumer.GetServiceInfoResponse MetadataServiceInfo - { - get; set; - } + /// + /// Gets or sets the WCF service information for the service that consumes + /// a metadata buddy class. + /// + /// + /// A + /// containing information retrieved from the multitenant WCF service. + /// + public WcfMetadataConsumer.GetServiceInfoResponse? MetadataServiceInfo + { + get; set; + } - /// - /// Gets or sets the WCF service information for the service that doesn't - /// use a metadata buddy class. - /// - /// - /// A - /// containing information retrieved from the multitenant WCF service. - /// - public WcfService.GetServiceInfoResponse StandardServiceInfo - { - get; set; - } + /// + /// Gets or sets the WCF service information for the service that doesn't + /// use a metadata buddy class. + /// + /// + /// A + /// containing information retrieved from the multitenant WCF service. + /// + public WcfService.GetServiceInfoResponse? StandardServiceInfo + { + get; set; } } diff --git a/src/MultitenantExample.MvcApplication/MultitenantExample.MvcApplication.csproj b/src/MultitenantExample.MvcApplication/MultitenantExample.MvcApplication.csproj index e216e61..97745d1 100644 --- a/src/MultitenantExample.MvcApplication/MultitenantExample.MvcApplication.csproj +++ b/src/MultitenantExample.MvcApplication/MultitenantExample.MvcApplication.csproj @@ -1,5 +1,6 @@  + ../../build/AspNet.ruleset net481 Library bin/ diff --git a/src/MultitenantExample.MvcApplication/RequestParameterStrategy.cs b/src/MultitenantExample.MvcApplication/RequestParameterStrategy.cs index 986ddbb..a93ddcc 100644 --- a/src/MultitenantExample.MvcApplication/RequestParameterStrategy.cs +++ b/src/MultitenantExample.MvcApplication/RequestParameterStrategy.cs @@ -1,28 +1,27 @@ using System.Web; using Autofac.Multitenant; -namespace MultitenantExample.MvcApplication +namespace MultitenantExample.MvcApplication; + +public class RequestParameterStrategy : ITenantIdentificationStrategy { - public class RequestParameterStrategy : ITenantIdentificationStrategy + public bool TryIdentifyTenant(out object? tenantId) { - public bool TryIdentifyTenant(out object tenantId) + // This is an EXAMPLE ONLY and is NOT RECOMMENDED. + tenantId = null; + try { - // This is an EXAMPLE ONLY and is NOT RECOMMENDED. - tenantId = null; - try - { - var context = HttpContext.Current; - if (context != null && context.Request != null) - { - tenantId = context.Request.Params["tenant"]; - } - } - catch (HttpException) + var context = HttpContext.Current; + if (context != null && context.Request != null) { - // Happens at app startup in IIS 7.0 + tenantId = context.Request.Params["tenant"]; } - - return tenantId != null; } + catch (HttpException) + { + // Happens at app startup in IIS 7.0 + } + + return tenantId != null; } } diff --git a/src/MultitenantExample.WcfService/Dependencies/BaseDependency.cs b/src/MultitenantExample.WcfService/Dependencies/BaseDependency.cs index 91b8525..3a30893 100644 --- a/src/MultitenantExample.WcfService/Dependencies/BaseDependency.cs +++ b/src/MultitenantExample.WcfService/Dependencies/BaseDependency.cs @@ -1,31 +1,30 @@ using System; -namespace MultitenantExample.WcfService.Dependencies +namespace MultitenantExample.WcfService.Dependencies; + +/// +/// Base class for dependencies. Used simply to avoid redundant code; it's not +/// actually required to have a common derivation chain. +/// +public class BaseDependency : IDependency { /// - /// Base class for dependencies. Used simply to avoid redundant code; it's not - /// actually required to have a common derivation chain. + /// Initializes a new instance of the class. /// - public class BaseDependency : IDependency + public BaseDependency() { - /// - /// Initializes a new instance of the class. - /// - public BaseDependency() - { - InstanceId = Guid.NewGuid(); - } + InstanceId = Guid.NewGuid(); + } - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - public Guid InstanceId - { - get; private set; - } + /// + /// Gets the unique instance ID for the dependency. + /// + /// + /// A that indicates the unique ID for the + /// instance. + /// + public Guid InstanceId + { + get; private set; } } diff --git a/src/MultitenantExample.WcfService/Dependencies/DefaultTenantDependency.cs b/src/MultitenantExample.WcfService/Dependencies/DefaultTenantDependency.cs index cfc817e..207f247 100644 --- a/src/MultitenantExample.WcfService/Dependencies/DefaultTenantDependency.cs +++ b/src/MultitenantExample.WcfService/Dependencies/DefaultTenantDependency.cs @@ -1,9 +1,8 @@ -namespace MultitenantExample.WcfService.Dependencies +namespace MultitenantExample.WcfService.Dependencies; + +/// +/// Tenant-specific dependency for the default tenant. +/// +public class DefaultTenantDependency : BaseDependency { - /// - /// Tenant-specific dependency for the default tenant. - /// - public class DefaultTenantDependency : BaseDependency - { - } } diff --git a/src/MultitenantExample.WcfService/Dependencies/IDependency.cs b/src/MultitenantExample.WcfService/Dependencies/IDependency.cs index 780793d..0a3e9ae 100644 --- a/src/MultitenantExample.WcfService/Dependencies/IDependency.cs +++ b/src/MultitenantExample.WcfService/Dependencies/IDependency.cs @@ -1,23 +1,22 @@ using System; -namespace MultitenantExample.WcfService.Dependencies +namespace MultitenantExample.WcfService.Dependencies; + +/// +/// Demonstration dependency interface that allows you to inspect the unique +/// ID on a specific resolved instance of the dependency. +/// +public interface IDependency { /// - /// Demonstration dependency interface that allows you to inspect the unique - /// ID on a specific resolved instance of the dependency. + /// Gets the unique instance ID for the dependency. /// - public interface IDependency + /// + /// A that indicates the unique ID for the + /// instance. + /// + Guid InstanceId { - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - Guid InstanceId - { - get; - } + get; } } diff --git a/src/MultitenantExample.WcfService/Dependencies/Tenant1Dependency.cs b/src/MultitenantExample.WcfService/Dependencies/Tenant1Dependency.cs index 9a694bf..6acf8e9 100644 --- a/src/MultitenantExample.WcfService/Dependencies/Tenant1Dependency.cs +++ b/src/MultitenantExample.WcfService/Dependencies/Tenant1Dependency.cs @@ -1,9 +1,8 @@ -namespace MultitenantExample.WcfService.Dependencies +namespace MultitenantExample.WcfService.Dependencies; + +/// +/// Tenant-specific dependency for Tenant 1. +/// +public class Tenant1Dependency : BaseDependency { - /// - /// Tenant-specific dependency for Tenant 1. - /// - public class Tenant1Dependency : BaseDependency - { - } } diff --git a/src/MultitenantExample.WcfService/Dependencies/Tenant2Dependency.cs b/src/MultitenantExample.WcfService/Dependencies/Tenant2Dependency.cs index 0c4d42f..a6bdc2b 100644 --- a/src/MultitenantExample.WcfService/Dependencies/Tenant2Dependency.cs +++ b/src/MultitenantExample.WcfService/Dependencies/Tenant2Dependency.cs @@ -1,9 +1,8 @@ -namespace MultitenantExample.WcfService.Dependencies +namespace MultitenantExample.WcfService.Dependencies; + +/// +/// Tenant-specific dependency for Tenant 2. +/// +public class Tenant2Dependency : BaseDependency { - /// - /// Tenant-specific dependency for Tenant 2. - /// - public class Tenant2Dependency : BaseDependency - { - } } diff --git a/src/MultitenantExample.WcfService/GetServiceInfoResponse.cs b/src/MultitenantExample.WcfService/GetServiceInfoResponse.cs index 3014865..7dc7222 100644 --- a/src/MultitenantExample.WcfService/GetServiceInfoResponse.cs +++ b/src/MultitenantExample.WcfService/GetServiceInfoResponse.cs @@ -1,60 +1,59 @@ using System; using System.ServiceModel; -namespace MultitenantExample.WcfService +namespace MultitenantExample.WcfService; + +/// +/// Response message contract for the service info operation. +/// +[MessageContract] +public class GetServiceInfoResponse { /// - /// Response message contract for the service info operation. + /// Gets or sets the tenant ID handling the request. /// - [MessageContract] - public class GetServiceInfoResponse + /// + /// A that represents the current tenant ID. + /// + [MessageBodyMember] + public string? TenantId { - /// - /// Gets or sets the tenant ID handling the request. - /// - /// - /// A that represents the current tenant ID. - /// - [MessageBodyMember] - public string TenantId - { - get; set; - } + get; set; + } - /// - /// Gets or sets the service implementation type name. - /// - /// - /// A with the service implementation type name to display. - /// - [MessageBodyMember] - public string ServiceImplementationTypeName - { - get; set; - } + /// + /// Gets or sets the service implementation type name. + /// + /// + /// A with the service implementation type name to display. + /// + [MessageBodyMember] + public string? ServiceImplementationTypeName + { + get; set; + } - /// - /// /// Gets or sets the dependency type name. - /// - /// - /// A with the dependency type name to display. - /// - [MessageBodyMember] - public string DependencyTypeName - { - get; set; - } + /// + /// /// Gets or sets the dependency type name. + /// + /// + /// A with the dependency type name to display. + /// + [MessageBodyMember] + public string? DependencyTypeName + { + get; set; + } - /// - /// Gets or sets the dependency instance ID. - /// - /// - /// A that indicates the unique ID for the dependency instance. - /// - [MessageBodyMember] - public Guid DependencyInstanceId - { - get; set; - } + /// + /// Gets or sets the dependency instance ID. + /// + /// + /// A that indicates the unique ID for the dependency instance. + /// + [MessageBodyMember] + public Guid DependencyInstanceId + { + get; set; } } diff --git a/src/MultitenantExample.WcfService/Global.asax.cs b/src/MultitenantExample.WcfService/Global.asax.cs index 3bfb8f0..72585d5 100644 --- a/src/MultitenantExample.WcfService/Global.asax.cs +++ b/src/MultitenantExample.WcfService/Global.asax.cs @@ -6,97 +6,96 @@ using MultitenantExample.WcfService.Dependencies; using MultitenantExample.WcfService.ServiceImplementations; -namespace MultitenantExample.WcfService +namespace MultitenantExample.WcfService; + +/// +/// Global application class for the multitenant WCF example application. +/// +/// +/// +/// It is easiest to see this application in action from the MVC example. +/// The MVC example makes use of this service and displays the information, +/// illustrating a complete multitenant system in action. +/// +/// +public class Global : System.Web.HttpApplication { /// - /// Global application class for the multitenant WCF example application. + /// Handles the global application startup event. /// - /// - /// - /// It is easiest to see this application in action from the MVC example. - /// The MVC example makes use of this service and displays the information, - /// illustrating a complete multitenant system in action. - /// - /// - public class Global : System.Web.HttpApplication + protected void Application_Start(object sender, EventArgs e) { - /// - /// Handles the global application startup event. - /// - protected void Application_Start(object sender, EventArgs e) - { - // Create the tenant ID strategy. Required for multitenant integration. - var tenantIdStrategy = new OperationContextTenantIdentificationStrategy(); + // Create the tenant ID strategy. Required for multitenant integration. + var tenantIdStrategy = new OperationContextTenantIdentificationStrategy(); - // Register application-level dependencies and service implementations. - // Note that we are registering the services as the interface type - // because the .svc files refer to the interfaces. We could potentially - // use named service types as well. - var builder = new ContainerBuilder(); - builder.RegisterType().As(); - builder.RegisterType().As(); - builder.RegisterType().As(); + // Register application-level dependencies and service implementations. + // Note that we are registering the services as the interface type + // because the .svc files refer to the interfaces. We could potentially + // use named service types as well. + var builder = new ContainerBuilder(); + builder.RegisterType().As(); + builder.RegisterType().As(); + builder.RegisterType().As(); - // Adding the tenant ID strategy into the container so services - // can return output about the current tenant. - builder.RegisterInstance(tenantIdStrategy).As(); + // Adding the tenant ID strategy into the container so services + // can return output about the current tenant. + builder.RegisterInstance(tenantIdStrategy).As(); - // Create the multitenant container based on the application - // defaults - here's where the multitenant bits truly come into play. - var mtc = new MultitenantContainer(tenantIdStrategy, builder.Build()); + // Create the multitenant container based on the application + // defaults - here's where the multitenant bits truly come into play. + var mtc = new MultitenantContainer(tenantIdStrategy, builder.Build()); - // Notice we configure tenant IDs as strings below because the tenant - // identification strategy retrieves string values from the message - // headers. + // Notice we configure tenant IDs as strings below because the tenant + // identification strategy retrieves string values from the message + // headers. - // Configure overrides for tenant 1 - dependencies, service implementations, etc. - mtc.ConfigureTenant("1", - b => - { - b.RegisterType().As().InstancePerDependency(); - b.RegisterType().As(); - b.RegisterType().As(); - }); + // Configure overrides for tenant 1 - dependencies, service implementations, etc. + mtc.ConfigureTenant("1", + b => + { + b.RegisterType().As().InstancePerDependency(); + b.RegisterType().As(); + b.RegisterType().As(); + }); - // Configure overrides for tenant 2 - dependencies, service implementations, etc. - mtc.ConfigureTenant("2", - b => - { - b.RegisterType().As().SingleInstance(); - b.RegisterType().As(); - b.RegisterType().As(); - }); + // Configure overrides for tenant 2 - dependencies, service implementations, etc. + mtc.ConfigureTenant("2", + b => + { + b.RegisterType().As().SingleInstance(); + b.RegisterType().As(); + b.RegisterType().As(); + }); - // Configure overrides for the default tenant. That means the default - // tenant will have some different dependencies than other unconfigured - // tenants. - mtc.ConfigureTenant(null, b => b.RegisterType().As().SingleInstance()); + // Configure overrides for the default tenant. That means the default + // tenant will have some different dependencies than other unconfigured + // tenants. + mtc.ConfigureTenant(null, b => b.RegisterType().As().SingleInstance()); - // Multitenant service hosting requires use of a different service implementation - // data provider that will allow you to define a metadata buddy class that isn't - // tenant-specific. - AutofacHostFactory.ServiceImplementationDataProvider = new MultitenantServiceImplementationDataProvider(); + // Multitenant service hosting requires use of a different service implementation + // data provider that will allow you to define a metadata buddy class that isn't + // tenant-specific. + AutofacHostFactory.ServiceImplementationDataProvider = new MultitenantServiceImplementationDataProvider(); - // Add a behavior to service hosts that get created so incoming messages - // get inspected and the tenant ID can be parsed from message headers. - // For multitenancy to work, you need to know for which tenant a - // given request is being made. In this case, the incoming message headers - // expect to see a string for the tenant ID; if your tenant ID coming - // from clients is different, change that here. - AutofacHostFactory.HostConfigurationAction = - host => - host.Opening += (s, args) => - host.Description.Behaviors.Add(new TenantPropagationBehavior(tenantIdStrategy)); + // Add a behavior to service hosts that get created so incoming messages + // get inspected and the tenant ID can be parsed from message headers. + // For multitenancy to work, you need to know for which tenant a + // given request is being made. In this case, the incoming message headers + // expect to see a string for the tenant ID; if your tenant ID coming + // from clients is different, change that here. + AutofacHostFactory.HostConfigurationAction = + host => + host.Opening += (s, args) => + host.Description.Behaviors.Add(new TenantPropagationBehavior(tenantIdStrategy)); - // Finally, set the host factory application container on the multitenant - // WCF host to a multitenant container. This is similar to standard - // Autofac WCF integration. - AutofacHostFactory.Container = mtc; + // Finally, set the host factory application container on the multitenant + // WCF host to a multitenant container. This is similar to standard + // Autofac WCF integration. + AutofacHostFactory.Container = mtc; - // Note that the .svc file for your service needs to use the - // Autofac.Extras.Multitenant.Wcf.AutofacServiceHostFactory or - // Autofac.Extras.Multitenant.Wcf.AutofacWebServiceHostFactory rather - // than the standard Autofac host factories. - } + // Note that the .svc file for your service needs to use the + // Autofac.Extras.Multitenant.Wcf.AutofacServiceHostFactory or + // Autofac.Extras.Multitenant.Wcf.AutofacWebServiceHostFactory rather + // than the standard Autofac host factories. } } diff --git a/src/MultitenantExample.WcfService/IMetadataConsumer.cs b/src/MultitenantExample.WcfService/IMetadataConsumer.cs index 6f496d3..7871af1 100644 --- a/src/MultitenantExample.WcfService/IMetadataConsumer.cs +++ b/src/MultitenantExample.WcfService/IMetadataConsumer.cs @@ -1,13 +1,12 @@ using System.ServiceModel; using Autofac.Multitenant.Wcf; -namespace MultitenantExample.WcfService +namespace MultitenantExample.WcfService; + +[ServiceContract] +[ServiceMetadataType(typeof(MetadataConsumerBuddyClass))] +public interface IMetadataConsumer { - [ServiceContract] - [ServiceMetadataType(typeof(MetadataConsumerBuddyClass))] - public interface IMetadataConsumer - { - [OperationContract] - GetServiceInfoResponse GetServiceInfo(); - } + [OperationContract] + GetServiceInfoResponse GetServiceInfo(); } diff --git a/src/MultitenantExample.WcfService/IMultitenantService.cs b/src/MultitenantExample.WcfService/IMultitenantService.cs index 01b742e..8a83de4 100644 --- a/src/MultitenantExample.WcfService/IMultitenantService.cs +++ b/src/MultitenantExample.WcfService/IMultitenantService.cs @@ -1,11 +1,10 @@ using System.ServiceModel; -namespace MultitenantExample.WcfService +namespace MultitenantExample.WcfService; + +[ServiceContract] +public interface IMultitenantService { - [ServiceContract] - public interface IMultitenantService - { - [OperationContract] - GetServiceInfoResponse GetServiceInfo(); - } + [OperationContract] + GetServiceInfoResponse GetServiceInfo(); } diff --git a/src/MultitenantExample.WcfService/MetadataConsumerBuddyClass.cs b/src/MultitenantExample.WcfService/MetadataConsumerBuddyClass.cs index 32e7168..c555392 100644 --- a/src/MultitenantExample.WcfService/MetadataConsumerBuddyClass.cs +++ b/src/MultitenantExample.WcfService/MetadataConsumerBuddyClass.cs @@ -1,12 +1,11 @@ using System.ServiceModel; -namespace MultitenantExample.WcfService +namespace MultitenantExample.WcfService; + +// Specifying a ConfigurationName on a metadata buddy class allows you to +// set configuration in web.config (or app.config) and have a nice, friendly, +// predictable configuration name for your service element. +[ServiceBehavior(ConfigurationName = "MultitenantExample.WcfService.IMetadataConsumer")] +public class MetadataConsumerBuddyClass { - // Specifying a ConfigurationName on a metadata buddy class allows you to - // set configuration in web.config (or app.config) and have a nice, friendly, - // predictable configuration name for your service element. - [ServiceBehavior(ConfigurationName = "MultitenantExample.WcfService.IMetadataConsumer")] - public class MetadataConsumerBuddyClass - { - } } diff --git a/src/MultitenantExample.WcfService/MultitenantExample.WcfService.csproj b/src/MultitenantExample.WcfService/MultitenantExample.WcfService.csproj index 981c67d..83b698a 100644 --- a/src/MultitenantExample.WcfService/MultitenantExample.WcfService.csproj +++ b/src/MultitenantExample.WcfService/MultitenantExample.WcfService.csproj @@ -1,5 +1,6 @@  + ../../build/AspNet.ruleset net481 Library bin/ diff --git a/src/MultitenantExample.WcfService/ServiceImplementations/BaseImplementation.cs b/src/MultitenantExample.WcfService/ServiceImplementations/BaseImplementation.cs index 990631a..709e6de 100644 --- a/src/MultitenantExample.WcfService/ServiceImplementations/BaseImplementation.cs +++ b/src/MultitenantExample.WcfService/ServiceImplementations/BaseImplementation.cs @@ -1,29 +1,28 @@ using Autofac.Multitenant; using MultitenantExample.WcfService.Dependencies; -namespace MultitenantExample.WcfService.ServiceImplementations +namespace MultitenantExample.WcfService.ServiceImplementations; + +public class BaseImplementation : IMultitenantService, IMetadataConsumer { - public class BaseImplementation : IMultitenantService, IMetadataConsumer + public BaseImplementation(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy) { - public BaseImplementation(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy) - { - Dependency = dependency; - TenantIdentificationStrategy = tenantIdStrategy; - } + Dependency = dependency; + TenantIdentificationStrategy = tenantIdStrategy; + } - public IDependency Dependency - { - get; set; - } + public IDependency Dependency + { + get; set; + } - public ITenantIdentificationStrategy TenantIdentificationStrategy - { - get; set; - } + public ITenantIdentificationStrategy TenantIdentificationStrategy + { + get; set; + } - public GetServiceInfoResponse GetServiceInfo() - { - return ServiceInfoBuilder.Build(this, Dependency, TenantIdentificationStrategy); - } + public GetServiceInfoResponse GetServiceInfo() + { + return ServiceInfoBuilder.Build(this, Dependency, TenantIdentificationStrategy); } } diff --git a/src/MultitenantExample.WcfService/ServiceImplementations/ServiceInfoBuilder.cs b/src/MultitenantExample.WcfService/ServiceImplementations/ServiceInfoBuilder.cs index 6662ec5..4515d4d 100644 --- a/src/MultitenantExample.WcfService/ServiceImplementations/ServiceInfoBuilder.cs +++ b/src/MultitenantExample.WcfService/ServiceImplementations/ServiceInfoBuilder.cs @@ -1,52 +1,51 @@ using Autofac.Multitenant; using MultitenantExample.WcfService.Dependencies; -namespace MultitenantExample.WcfService.ServiceImplementations +namespace MultitenantExample.WcfService.ServiceImplementations; + +/// +/// Common logic for building a service info response. +/// +/// +/// +/// This builder class is used instead of an +/// inheritance hierarchy to illustrate that service implementations only +/// have to implement the same service contract; they don't need to share +/// an inheritance chain. +/// +/// +public static class ServiceInfoBuilder { /// - /// Common logic for building a service info response. + /// Builds a service info response. /// - /// - /// - /// This builder class is used instead of an - /// inheritance hierarchy to illustrate that service implementations only - /// have to implement the same service contract; they don't need to share - /// an inheritance chain. - /// - /// - public static class ServiceInfoBuilder + /// + /// The service implementation that will be returning the response. + /// + /// + /// The dependency that was provided to the service implementation on construction. + /// + /// + /// The tenant ID strategy. + /// + /// + /// A populated service info response. + /// + public static GetServiceInfoResponse Build(IMultitenantService serviceImplementation, IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy) { - /// - /// Builds a service info response. - /// - /// - /// The service implementation that will be returning the response. - /// - /// - /// The dependency that was provided to the service implementation on construction. - /// - /// - /// The tenant ID strategy. - /// - /// - /// A populated service info response. - /// - public static GetServiceInfoResponse Build(IMultitenantService serviceImplementation, IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy) + var success = tenantIdStrategy.TryIdentifyTenant(out var tenantId); + if (!success || tenantId == null) { - var success = tenantIdStrategy.TryIdentifyTenant(out var tenantId); - if (!success || tenantId == null) - { - tenantId = "[Default Tenant]"; - } - - var response = new GetServiceInfoResponse() - { - ServiceImplementationTypeName = serviceImplementation.GetType().Name, - DependencyInstanceId = dependency.InstanceId, - DependencyTypeName = dependency.GetType().Name, - TenantId = tenantId.ToString() - }; - return response; + tenantId = "[Default Tenant]"; } + + var response = new GetServiceInfoResponse() + { + ServiceImplementationTypeName = serviceImplementation.GetType().Name, + DependencyInstanceId = dependency.InstanceId, + DependencyTypeName = dependency.GetType().Name, + TenantId = tenantId.ToString() + }; + return response; } } diff --git a/src/MultitenantExample.WcfService/ServiceImplementations/Tenant1Implementation.cs b/src/MultitenantExample.WcfService/ServiceImplementations/Tenant1Implementation.cs index cdcf7a7..5f5bb9d 100644 --- a/src/MultitenantExample.WcfService/ServiceImplementations/Tenant1Implementation.cs +++ b/src/MultitenantExample.WcfService/ServiceImplementations/Tenant1Implementation.cs @@ -1,31 +1,30 @@ using Autofac.Multitenant; using MultitenantExample.WcfService.Dependencies; -namespace MultitenantExample.WcfService.ServiceImplementations +namespace MultitenantExample.WcfService.ServiceImplementations; + +public class Tenant1Implementation : IMultitenantService, IMetadataConsumer { - public class Tenant1Implementation : IMultitenantService, IMetadataConsumer + public Tenant1Implementation(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy) { - public Tenant1Implementation(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy) - { - Dependency = dependency; - TenantIdentificationStrategy = tenantIdStrategy; - } + Dependency = dependency; + TenantIdentificationStrategy = tenantIdStrategy; + } - public IDependency Dependency - { - get; set; - } + public IDependency Dependency + { + get; set; + } - public ITenantIdentificationStrategy TenantIdentificationStrategy - { - get; set; - } + public ITenantIdentificationStrategy TenantIdentificationStrategy + { + get; set; + } - public GetServiceInfoResponse GetServiceInfo() - { - var response = ServiceInfoBuilder.Build(this, Dependency, TenantIdentificationStrategy); - response.ServiceImplementationTypeName += " [Custom value from Tenant 1 service imp.]"; - return response; - } + public GetServiceInfoResponse GetServiceInfo() + { + var response = ServiceInfoBuilder.Build(this, Dependency, TenantIdentificationStrategy); + response.ServiceImplementationTypeName += " [Custom value from Tenant 1 service imp.]"; + return response; } } diff --git a/src/MultitenantExample.WcfService/ServiceImplementations/Tenant2Implementation.cs b/src/MultitenantExample.WcfService/ServiceImplementations/Tenant2Implementation.cs index 3c46696..10d951d 100644 --- a/src/MultitenantExample.WcfService/ServiceImplementations/Tenant2Implementation.cs +++ b/src/MultitenantExample.WcfService/ServiceImplementations/Tenant2Implementation.cs @@ -1,31 +1,30 @@ using Autofac.Multitenant; using MultitenantExample.WcfService.Dependencies; -namespace MultitenantExample.WcfService.ServiceImplementations +namespace MultitenantExample.WcfService.ServiceImplementations; + +public class Tenant2Implementation : IMultitenantService, IMetadataConsumer { - public class Tenant2Implementation : IMultitenantService, IMetadataConsumer + public Tenant2Implementation(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy) { - public Tenant2Implementation(IDependency dependency, ITenantIdentificationStrategy tenantIdStrategy) - { - Dependency = dependency; - TenantIdentificationStrategy = tenantIdStrategy; - } + Dependency = dependency; + TenantIdentificationStrategy = tenantIdStrategy; + } - public IDependency Dependency - { - get; set; - } + public IDependency Dependency + { + get; set; + } - public ITenantIdentificationStrategy TenantIdentificationStrategy - { - get; set; - } + public ITenantIdentificationStrategy TenantIdentificationStrategy + { + get; set; + } - public GetServiceInfoResponse GetServiceInfo() - { - var response = ServiceInfoBuilder.Build(this, Dependency, TenantIdentificationStrategy); - response.ServiceImplementationTypeName += " [Tenant 2 service imp custom value here.]"; - return response; - } + public GetServiceInfoResponse GetServiceInfo() + { + var response = ServiceInfoBuilder.Build(this, Dependency, TenantIdentificationStrategy); + response.ServiceImplementationTypeName += " [Tenant 2 service imp custom value here.]"; + return response; } } diff --git a/src/MvcExample/Controllers/HomeController.cs b/src/MvcExample/Controllers/HomeController.cs index 85f0340..0a0c435 100644 --- a/src/MvcExample/Controllers/HomeController.cs +++ b/src/MvcExample/Controllers/HomeController.cs @@ -3,40 +3,41 @@ using MvcExample.HostFactoryService; using MvcExample.Models; -namespace MvcExample.Controllers +namespace MvcExample.Controllers; + +public class HomeController : Controller { - public class HomeController : Controller + public HomeController(IService serviceClient) { - public HomeController(IService serviceClient) - { - ServiceClient = serviceClient; - } + ServiceClient = serviceClient; + } - public IService ServiceClient - { - get; private set; - } + public IService ServiceClient + { + get; private set; + } - public ActionResult About() - { - return View(); - } + [HttpGet] + public ActionResult About() + { + return View(); + } - [CustomActionFilter] - public async Task Index() - { - var serviceInfo = await ServiceClient.GetServiceInfoAsync(new GetServiceInfoRequest()); + [HttpGet] + [CustomActionFilter] + public async Task Index() + { + var serviceInfo = await ServiceClient.GetServiceInfoAsync(new GetServiceInfoRequest()); - var model = new DependencyValueModel - { - // Comes from a dependency in the custom action filter. - FilterValue = (long)HttpContext.Items["filterValue"], + var model = new DependencyValueModel + { + // Comes from a dependency in the custom action filter. + FilterValue = (long)HttpContext.Items["filterValue"], - // Comes from a dependency injected into the WCF service. - WcfServiceDependencyId = serviceInfo.DependencyInstanceId - }; + // Comes from a dependency injected into the WCF service. + WcfServiceDependencyId = serviceInfo.DependencyInstanceId + }; - return View(model); - } + return View(model); } } diff --git a/src/MvcExample/CustomActionFilterAttribute.cs b/src/MvcExample/CustomActionFilterAttribute.cs index a5e2641..28428e5 100644 --- a/src/MvcExample/CustomActionFilterAttribute.cs +++ b/src/MvcExample/CustomActionFilterAttribute.cs @@ -1,20 +1,19 @@ using System.Web.Mvc; using MvcExample.Dependencies; -namespace MvcExample +namespace MvcExample; + +public class CustomActionFilterAttribute : ActionFilterAttribute { - public class CustomActionFilterAttribute : ActionFilterAttribute + public IFilterDependency? Dependency { - public IFilterDependency Dependency - { - get; set; - } + get; set; + } - public override void OnActionExecuting(ActionExecutingContext filterContext) - { - // This filter adds a value from the dependency to the current context - // so the controller can grab it and pass it to the view. - filterContext.HttpContext.Items["filterValue"] = Dependency.CurrentTicks; - } + public override void OnActionExecuting(ActionExecutingContext filterContext) + { + // This filter adds a value from the dependency to the current context + // so the controller can grab it and pass it to the view. + filterContext.HttpContext.Items["filterValue"] = Dependency!.CurrentTicks; } } diff --git a/src/MvcExample/CustomViewPage.cs b/src/MvcExample/CustomViewPage.cs index 34c0f53..e2214fd 100644 --- a/src/MvcExample/CustomViewPage.cs +++ b/src/MvcExample/CustomViewPage.cs @@ -1,17 +1,16 @@ using System.Web.Mvc; using MvcExample.Dependencies; -namespace MvcExample +namespace MvcExample; + +/// +/// Custom view page base class to illustrate view injection. +/// +/// +public abstract class CustomViewPage : WebViewPage { - /// - /// Custom view page base class to illustrate view injection. - /// - /// - public abstract class CustomViewPage : WebViewPage + public IViewDependency? Dependency { - public IViewDependency Dependency - { - get; set; - } + get; set; } } diff --git a/src/MvcExample/Dependencies/FilterDependency.cs b/src/MvcExample/Dependencies/FilterDependency.cs index 19408d6..2633aa0 100644 --- a/src/MvcExample/Dependencies/FilterDependency.cs +++ b/src/MvcExample/Dependencies/FilterDependency.cs @@ -1,25 +1,24 @@ using System; -namespace MvcExample.Dependencies +namespace MvcExample.Dependencies; + +/// +/// Implementation of a simple dependency to inject into a filter. +/// +/// +public class FilterDependency : IFilterDependency { /// - /// Implementation of a simple dependency to inject into a filter. + /// Gets the current date and time as ticks. /// - /// - public class FilterDependency : IFilterDependency + /// + /// An with the current date and time as ticks. + /// + public long CurrentTicks { - /// - /// Gets the current date and time as ticks. - /// - /// - /// An with the current date and time as ticks. - /// - public long CurrentTicks + get { - get - { - return DateTime.UtcNow.Ticks; - } + return DateTime.UtcNow.Ticks; } } } diff --git a/src/MvcExample/Dependencies/IFilterDependency.cs b/src/MvcExample/Dependencies/IFilterDependency.cs index ab917d8..37f6638 100644 --- a/src/MvcExample/Dependencies/IFilterDependency.cs +++ b/src/MvcExample/Dependencies/IFilterDependency.cs @@ -1,19 +1,18 @@ -namespace MvcExample.Dependencies +namespace MvcExample.Dependencies; + +/// +/// Simple dependency to show injection into an action filter. +/// +public interface IFilterDependency { /// - /// Simple dependency to show injection into an action filter. + /// Gets the current date and time as ticks. /// - public interface IFilterDependency + /// + /// An with the current date and time as ticks. + /// + long CurrentTicks { - /// - /// Gets the current date and time as ticks. - /// - /// - /// An with the current date and time as ticks. - /// - long CurrentTicks - { - get; - } + get; } } diff --git a/src/MvcExample/Dependencies/IViewDependency.cs b/src/MvcExample/Dependencies/IViewDependency.cs index 1335bb7..60f85e6 100644 --- a/src/MvcExample/Dependencies/IViewDependency.cs +++ b/src/MvcExample/Dependencies/IViewDependency.cs @@ -1,22 +1,21 @@ using System; -namespace MvcExample.Dependencies +namespace MvcExample.Dependencies; + +/// +/// Simple dependency to show injection into a Razor view. +/// +public interface IViewDependency { /// - /// Simple dependency to show injection into a Razor view. + /// Gets the unique instance ID for the dependency. /// - public interface IViewDependency + /// + /// A that indicates the unique ID for the + /// instance. + /// + Guid InstanceId { - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - Guid InstanceId - { - get; - } + get; } } diff --git a/src/MvcExample/Dependencies/ViewDependency.cs b/src/MvcExample/Dependencies/ViewDependency.cs index d4f99d2..03eafcb 100644 --- a/src/MvcExample/Dependencies/ViewDependency.cs +++ b/src/MvcExample/Dependencies/ViewDependency.cs @@ -1,31 +1,30 @@ using System; -namespace MvcExample.Dependencies +namespace MvcExample.Dependencies; + +/// +/// Implementation of a simple dependency to inject into a view. +/// +/// +public class ViewDependency : IViewDependency { /// - /// Implementation of a simple dependency to inject into a view. + /// Initializes a new instance of the class. /// - /// - public class ViewDependency : IViewDependency + public ViewDependency() { - /// - /// Initializes a new instance of the class. - /// - public ViewDependency() - { - InstanceId = Guid.NewGuid(); - } + InstanceId = Guid.NewGuid(); + } - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - public Guid InstanceId - { - get; private set; - } + /// + /// Gets the unique instance ID for the dependency. + /// + /// + /// A that indicates the unique ID for the + /// instance. + /// + public Guid InstanceId + { + get; private set; } } diff --git a/src/MvcExample/Global.asax.cs b/src/MvcExample/Global.asax.cs index 449d910..b18e238 100644 --- a/src/MvcExample/Global.asax.cs +++ b/src/MvcExample/Global.asax.cs @@ -8,84 +8,83 @@ using MvcExample.Dependencies; using MvcExample.HostFactoryService; -namespace MvcExample +namespace MvcExample; + +public class MvcApplication : System.Web.HttpApplication { - public class MvcApplication : System.Web.HttpApplication + public static void RegisterBundles(BundleCollection bundles) { - public static void RegisterBundles(BundleCollection bundles) - { - bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/Site.css")); - } + bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/Site.css")); + } - public static void RegisterGlobalFilters(GlobalFilterCollection filters) - { - filters.Add(new HandleErrorAttribute()); - } + public static void RegisterGlobalFilters(GlobalFilterCollection filters) + { + filters.Add(new HandleErrorAttribute()); + } - public static void RegisterRoutes(RouteCollection routes) - { - routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); + public static void RegisterRoutes(RouteCollection routes) + { + routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); - routes.MapRoute( - name: "Default", - url: "{controller}/{action}/{id}", - defaults: new - { - controller = "Home", - action = "Index", - id = UrlParameter.Optional - } - ); - } + routes.MapRoute( + name: "Default", + url: "{controller}/{action}/{id}", + defaults: new + { + controller = "Home", + action = "Index", + id = UrlParameter.Optional + } + ); + } - protected void Application_Start() - { - // MVC setup documentation here: - // https://autofac.readthedocs.io/en/latest/integration/mvc.html - // WCF setup documentation here: - // https://autofac.readthedocs.io/en/latest/integration/wcf.html - // - // First we'll register the MVC/WCF stuff... - var builder = new ContainerBuilder(); + protected static void Application_Start() + { + // MVC setup documentation here: + // https://autofac.readthedocs.io/en/latest/integration/mvc.html + // WCF setup documentation here: + // https://autofac.readthedocs.io/en/latest/integration/wcf.html + // + // First we'll register the MVC/WCF stuff... + var builder = new ContainerBuilder(); - // MVC - Register your MVC controllers. - builder.RegisterControllers(typeof(MvcApplication).Assembly); + // MVC - Register your MVC controllers. + builder.RegisterControllers(typeof(MvcApplication).Assembly); - // MVC - OPTIONAL: Register model binders that require DI. - builder.RegisterModelBinders(typeof(MvcApplication).Assembly); - builder.RegisterModelBinderProvider(); + // MVC - OPTIONAL: Register model binders that require DI. + builder.RegisterModelBinders(typeof(MvcApplication).Assembly); + builder.RegisterModelBinderProvider(); - // MVC - OPTIONAL: Register web abstractions like HttpContextBase. - builder.RegisterModule(); + // MVC - OPTIONAL: Register web abstractions like HttpContextBase. + builder.RegisterModule(); - // MVC - OPTIONAL: Enable property injection in view pages. - builder.RegisterSource(new ViewRegistrationSource()); + // MVC - OPTIONAL: Enable property injection in view pages. + builder.RegisterSource(new ViewRegistrationSource()); - // MVC - OPTIONAL: Enable property injection into action filters. - builder.RegisterFilterProvider(); + // MVC - OPTIONAL: Enable property injection into action filters. + builder.RegisterFilterProvider(); - // WCF - Register channel factory and channel for service clients. - builder - .Register(c => new ChannelFactory("BasicHttpBinding_IService")) - .SingleInstance(); - builder - .Register(c => c.Resolve>().CreateChannel()) - .As() - .UseWcfSafeRelease(); + // WCF - Register channel factory and channel for service clients. + builder + .Register(c => new ChannelFactory("BasicHttpBinding_IService")) + .SingleInstance(); + builder + .Register(c => c.Resolve>().CreateChannel()) + .As() + .UseWcfSafeRelease(); - // Register application dependencies. - builder.RegisterType().As(); - builder.RegisterType().As(); + // Register application dependencies. + builder.RegisterType().As(); + builder.RegisterType().As(); - // MVC - Set the dependency resolver to be Autofac. - var container = builder.Build(); - DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); + // MVC - Set the dependency resolver to be Autofac. + var container = builder.Build(); + DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); - // Standard MVC setup: - AreaRegistration.RegisterAllAreas(); - RegisterGlobalFilters(GlobalFilters.Filters); - RegisterRoutes(RouteTable.Routes); - RegisterBundles(BundleTable.Bundles); - } + // Standard MVC setup: + AreaRegistration.RegisterAllAreas(); + RegisterGlobalFilters(GlobalFilters.Filters); + RegisterRoutes(RouteTable.Routes); + RegisterBundles(BundleTable.Bundles); } } diff --git a/src/MvcExample/Models/DependencyValueModel.cs b/src/MvcExample/Models/DependencyValueModel.cs index 1c6a71f..b26aade 100644 --- a/src/MvcExample/Models/DependencyValueModel.cs +++ b/src/MvcExample/Models/DependencyValueModel.cs @@ -1,32 +1,31 @@ using System; -namespace MvcExample.Models +namespace MvcExample.Models; + +/// +/// Model used to gather values from dependencies and display them. +/// +public class DependencyValueModel { /// - /// Model used to gather values from dependencies and display them. + /// Gets or sets the value retrieved from the action filter. /// - public class DependencyValueModel + /// + /// An with the current date and time as ticks. + /// + public long FilterValue { - /// - /// Gets or sets the value retrieved from the action filter. - /// - /// - /// An with the current date and time as ticks. - /// - public long FilterValue - { - get; set; - } + get; set; + } - /// - /// Gets or sets the ID of the WCF service dependency. - /// - /// - /// The that identifies the dependency injected into the WCF service. - /// - public Guid WcfServiceDependencyId - { - get; set; - } + /// + /// Gets or sets the ID of the WCF service dependency. + /// + /// + /// The that identifies the dependency injected into the WCF service. + /// + public Guid WcfServiceDependencyId + { + get; set; } } diff --git a/src/MvcExample/MvcExample.csproj b/src/MvcExample/MvcExample.csproj index 74ad47b..afac154 100644 --- a/src/MvcExample/MvcExample.csproj +++ b/src/MvcExample/MvcExample.csproj @@ -1,5 +1,6 @@  + ../../build/AspNet.ruleset net481 Library bin/ diff --git a/src/WcfExample/Dependencies/Dependency.cs b/src/WcfExample/Dependencies/Dependency.cs index 20d830c..4f8256e 100644 --- a/src/WcfExample/Dependencies/Dependency.cs +++ b/src/WcfExample/Dependencies/Dependency.cs @@ -1,30 +1,29 @@ using System; -namespace WcfExample.Dependencies +namespace WcfExample.Dependencies; + +/// +/// Simple dependency implementation. +/// +public class Dependency : IDependency { /// - /// Simple dependency implementation. + /// Initializes a new instance of the class. /// - public class Dependency : IDependency + public Dependency() { - /// - /// Initializes a new instance of the class. - /// - public Dependency() - { - InstanceId = Guid.NewGuid(); - } + InstanceId = Guid.NewGuid(); + } - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - public Guid InstanceId - { - get; private set; - } + /// + /// Gets the unique instance ID for the dependency. + /// + /// + /// A that indicates the unique ID for the + /// instance. + /// + public Guid InstanceId + { + get; private set; } } diff --git a/src/WcfExample/Dependencies/IDependency.cs b/src/WcfExample/Dependencies/IDependency.cs index fcf0bec..de59d65 100644 --- a/src/WcfExample/Dependencies/IDependency.cs +++ b/src/WcfExample/Dependencies/IDependency.cs @@ -1,23 +1,22 @@ using System; -namespace WcfExample.Dependencies +namespace WcfExample.Dependencies; + +/// +/// Demonstration dependency interface that allows you to inspect the unique +/// ID on a specific resolved instance of the dependency. +/// +public interface IDependency { /// - /// Demonstration dependency interface that allows you to inspect the unique - /// ID on a specific resolved instance of the dependency. + /// Gets the unique instance ID for the dependency. /// - public interface IDependency + /// + /// A that indicates the unique ID for the + /// instance. + /// + Guid InstanceId { - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - Guid InstanceId - { - get; - } + get; } } diff --git a/src/WcfExample/GetServiceInfoResponse.cs b/src/WcfExample/GetServiceInfoResponse.cs index 716b63c..fd0fb7b 100644 --- a/src/WcfExample/GetServiceInfoResponse.cs +++ b/src/WcfExample/GetServiceInfoResponse.cs @@ -1,36 +1,35 @@ using System; using System.ServiceModel; -namespace WcfExample +namespace WcfExample; + +/// +/// Response message contract for the service info operation. +/// +[MessageContract] +public class GetServiceInfoResponse { /// - /// Response message contract for the service info operation. + /// Gets or sets the service implementation type name. /// - [MessageContract] - public class GetServiceInfoResponse + /// + /// A with the service implementation type name to display. + /// + [MessageBodyMember] + public string? ServiceImplementationTypeName { - /// - /// Gets or sets the service implementation type name. - /// - /// - /// A with the service implementation type name to display. - /// - [MessageBodyMember] - public string ServiceImplementationTypeName - { - get; set; - } + get; set; + } - /// - /// Gets or sets the dependency instance ID. - /// - /// - /// A that indicates the unique ID for the dependency instance. - /// - [MessageBodyMember] - public Guid DependencyInstanceId - { - get; set; - } + /// + /// Gets or sets the dependency instance ID. + /// + /// + /// A that indicates the unique ID for the dependency instance. + /// + [MessageBodyMember] + public Guid DependencyInstanceId + { + get; set; } } diff --git a/src/WcfExample/Global.asax.cs b/src/WcfExample/Global.asax.cs index 9177409..4c0bb5d 100644 --- a/src/WcfExample/Global.asax.cs +++ b/src/WcfExample/Global.asax.cs @@ -4,27 +4,26 @@ using Autofac.Integration.Wcf; using WcfExample.Dependencies; -namespace WcfExample +namespace WcfExample; + +public class Global : HttpApplication { - public class Global : HttpApplication + protected void Application_Start(object sender, EventArgs e) { - protected void Application_Start(object sender, EventArgs e) - { - // WCF integration docs are at: - // https://autofac.readthedocs.io/en/latest/integration/wcf.html - var builder = new ContainerBuilder(); + // WCF integration docs are at: + // https://autofac.readthedocs.io/en/latest/integration/wcf.html + var builder = new ContainerBuilder(); - // Register your service implementations. - builder.RegisterType(); - builder.RegisterType(); + // Register your service implementations. + builder.RegisterType(); + builder.RegisterType(); - // Register your dependencies. - builder.RegisterType().As(); + // Register your dependencies. + builder.RegisterType().As(); - // Set the dependency resolver. This works for both regular - // WCF services and REST-enabled services. - var container = builder.Build(); - AutofacHostFactory.Container = container; - } + // Set the dependency resolver. This works for both regular + // WCF services and REST-enabled services. + var container = builder.Build(); + AutofacHostFactory.Container = container; } } diff --git a/src/WcfExample/HostFactoryService.svc.cs b/src/WcfExample/HostFactoryService.svc.cs index eac1a24..06e9ff9 100644 --- a/src/WcfExample/HostFactoryService.svc.cs +++ b/src/WcfExample/HostFactoryService.svc.cs @@ -1,26 +1,25 @@ using WcfExample.Dependencies; -namespace WcfExample +namespace WcfExample; + +public class HostFactoryService : IService { - public class HostFactoryService : IService + public HostFactoryService(IDependency dependency) { - public HostFactoryService(IDependency dependency) - { - Dependency = dependency; - } + Dependency = dependency; + } - public IDependency Dependency - { - get; private set; - } + public IDependency Dependency + { + get; private set; + } - public GetServiceInfoResponse GetServiceInfo() + public GetServiceInfoResponse GetServiceInfo() + { + return new GetServiceInfoResponse { - return new GetServiceInfoResponse - { - DependencyInstanceId = Dependency.InstanceId, - ServiceImplementationTypeName = GetType().FullName - }; - } + DependencyInstanceId = Dependency.InstanceId, + ServiceImplementationTypeName = GetType().FullName + }; } } diff --git a/src/WcfExample/IService.cs b/src/WcfExample/IService.cs index 3e2e3ad..e4f97e1 100644 --- a/src/WcfExample/IService.cs +++ b/src/WcfExample/IService.cs @@ -1,13 +1,12 @@ using System.ServiceModel; using System.ServiceModel.Web; -namespace WcfExample +namespace WcfExample; + +[ServiceContract] +public interface IService { - [ServiceContract] - public interface IService - { - [OperationContract] - [WebGet(UriTemplate = "GetInfo")] - GetServiceInfoResponse GetServiceInfo(); - } + [OperationContract] + [WebGet(UriTemplate = "GetInfo")] + GetServiceInfoResponse GetServiceInfo(); } diff --git a/src/WcfExample/WcfExample.csproj b/src/WcfExample/WcfExample.csproj index 4ce3a4e..8d82e6d 100644 --- a/src/WcfExample/WcfExample.csproj +++ b/src/WcfExample/WcfExample.csproj @@ -1,5 +1,6 @@  + ../../build/AspNet.ruleset net481 Library bin/ diff --git a/src/WcfExample/WebHostFactoryService.svc.cs b/src/WcfExample/WebHostFactoryService.svc.cs index 5a8130c..79b29a2 100644 --- a/src/WcfExample/WebHostFactoryService.svc.cs +++ b/src/WcfExample/WebHostFactoryService.svc.cs @@ -1,32 +1,31 @@ using WcfExample.Dependencies; -namespace WcfExample +namespace WcfExample; + +/// +/// REST-enabled version of the service. Call +/// http://localhost:25665/WebHostFactoryService.svc/GetInfo +/// to see this execute. +/// +/// +public class WebHostFactoryService : IService { - /// - /// REST-enabled version of the service. Call - /// http://localhost:25665/WebHostFactoryService.svc/GetInfo - /// to see this execute. - /// - /// - public class WebHostFactoryService : IService + public WebHostFactoryService(IDependency dependency) { - public WebHostFactoryService(IDependency dependency) - { - Dependency = dependency; - } + Dependency = dependency; + } - public IDependency Dependency - { - get; private set; - } + public IDependency Dependency + { + get; private set; + } - public GetServiceInfoResponse GetServiceInfo() + public GetServiceInfoResponse GetServiceInfo() + { + return new GetServiceInfoResponse { - return new GetServiceInfoResponse - { - DependencyInstanceId = Dependency.InstanceId, - ServiceImplementationTypeName = GetType().FullName - }; - } + DependencyInstanceId = Dependency.InstanceId, + ServiceImplementationTypeName = GetType().FullName + }; } } diff --git a/src/WebApiExample.OwinSelfHost/CustomActionFilter.cs b/src/WebApiExample.OwinSelfHost/CustomActionFilter.cs index 1c5afde..88c47ff 100644 --- a/src/WebApiExample.OwinSelfHost/CustomActionFilter.cs +++ b/src/WebApiExample.OwinSelfHost/CustomActionFilter.cs @@ -4,27 +4,26 @@ using System.Web.Http.Filters; using Autofac.Integration.WebApi; -namespace WebApiExample.OwinSelfHost +namespace WebApiExample.OwinSelfHost; + +public class CustomActionFilter : IAutofacActionFilter { - public class CustomActionFilter : IAutofacActionFilter - { - private readonly ILogger _logger; + private readonly ILogger _logger; - public CustomActionFilter(ILogger logger) - { - _logger = logger; - } + public CustomActionFilter(ILogger logger) + { + _logger = logger; + } - public Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) - { - _logger.Write("Inside the 'OnActionExecutedAsync' method of the custom action filter."); - return Task.FromResult(0); - } + public Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) + { + _logger.Write("Inside the 'OnActionExecutedAsync' method of the custom action filter."); + return Task.FromResult(0); + } - public Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken) - { - _logger.Write("Inside the 'OnActionExecutingAsync' method of the custom action filter."); - return Task.FromResult(0); - } + public Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken) + { + _logger.Write("Inside the 'OnActionExecutingAsync' method of the custom action filter."); + return Task.FromResult(0); } } diff --git a/src/WebApiExample.OwinSelfHost/FirstMiddleware.cs b/src/WebApiExample.OwinSelfHost/FirstMiddleware.cs index 8613892..d9a066a 100644 --- a/src/WebApiExample.OwinSelfHost/FirstMiddleware.cs +++ b/src/WebApiExample.OwinSelfHost/FirstMiddleware.cs @@ -1,22 +1,21 @@ using System.Threading.Tasks; using Microsoft.Owin; -namespace WebApiExample.OwinSelfHost +namespace WebApiExample.OwinSelfHost; + +public class FirstMiddleware : OwinMiddleware { - public class FirstMiddleware : OwinMiddleware - { - private readonly ILogger _logger; + private readonly ILogger _logger; - public FirstMiddleware(OwinMiddleware next, ILogger logger) : base(next) - { - _logger = logger; - } + public FirstMiddleware(OwinMiddleware next, ILogger logger) : base(next) + { + _logger = logger; + } - public override async Task Invoke(IOwinContext context) - { - _logger.Write("Inside the 'Invoke' method of the '{0}' middleware.", GetType().Name); + public override async Task Invoke(IOwinContext context) + { + _logger.Write("Inside the 'Invoke' method of the '{0}' middleware.", GetType().Name); - await Next.Invoke(context); - } + await Next.Invoke(context); } } diff --git a/src/WebApiExample.OwinSelfHost/ILogger.cs b/src/WebApiExample.OwinSelfHost/ILogger.cs index 76a227b..0695746 100644 --- a/src/WebApiExample.OwinSelfHost/ILogger.cs +++ b/src/WebApiExample.OwinSelfHost/ILogger.cs @@ -1,7 +1,6 @@ -namespace WebApiExample.OwinSelfHost +namespace WebApiExample.OwinSelfHost; + +public interface ILogger { - public interface ILogger - { - void Write(string message, params object[] args); - } + void Write(string message, params object[] args); } diff --git a/src/WebApiExample.OwinSelfHost/Logger.cs b/src/WebApiExample.OwinSelfHost/Logger.cs index 96f28a8..4b8eea1 100644 --- a/src/WebApiExample.OwinSelfHost/Logger.cs +++ b/src/WebApiExample.OwinSelfHost/Logger.cs @@ -1,12 +1,11 @@ using System.Diagnostics; -namespace WebApiExample.OwinSelfHost +namespace WebApiExample.OwinSelfHost; + +public class Logger : ILogger { - public class Logger : ILogger + public void Write(string message, params object[] args) { - public void Write(string message, params object[] args) - { - Debug.WriteLine(message, args); - } + Debug.WriteLine(message, args); } } diff --git a/src/WebApiExample.OwinSelfHost/Program.cs b/src/WebApiExample.OwinSelfHost/Program.cs index e84ce20..9d9c7aa 100644 --- a/src/WebApiExample.OwinSelfHost/Program.cs +++ b/src/WebApiExample.OwinSelfHost/Program.cs @@ -3,34 +3,33 @@ using System.Net.Http; using Microsoft.Owin.Hosting; -namespace WebApiExample.OwinSelfHost +namespace WebApiExample.OwinSelfHost; + +internal sealed class Program { - internal class Program + private static void Main() { - private static void Main() - { - const string BaseAddress = "http://localhost:9123/"; + const string BaseAddress = "http://localhost:9123/"; - // This starts the OWIN host using the application startup - // logic in the Startup class. See Startup for the example of - // how to set up OWIN Web API. - using (WebApp.Start(BaseAddress)) - { - // On startup this app will make a request to the self-hosted - // Web API service. You should see logging statements and results - // dumped to the console window. - var client = new HttpClient(); - var response = client.GetAsync(BaseAddress + "api/test").Result; + // This starts the OWIN host using the application startup + // logic in the Startup class. See Startup for the example of + // how to set up OWIN Web API. + using (WebApp.Start(BaseAddress)) + { + // On startup this app will make a request to the self-hosted + // Web API service. You should see logging statements and results + // dumped to the console window. + var client = new HttpClient(); + var response = client.GetAsync(BaseAddress + "api/test").Result; - Console.WriteLine(response); - Console.WriteLine(response.Content.ReadAsStringAsync().Result); - } + Console.WriteLine(response); + Console.WriteLine(response.Content.ReadAsStringAsync().Result); + } - if (Debugger.IsAttached) - { - Console.WriteLine("Press any key to exit."); - Console.ReadLine(); - } + if (Debugger.IsAttached) + { + Console.WriteLine("Press any key to exit."); + Console.ReadLine(); } } } diff --git a/src/WebApiExample.OwinSelfHost/SecondMiddleware.cs b/src/WebApiExample.OwinSelfHost/SecondMiddleware.cs index df71ad3..56a1ace 100644 --- a/src/WebApiExample.OwinSelfHost/SecondMiddleware.cs +++ b/src/WebApiExample.OwinSelfHost/SecondMiddleware.cs @@ -1,22 +1,21 @@ using System.Threading.Tasks; using Microsoft.Owin; -namespace WebApiExample.OwinSelfHost +namespace WebApiExample.OwinSelfHost; + +public class SecondMiddleware : OwinMiddleware { - public class SecondMiddleware : OwinMiddleware - { - private readonly ILogger _logger; + private readonly ILogger _logger; - public SecondMiddleware(OwinMiddleware next, ILogger logger) : base(next) - { - _logger = logger; - } + public SecondMiddleware(OwinMiddleware next, ILogger logger) : base(next) + { + _logger = logger; + } - public override async Task Invoke(IOwinContext context) - { - _logger.Write("Inside the 'Invoke' method of the '{0}' middleware.", GetType().Name); + public override async Task Invoke(IOwinContext context) + { + _logger.Write("Inside the 'Invoke' method of the '{0}' middleware.", GetType().Name); - await Next.Invoke(context); - } + await Next.Invoke(context); } } diff --git a/src/WebApiExample.OwinSelfHost/Startup.cs b/src/WebApiExample.OwinSelfHost/Startup.cs index 5c6738b..20b91e4 100644 --- a/src/WebApiExample.OwinSelfHost/Startup.cs +++ b/src/WebApiExample.OwinSelfHost/Startup.cs @@ -4,67 +4,66 @@ using Autofac.Integration.WebApi; using Owin; -namespace WebApiExample.OwinSelfHost +namespace WebApiExample.OwinSelfHost; + +public class Startup { - public class Startup + public static void Configuration(IAppBuilder app) { - public void Configuration(IAppBuilder app) - { - // In OWIN you create your own HttpConfiguration rather than - // re-using the GlobalConfiguration. - var config = new HttpConfiguration(); + // In OWIN you create your own HttpConfiguration rather than + // re-using the GlobalConfiguration. + var config = new HttpConfiguration(); - config.Routes.MapHttpRoute( - "DefaultApi", - "api/{controller}/{id}", - new - { - id = RouteParameter.Optional - }); + config.Routes.MapHttpRoute( + "DefaultApi", + "api/{controller}/{id}", + new + { + id = RouteParameter.Optional + }); - var builder = new ContainerBuilder(); + var builder = new ContainerBuilder(); - // Register Web API controller in executing assembly. - builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); + // Register Web API controller in executing assembly. + builder.RegisterApiControllers(Assembly.GetExecutingAssembly()); - // OPTIONAL - Register the filter provider if you have custom filters that need DI. - // Also hook the filters up to controllers. - builder.RegisterWebApiFilterProvider(config); - builder.RegisterType() - .AsWebApiActionFilterFor() - .InstancePerRequest(); + // OPTIONAL - Register the filter provider if you have custom filters that need DI. + // Also hook the filters up to controllers. + builder.RegisterWebApiFilterProvider(config); + builder.RegisterType() + .AsWebApiActionFilterFor() + .InstancePerRequest(); - // Register a logger service to be used by the controller and middleware. - builder.Register(c => new Logger()).As().InstancePerRequest(); + // Register a logger service to be used by the controller and middleware. + builder.Register(c => new Logger()).As().InstancePerRequest(); - // Autofac will add middleware to IAppBuilder in the order registered. - // The middleware will execute in the order added to IAppBuilder. - builder.RegisterType().InstancePerRequest(); - builder.RegisterType().InstancePerRequest(); + // Autofac will add middleware to IAppBuilder in the order registered. + // The middleware will execute in the order added to IAppBuilder. + builder.RegisterType().InstancePerRequest(); + builder.RegisterType().InstancePerRequest(); - // Create and assign a dependency resolver for Web API to use. - var container = builder.Build(); - config.DependencyResolver = new AutofacWebApiDependencyResolver(container); + // Create and assign a dependency resolver for Web API to use. + var container = builder.Build(); + config.DependencyResolver = new AutofacWebApiDependencyResolver(container); - // The Autofac middleware should be the first middleware added to the IAppBuilder. - // If you "UseAutofacMiddleware" then all of the middleware in the container - // will be injected into the pipeline right after the Autofac lifetime scope - // is created/injected. - // - // Alternatively, you can control when container-based - // middleware is used by using "UseAutofacLifetimeScopeInjector" along with - // "UseMiddlewareFromContainer". As long as the lifetime scope injector - // comes first, everything is good. - app.UseAutofacMiddleware(container); + // The Autofac middleware should be the first middleware added to the IAppBuilder. + // If you "UseAutofacMiddleware" then all of the middleware in the container + // will be injected into the pipeline right after the Autofac lifetime scope + // is created/injected. + // + // Alternatively, you can control when container-based + // middleware is used by using "UseAutofacLifetimeScopeInjector" along with + // "UseMiddlewareFromContainer". As long as the lifetime scope injector + // comes first, everything is good. + app.UseAutofacMiddleware(container); - // Again, the alternative to "UseAutofacMiddleware" is something like this: - // app.UseAutofacLifetimeScopeInjector(container); - // app.UseMiddlewareFromContainer(); - // app.UseMiddlewareFromContainer(); + // Again, the alternative to "UseAutofacMiddleware" is something like this: + // app.UseAutofacLifetimeScopeInjector(container); + // app.UseMiddlewareFromContainer(); + // app.UseMiddlewareFromContainer(); - // Make sure the Autofac lifetime scope is passed to Web API. - app.UseAutofacWebApi(config); - app.UseWebApi(config); - } + // Make sure the Autofac lifetime scope is passed to Web API. + app.UseAutofacWebApi(config); + app.UseWebApi(config); } } diff --git a/src/WebApiExample.OwinSelfHost/TestController.cs b/src/WebApiExample.OwinSelfHost/TestController.cs index 3eb616c..bd4acbd 100644 --- a/src/WebApiExample.OwinSelfHost/TestController.cs +++ b/src/WebApiExample.OwinSelfHost/TestController.cs @@ -1,21 +1,20 @@ using System.Web.Http; -namespace WebApiExample.OwinSelfHost +namespace WebApiExample.OwinSelfHost; + +public class TestController : ApiController { - public class TestController : ApiController - { - private readonly ILogger _logger; + private readonly ILogger _logger; - public TestController(ILogger logger) - { - _logger = logger; - } + public TestController(ILogger logger) + { + _logger = logger; + } - public string Get() - { - _logger.Write("Inside the 'Get' method of the '{0}' controller.", GetType().Name); + public string Get() + { + _logger.Write("Inside the 'Get' method of the '{0}' controller.", GetType().Name); - return "Hello, world!"; - } + return "Hello, world!"; } } diff --git a/src/WebFormsExample/About.aspx.cs b/src/WebFormsExample/About.aspx.cs index 9123ce4..4e1ab7f 100644 --- a/src/WebFormsExample/About.aspx.cs +++ b/src/WebFormsExample/About.aspx.cs @@ -1,8 +1,7 @@ using System.Web.UI; -namespace WebFormsExample +namespace WebFormsExample; + +public partial class About : Page { - public partial class About : Page - { - } } diff --git a/src/WebFormsExample/Default.aspx.cs b/src/WebFormsExample/Default.aspx.cs index d02d7b1..b1757ff 100644 --- a/src/WebFormsExample/Default.aspx.cs +++ b/src/WebFormsExample/Default.aspx.cs @@ -3,21 +3,20 @@ using System.Web.UI; using WebFormsExample.Dependencies; -namespace WebFormsExample +namespace WebFormsExample; + +[SuppressMessage("IDE1006", "IDE1006", Justification = "Underscore is required to avoid conflict with reserved keyword 'default'.")] +public partial class _Default : Page { - [SuppressMessage("IDE1006", "IDE1006", Justification = "Underscore is required to avoid conflict with reserved keyword 'default'.")] - public partial class _Default : Page + // This property will be set for you by the PropertyInjectionModule. + public IDependency? Dependency { - // This property will be set for you by the PropertyInjectionModule. - public IDependency Dependency - { - get; set; - } + get; set; + } - protected void Page_Load(object sender, EventArgs e) - { - // Now you can use the property that was set for you. - DependencyLabel.Text = Dependency.InstanceId.ToString(); - } + protected void Page_Load(object sender, EventArgs e) + { + // Now you can use the property that was set for you. + DependencyLabel.Text = Dependency!.InstanceId.ToString(); } } diff --git a/src/WebFormsExample/Dependencies/Dependency.cs b/src/WebFormsExample/Dependencies/Dependency.cs index 9124dd5..54927b1 100644 --- a/src/WebFormsExample/Dependencies/Dependency.cs +++ b/src/WebFormsExample/Dependencies/Dependency.cs @@ -1,30 +1,29 @@ using System; -namespace WebFormsExample.Dependencies +namespace WebFormsExample.Dependencies; + +/// +/// Simple dependency implementation. +/// +public class Dependency : IDependency { /// - /// Simple dependency implementation. + /// Initializes a new instance of the class. /// - public class Dependency : IDependency + public Dependency() { - /// - /// Initializes a new instance of the class. - /// - public Dependency() - { - InstanceId = Guid.NewGuid(); - } + InstanceId = Guid.NewGuid(); + } - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - public Guid InstanceId - { - get; private set; - } + /// + /// Gets the unique instance ID for the dependency. + /// + /// + /// A that indicates the unique ID for the + /// instance. + /// + public Guid InstanceId + { + get; private set; } } diff --git a/src/WebFormsExample/Dependencies/IDependency.cs b/src/WebFormsExample/Dependencies/IDependency.cs index 89c2d23..433f6ac 100644 --- a/src/WebFormsExample/Dependencies/IDependency.cs +++ b/src/WebFormsExample/Dependencies/IDependency.cs @@ -1,23 +1,22 @@ using System; -namespace WebFormsExample.Dependencies +namespace WebFormsExample.Dependencies; + +/// +/// Demonstration dependency interface that allows you to inspect the unique +/// ID on a specific resolved instance of the dependency. +/// +public interface IDependency { /// - /// Demonstration dependency interface that allows you to inspect the unique - /// ID on a specific resolved instance of the dependency. + /// Gets the unique instance ID for the dependency. /// - public interface IDependency + /// + /// A that indicates the unique ID for the + /// instance. + /// + Guid InstanceId { - /// - /// Gets the unique instance ID for the dependency. - /// - /// - /// A that indicates the unique ID for the - /// instance. - /// - Guid InstanceId - { - get; - } + get; } } diff --git a/src/WebFormsExample/Global.asax.cs b/src/WebFormsExample/Global.asax.cs index 4e64cd1..1ba3d62 100644 --- a/src/WebFormsExample/Global.asax.cs +++ b/src/WebFormsExample/Global.asax.cs @@ -6,44 +6,43 @@ using Microsoft.AspNet.FriendlyUrls; using WebFormsExample.Dependencies; -namespace WebFormsExample +namespace WebFormsExample; + +public class Global : HttpApplication, IContainerProviderAccessor { - public class Global : HttpApplication, IContainerProviderAccessor - { - // Provider that holds the application container. - private static IContainerProvider _containerProvider; + // Provider that holds the application container. + private static IContainerProvider? _containerProvider; - // Instance property that will be used by Autofac HttpModules - // to resolve and inject dependencies. - public IContainerProvider ContainerProvider + // Instance property that will be used by Autofac HttpModules + // to resolve and inject dependencies. + public IContainerProvider ContainerProvider + { + get { - get - { - return _containerProvider; - } + return _containerProvider!; } + } - public static void RegisterRoutes(RouteCollection routes) + public static void RegisterRoutes(RouteCollection routes) + { + var settings = new FriendlyUrlSettings { - var settings = new FriendlyUrlSettings - { - AutoRedirectMode = RedirectMode.Permanent - }; - routes.EnableFriendlyUrls(settings); - } + AutoRedirectMode = RedirectMode.Permanent + }; + routes.EnableFriendlyUrls(settings); + } - private void Application_Start(object sender, EventArgs e) - { - // Build up your application container and register your dependencies. - var builder = new ContainerBuilder(); - builder.RegisterType().As(); + private void Application_Start(object sender, EventArgs e) + { + // Build up your application container and register your dependencies. + var builder = new ContainerBuilder(); + builder.RegisterType().As(); - // Once you're done registering things, set the container - // provider up with your registrations. - _containerProvider = new ContainerProvider(builder.Build()); + // Once you're done registering things, set the container + // provider up with your registrations. + _containerProvider = new ContainerProvider(builder.Build()); - // Standard web forms startup. - RegisterRoutes(RouteTable.Routes); - } + // Standard web forms startup. + RegisterRoutes(RouteTable.Routes); } } diff --git a/src/WebFormsExample/Site.Master.cs b/src/WebFormsExample/Site.Master.cs index 3fb4733..51bf62a 100644 --- a/src/WebFormsExample/Site.Master.cs +++ b/src/WebFormsExample/Site.Master.cs @@ -1,13 +1,12 @@ using System; using System.Web.UI; -namespace WebFormsExample +namespace WebFormsExample; + +public partial class SiteMaster : MasterPage { - public partial class SiteMaster : MasterPage + protected void Page_Load(object sender, EventArgs e) { - protected void Page_Load(object sender, EventArgs e) - { - } } } diff --git a/src/WebFormsExample/WebFormsExample.csproj b/src/WebFormsExample/WebFormsExample.csproj index 78eefe1..88a6004 100644 --- a/src/WebFormsExample/WebFormsExample.csproj +++ b/src/WebFormsExample/WebFormsExample.csproj @@ -1,11 +1,12 @@  + ../../build/AspNet.ruleset net481 Library bin/ false - MvcExample - MvcExample + WebFormsExample + WebFormsExample true