Serilog Setup with Two stage in .NET 6 RC1 using Minimal API - serilog

I could not find any example of using serilog configuration with Two stage setup in .NET 6 RC1 with minimal API

Just use this line :
builder.WebHost.UseSerilog();
Sample Code :
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.Enrich.FromLogContext()
.WriteTo.Console()
.CreateLogger();
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<DapperService>();
builder.WebHost.UseSerilog(); // <===============
// Build configuration
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetParent(AppContext.BaseDirectory).FullName)
.AddJsonFile("appsettings.json", false)
.Build();
// Add access to generic IConfigurationRoot
builder.Services.AddSingleton<IConfigurationRoot>(configuration);
var app = builder.Build();

builder.Host.UseSerilog((ctx, lc) => lc .WriteTo.Console() .WriteTo.File("Your File Path"));

Related

Windows Service with .NET 6 not running with WebApplication builder

I am having the following error when trying to create a windows service:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.NotSupportedException: The content root changed from "C:\WINDOWS\system32" to "C:\foo\foo\publish". Changing the host configuration using WebApplicationBuilder.Host is not supported. Use WebApplication.CreateBuilder(WebApplicationOptions) instead.
My builder:
var builder = WebApplication.CreateBuilder(args);
builder.Services...
builder.Host.UseWindowsService();
builder.Host.UseSerilog((ctx, lc) => lc
.WriteTo.Console()
.WriteTo.File(_logDir)
.ReadFrom.Configuration(ctx.Configuration));
WebApplication app = builder.Build();
app.Run();
It works with IHostBuilder:
public static IHostBuilder CreateServiceHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseWindowsService()
..
What am I doing wrong?
As the error says, you need to set your ContentRootPath with WebApplicationOptions
var builder = WebApplication.CreateBuilder(new WebApplicationOptions
{
ContentRootPath = #"C:\foo\foo\publish",
Args = args
});

How to handle deprecation of IWebHostBuilder.UseSerilog() when IWebHostBuilder is still needed?

The UseSerilog() extension is deprecated* for IWebHostBuilder in serilog-aspnetcore version 5.0.0. However I'm still using a IWebHostBuilder and a Startup class (aspnetcore 6), and IWebHostBuilder is not deprecated.
Since deprecation implies future removal, how should I leverage Serilog going forward?
reference:
https://github.com/serilog/serilog-aspnetcore/releases/tag/v5.0.0
"mark IWebHostBuilder extensions as obsolete on platforms with IHostBuilder"
I was able to get this to work by switching to IHostBuilder instead of IWebHostBuilder. The key in my case was to call ConfigureWebHostDefaults (or ConfigureWebHost), where you can then utilize an IWebHostBuilder.
In this way, I could call UseSerilog on the IHostBuilder while still utilizing the Startup class as before with an IWebHostBuilder.
Example:
public static void Main(string[] args)
{
// temp initial logging
Log.Logger = new LoggerConfiguration()
.WriteTo.Console()
.CreateBootstrapLogger();
using var app =
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webHostBuilder
=> webHostBuilder.ConfigureAppConfiguration((hostingContext, config) =>
_ = config.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("appsettings.json", false, true))
.UseStartup<Startup>())
.UseSerilog(
(hostingContext, loggerConfig) =>
loggerConfig
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext(),
writeToProviders: true)
.Build();
app.Run();
}
I Solved with:
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseSerilog();

Filtering events via ByIncludingOnly

I've got a situation where some log events contain large property values (in this particular case, a large packet of XML). I want to use Serilog's ByIncludingOnly functionality to use an additional sink for these large data events. Here's a sample of what I thought would work:
private static void FilteredLogging()
{
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new RawFormatter())
.WriteTo.Logger(lc => lc.Filter.ByIncludingOnly(LargeDataPackets))
.WriteTo.File("big.txt")
.CreateLogger();
Log.Information("go");
Log.ForContext("data", "12345").Information("Small packet");
Log.ForContext("data", "1234567890987654321").Information("Big packet");
Log.CloseAndFlush();
}
private static bool LargeDataPackets(LogEvent le)
{
return le.Properties.ContainsKey("data") &&
le.Properties["data"].ToString().Length > 10;
}
However, when I run this code, all three messages go to the "big.txt" file. I would expect only the last item ("Big packet") to go to the file since it's the only event with a data property that is over 10 characters.
I'm using Serilog 2.0.
Your parentheses are slightly off in:
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new RawFormatter())
.WriteTo.Logger(lc => lc.Filter.ByIncludingOnly(LargeDataPackets))
.WriteTo.File("big.txt")
.CreateLogger();
Should be:
Log.Logger = new LoggerConfiguration()
.WriteTo.Console(new RawFormatter())
.WriteTo.Logger(lc => lc.Filter.ByIncludingOnly(LargeDataPackets)
.WriteTo.File("big.txt"))
.CreateLogger();

AWS Elastic Beanstalk environment variables in ASP.NET Core 1.0

How do I get environment variables from elastic beanstalk into an asp.net core mvc application? I have added a .ebextensions folder with app.config file in it with the following:
option_settings:
- option_name: HelloWorld
value: placeholder
- option_name: ASPNETCORE_ENVIRONMENT
value: placeholder
The .ebextensions folder is included in the publish package.
On deployment, both the variables are visible in the aws elasticbeanstalk console at Configuration > Software Configuration > Environment Variables
However, when I try to read the variables in the application, none of the below options are working:
Environment.GetEnvironmentVariable("HelloWorld") // In controller
Configuration["HelloWorld"] // In startup.cs
Any ideas on what I could be missing? Thanks.
I just implemented a slightly other solution which injects the beanstalk environment variables to the program so that you may access them by Environment.GetEnvironmentVariable():
private static void SetEbConfig()
{
var tempConfigBuilder = new ConfigurationBuilder();
tempConfigBuilder.AddJsonFile(
#"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration",
optional: true,
reloadOnChange: true
);
var configuration = tempConfigBuilder.Build();
var ebEnv =
configuration.GetSection("iis:env")
.GetChildren()
.Select(pair => pair.Value.Split(new[] { '=' }, 2))
.ToDictionary(keypair => keypair[0], keypair => keypair[1]);
foreach (var keyVal in ebEnv)
{
Environment.SetEnvironmentVariable(keyVal.Key, keyVal.Value);
}
}
Simply call SetEbConfig(); before building your webhost. With this solution, also AWS SDK does read it's settings like AWS_ACCESS_KEY_ID correctly.
Had the same problem, and just received a reply from AWS support about this issue. Apparently environment variables are not properly injected into ASP.NET Core applications in elastic beanstalk.
As far as I know, they're working to fix the problem.
The workaround is to parse C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration into the configuration builder. This file is part of your elastic beanstalk environment and should be accessible upon deploying your project.
First add the file:
var builder = new ConfigurationBuilder()
.SetBasePath("C:\\Program Files\\Amazon\\ElasticBeanstalk\\config")
.AddJsonFile("containerconfiguration", optional: true, reloadOnChange: true);
Then access the values:
var env = Configuration.GetSection("iis:env").GetChildren();
foreach (var envKeyValue in env)
{
var splitKeyValue = envKeyValue.Value.Split('=');
var envKey = splitKeyValue[0];
var envValue = splitKeyValue[1];
if (envKey == "HelloWorld")
{
// use envValue here
}
}
Courtesy of
G.P. from
Amazon Web Services
I implemented the other answer to create a convenient workaround to load the environment properties from Elastic Beanstalk directly into your ASP.NET Core app configuration.
For ASP.NET Core 2.0 - edit your Program.cs
Note that this WebHost build was taken from the source code of WebHostBuilder.CreateDefaultBuilder()
https://github.com/aspnet/MetaPackages/blob/dev/src/Microsoft.AspNetCore/WebHost.cs
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.AspNetCore.Server.Kestrel.Core.Internal;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace NightSpotAdm
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args)
{
// TEMP CONFIG BUILDER TO GET THE VALUES IN THE ELASTIC BEANSTALK CONFIG
IConfigurationBuilder tempConfigBuilder = new ConfigurationBuilder();
tempConfigBuilder.AddJsonFile(
#"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration",
optional: true,
reloadOnChange: true
);
IConfigurationRoot tempConfig = tempConfigBuilder.Build();
Dictionary<string, string> ebConfig = ElasticBeanstalk.GetConfig(tempConfig);
// START WEB HOST BUILDER
IWebHostBuilder builder = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory());
// CHECK IF EBCONFIG HAS ENVIRONMENT KEY IN IT
// IF SO THEN CHANGE THE BUILDERS ENVIRONMENT
const string envKey = "ASPNETCORE_ENVIRONMENT";
if (ebConfig.ContainsKey(envKey))
{
string ebEnvironment = ebConfig[envKey];
builder.UseEnvironment(ebEnvironment);
}
// CONTINUE WITH WEB HOST BUILDER AS NORMAL
builder.ConfigureAppConfiguration((hostingContext, config) =>
{
IHostingEnvironment env = hostingContext.HostingEnvironment;
// ADD THE ELASTIC BEANSTALK CONFIG DICTIONARY
config.AddJsonFile(
"appsettings.json",
optional: true,
reloadOnChange: true
)
.AddJsonFile(
$"appsettings.{env.EnvironmentName}.json",
optional: true,
reloadOnChange: true
)
.AddInMemoryCollection(ebConfig);
if (env.IsDevelopment())
{
Assembly appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
}
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.UseIISIntegration()
.UseDefaultServiceProvider(
(context, options) => { options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); })
.ConfigureServices(
services =>
{
services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerOptionsSetup>();
});
return builder.UseStartup<Startup>().Build();
}
}
public static class ElasticBeanstalk
{
public static Dictionary<string, string> GetConfig(IConfiguration configuration)
{
return
configuration.GetSection("iis:env")
.GetChildren()
.Select(pair => pair.Value.Split(new[] { '=' }, 2))
.ToDictionary(keypair => keypair[0], keypair => keypair[1]);
}
}
}
For ASP.NET Core 1.0
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile(#"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
var config = builder.Build();
builder.AddInMemoryCollection(GetEbConfig(config));
Configuration = builder.Build();
}
private static Dictionary<string, string> GetEbConfig(IConfiguration configuration)
{
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (IConfigurationSection pair in configuration.GetSection("iis:env").GetChildren())
{
string[] keypair = pair.Value.Split(new [] {'='}, 2);
dict.Add(keypair[0], keypair[1]);
}
return dict;
}
Instead of having to parse the containerconfiguration you can leverage the ebextensions options to set the variable as part of your deploy process:
commands:
set_environment:
command: setx ASPNETCORE_ENVIRONMENT "Development" /M
This will set a global environment variable as part of your application deployment. This variable use-case is officially supported and documented by Microsoft.
After deploying your app you can verify the setting is set correctly in the EC2 instance:
AWS addressed this issue in the Elastic Beanstalk Windows Server platform update on June 29, 2020:
Previously, Elastic Beanstalk didn't support passing environment variables to .NET Core applications and multiple-application IIS deployments that use a deployment manifest [1]. The Elastic Beanstalk Windows Server platform update on June 29, 2020 [2] now fixes this gap. For details, see Configuring your .NET environment in the Elastic Beanstalk console [3].
[1] https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/dotnet-manifest.html
[2] https://docs.aws.amazon.com/elasticbeanstalk/latest/relnotes/release-2020-06-29-windows.html
[3] https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_NET.container.console.html#dotnet-console
Above solution doesnt helped me to load config file based on enviroment settings. So here is my solution AWS ElasticBeansTalk "hack"
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{GetEnvVariableAWSBeansTalkHack(env)}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
private static string GetEnvVariableAWSBeansTalkHack(IHostingEnvironment env)
{
var config = new ConfigurationBuilder()
.AddJsonFile(#"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration", optional: true, reloadOnChange: true).Build();
Dictionary<string, string> dict = new Dictionary<string, string>();
foreach (IConfigurationSection pair in config.GetSection("iis:env").GetChildren())
{
string[] keypair = pair.Value.Split(new[] { '=' }, 2);
dict.Add(keypair[0], keypair[1]);
}
return dict.ContainsKey("ASPNETCORE_ENVIRONMENT")
? dict["ASPNETCORE_ENVIRONMENT"]
: env.EnvironmentName;
}
You can create an implementation of Microsoft.Extensions.Configuration.
Also available at https://gist.github.com/skarllot/11e94ed8901a9ddabdf05c0e5c08dbc5.
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json.Linq;
using System.IO;
using System.Linq;
namespace Microsoft.Extensions.Configuration.AWS
{
public class AmazonEBConfigurationProvider : ConfigurationProvider
{
private const string ConfigurationFilename = #"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration";
public override void Load()
{
if (!File.Exists(ConfigurationFilename))
return;
string configJson;
try
{
configJson = File.ReadAllText(ConfigurationFilename);
}
catch
{
return;
}
var config = JObject.Parse(configJson);
var env = (JArray)config["iis"]["env"];
if (env.Count == 0)
return;
foreach (var item in env.Select(i => (string)i))
{
int eqIndex = item.IndexOf('=');
Data[item.Substring(0, eqIndex)] = item.Substring(eqIndex + 1);
}
}
}
public class AmazonEBConfigurationSource : IConfigurationSource
{
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
return new AmazonEBConfigurationProvider();
}
}
public static class AmazonEBExtensions
{
public static IConfigurationBuilder AddAmazonElasticBeanstalk(this IConfigurationBuilder configurationBuilder)
{
configurationBuilder.Add(new AmazonEBConfigurationSource());
return configurationBuilder;
}
}
}
Then use with your ConfigurationBuilder:
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", true, true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", true)
.AddAmazonElasticBeanstalk() // <-- Merge with other sources
.AddEnvironmentVariables();
.NET Core 2 + posrgresql RDS
Further to #sebastian's great answer above, I found that the settings were in a different part of the file, viz. plugins:rds:env.
Also there was no need to split on =, so the parsing code I have is:
private static void SetEbConfig()
{
var tempConfigBuilder = new ConfigurationBuilder();
tempConfigBuilder.AddJsonFile(
#"C:\Program Files\Amazon\ElasticBeanstalk\config\containerconfiguration",
optional: true,
reloadOnChange: true
);
var configuration = tempConfigBuilder.Build();
var ebEnv = configuration.GetSection("plugins:rds:env")
.GetChildren()
.ToDictionary(child => child.Key, child => child.Value);
foreach (var keyVal in ebEnv)
{
Environment.SetEnvironmentVariable(keyVal.Key, keyVal.Value);
}
}
The relevant (and redacted ;-)) JSON is as follows:
{
"plugins": {
"rds": {
"Description": "RDS Environment variables",
"env": {
"RDS_PORT": "....",
"RDS_HOSTNAME": "....",
"RDS_USERNAME": "....",
"RDS_DB_NAME": "....",
"RDS_PASSWORD": "...."
}
}
}
}
(This reply is separate since I don't have rep to comment...)
This can definitely be done in an .ebextensions folder. Simply create a new file in your .ebextensions folder (I used a name of "options.config"), mark it as "copy if newer" or "copy always" and make sure you use the option_settings header with a aws:elasticbeanstalk:application:environment namespace:
option_settings:
aws:elasticbeanstalk:application:environment:
MyEnvVar: SomeValue
EDIT: I forgot to include a link to the docs!
https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environments-cfg-softwaresettings.html
Update for ASP.net Core 3
Set ASPNETCORE_ENVIRONMENT environment variable in Elastic Beanstalk to Staging, Production, Development...
In Core project create appsettings.Staging.json and this configuration will be used when this the project is deployed.

How to configure Autofac and SignalR in a MVC 5 application

I am trying to configure an MVC 5 application to use SignalR 2.2.x and inject a service into my NotificationsHub.
We are using Autofac for MVC but I am not sure on how to correctly configure this.
Autofac documentation exists for NuGet Autofac.Integration.SignalR (3.0.2) and Autofac.Integration.Mvc (3.3.4).
What I am doing so far is register the hubs via:
ContainerBuilder builder = new ContainerBuilder();
// Register MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly);
builder.RegisterType<ServiceForSignalRHub>().AsImplementedInterfaces();
builder.RegisterType<...>().AsImplementedInterfaces();
builder.RegisterHubs(Assembly.GetExecutingAssembly());
IContainer container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
However the call to .SetResolver(...) is ambigious as it exists in both MVC and SignalR integration packages. Now what? I am unable to confirm if the contructor injection of my service works for the Hub I am using.
EDIT
I can configure MVC5 with Autofac just fine. Where I get lost is how to do the same with SignalR, using the Autofac Signal integration NuGet.
Please see below.
This is my startup class:
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var defaultFactory = LogManager.Use<DefaultFactory>();
defaultFactory.Directory("#D:\\NServiceBus\\ );
defaultFactory.Level(LogLevel.Debug);
var container = ConfigureAutofac(app);
ConfigureServiceBus(container, app);
app.UseAutofacMiddleware(container); // REGISTER WITH OWIN
app.UseAutofacMvc();
ConfigureAuth(app);
GlobalConfiguration.Configuration.UseSqlServerStorage("hangfire");
ConfigureSignalR(app);
}
}
This is the part where I configure SignalR:
public partial class Startup
{
public void ConfigureSignalR(IAppBuilder app)
{
var builder = new ContainerBuilder();
builder.RegisterHubs(Assembly.GetExecutingAssembly()).PropertiesAutowired();
builder.RegisterType<MaintenanceService>().As<IMaintenanceService>().PropertiesAutowired();
var container = builder.Build();
//var container = new AutofacContainer().Container;
var resolver = new AutofacDependencyResolver(container);
// Any connection or hub wire up and configuration should go here
app.MapSignalR(new HubConfiguration
{
Resolver = resolver,
EnableJSONP = true,
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
});
builder.RegisterInstance(resolver.Resolve<IConnectionManager>());
}
}
How can this be correctly done?
You should tell SignalR explicitly to use the AutofacDependencyResolver when you are mapping it.
I assume that you know that in your Startup class you have to call app.MapSignalR();
When you are mapping it, you should tell it to use the custom dependency resolver (the AutofacDependencyResolver).
Here's how I do it:
var resolver = new AutofacDependencyResolver(container);
app.MapSignalR(new HubConfiguration
{
Resolver = resolver
});
This way, you are telling SignalR directly which dependency resolver to use.
I have a GitHub repo for SignalR Dependency Injection, but it's not configured to use MVC. Still, I think it will give you a hint in how to create your configuration.
Note: If you are using the OWIN Middleware, be sure not to use the GlobalHost static property AT ALL since it will have massive inconsistencies.
A common error in OWIN integration is use of the GlobalHost. In OWIN
you create the configuration from scratch. You should not reference
GlobalHost anywhere when using the OWIN integration.
Again, check the repo I gave you to see how to do this.
Hope this helps:)
Best of luck!
I ended up with this (pay attention to comments):
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
IContainer container = AutofacConfig(app);
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
DependencyResolver.SetResolver(new Autofac.Integration.Mvc.AutofacDependencyResolver(container));
GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacWebApi(GlobalConfiguration.Configuration);
var hubConfiguration = new Microsoft.AspNet.SignalR.HubConfiguration()
{
// Resolve presolver from container
Resolver = container.Resolve<Microsoft.AspNet.SignalR.IDependencyResolver>(),
};
app.MapSignalR(hubConfiguration);
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
_
private static IContainer AutofacConfig(IAppBuilder app)
{
var builder = new ContainerBuilder();
RegisterSignalR(builder);
return builder.Build();
}
_
private static void RegisterSignalR(ContainerBuilder builder)
{
// Register Autofac resolver into container to be set into HubConfiguration later
builder.RegisterType<Autofac.Integration.SignalR.AutofacDependencyResolver>()
.As<Microsoft.AspNet.SignalR.IDependencyResolver>()
.SingleInstance();
// Register ConnectionManager as IConnectionManager so that you can get
// hub context via IConnectionManager injected to your service
builder.RegisterType<Microsoft.AspNet.SignalR.Infrastructure.ConnectionManager>()
.As<Microsoft.AspNet.SignalR.Infrastructure.IConnectionManager>()
.SingleInstance();
// Register hubs one by one
builder.RegisterType<MessageNotificationsHub>().ExternallyOwned();
builder.RegisterType<SystemNotificationsHub>().ExternallyOwned();
}
Thanks to #Nathan and his answer (originally found here) and logical thinking to figure out to register ConnectionManager as IConnectionManager
Install nuget package Autofac.SignalR, for example:
<package id="Autofac.SignalR" version="3.0.2" targetFramework="net471" />
Register your hubs
// during creation of the IContainer, register signalr hubs automatically
var executingAssembly = Assembly.GetExecutingAssembly();
builder.RegisterHubs(executingAssembly);
// alternatively register hubs individually
// ExternallyOwned() ensures SignalR is allowed to control disposal of the hubs rather than Autofac.
builder.RegisterType<NotificationHub>().ExternallyOwned();
Set signalr service locator
// replace the Signalr dependency resolver once your IContainer 'container' is ready
GlobalHost.DependencyResolver = new AutofacDependencyResolver(container);
// or this can alternatively be set in the HubConfiguration instance when using OWIN IAppBuilder map.RunSignalR(hubConfiguration);
var hubConfiguration = new HubConfiguration
{
Resolver = new AutofacDependencyResolver(container),
//...
}
For more information:
https://autofaccn.readthedocs.io/en/latest/integration/signalr.html
https://learn.microsoft.com/en-us/aspnet/signalr/overview/advanced/dependency-injection

Resources