Configure NServicebus in Asp.net Core 5 - asp.net-core

I am using the NServiceBus.Extensions.Hosting extension to configure NServicebus
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseNServiceBus(c =>
{
var endpointConfiguration = new EndpointConfiguration("nsb.medusa");
endpointConfiguration.UseTransport<RabbitMQTransport>().ConnectionString("How do I access app settings?");
endpointConfiguration.SendOnly();
return endpointConfiguration;
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
The problem I am having is that I don't know how to get an instance of IConfiguration from a IHostBuilder. I need IConfiguration so I can get the connection string to RabbitMQ.
Also can this be moved to the startup class?

Microsoft has some excellent documentation. After reading it I just added two lines of code and I can now access the configuration.
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseNServiceBus(c =>
{
var configuration = c.Configuration; /* New */
var cnnStr = configuration.GetSection("mq:connection").Value; /* New */
var endpointConfiguration = new EndpointConfiguration("nsb.medusa");
endpointConfiguration.UseTransport<RabbitMQTransport>().ConnectionString(cnnStr);
endpointConfiguration.SendOnly();
return endpointConfiguration;
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}

Related

ASP.NET core how could i get my websites url/hostname when the program starts up

I need to get my site's host name so I can change the directory of the JSON file that I am adding to my project. I just have no clue how I can collect the URL.
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) => {
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
config.SetBasePath(Directory.GetCurrentDirectory()).AddJsonFile("wwwroot/sites/"environment"/"environment".json", optional: false, reloadOnChange: true);
})
.UseStartup<Startup>()
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddLog4Net();
logging.SetMinimumLevel(LogLevel.Information);
});
You can get the url in the following ways.
public static void Main()
{
var host = BuildWebHost(null);
host.Start();
var serverAddress = host.ServerFeatures.Get<IServerAddressesFeature>().Addresses;
foreach (var address in serverAddress)
{
var uri = new Uri(address);
var port = uri.Port;
Console.WriteLine($"Bound to port: {port}");
}
host.WaitForShutdown();
}
private static IWebHost BuildWebHost(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.Build();
}

Hooking into SignalR event in Blazor ServerSide

I have found this piece of code for the default logging mechanism provided by Microsoft:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.AddConsole();
logging.AddFilter(
"Microsoft.AspNetCore.SignalR", LogLevel.Trace);
logging.AddFilter(
"Microsoft.AspNetCore.Http.Connections",
LogLevel.Trace);
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
My set for Serilog is as follows:
public class Program
{
public static void Main(string[] args)
{
try
{
using IHost host = CreateHostBuilder(args).Build();
host.Run();
}
catch (Exception ex)
{
if (Log.Logger == null || Log.Logger.GetType().Name == "SilentLogger")
{
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.WriteTo.Console()
.CreateLogger();
}
Log.Fatal(ex, "Host terminated unexpectedly");
}
finally
{
Log.CloseAndFlush();
}
}
private static IHostBuilder CreateHostBuilder(string[] args)
=> Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory(Register))
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>()
.CaptureStartupErrors(true)
.ConfigureAppConfiguration(config => { config.AddJsonFile("appsettings.Local.json", optional: true); })
.UseSerilog((hostingContext, loggerConfiguration) =>
{
loggerConfiguration
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext()
.Enrich.WithProperty("ApplicationName", typeof(Program).Assembly.GetName().Name)
.Enrich.WithProperty("Environment", hostingContext.HostingEnvironment);
#if DEBUG
loggerConfiguration.Enrich.WithProperty("DebuggerAttached", Debugger.IsAttached);
#endif
});
});
private static void Register(ContainerBuilder builder) => builder.RegisterLogger(autowireProperties: true);
}
How do I add SignalR filters to my setup?
In Serilog terminology you need to override the minimum level for the Microsoft SignalR namespaces.
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.UseSerilog((context, config) =>
{
/*
* the rest of the Serilog configuration here
*/
config.MinimumLevel.Override("Microsoft.AspNetCore.SignalR", LogEventLevel.Debug);
config.MinimumLevel.Override("Microsoft.AspNetCore.Http.Connections", LogEventLevel.Debug);
})
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });

Implementing Autofac in .NET Core 3 Console Application, injecting IServiceProvider into Config class (not working?)

This might be a "stupid" question but I'm kind of lost, I'm trying to implement Autofac into a working .NET Core 3.1 Console Application but can't seem to get some things to work.
I have a class named Config.cs that are used at multiple places the console application so I'd like to keep that file so as to not rewrite this implementation.
Here is that file
public class Config : IConfig
{
readonly IConfiguration _config;
public Config(IServiceProvider services)
{
_config = (IConfiguration)services.GetService(typeof(IConfiguration));
}
public string StorageConnectionString => _config["ConnectionStrings:StorageConnectionString"];
public string SqlConnectionString => _config["ConnectionStrings:SqlConnectionString"];
public string MongoConnectionString => _config["ConnectionStrings:MongoConnectionString"];
public string RayGunApiKey => _config["RayGunApiKey"];
public string ElasticsearchUri => _config["Uris:ElasticsearchUri"];
public string StatsDUri => _config["Uris:StatsDUri"];
public string Get(string key) => _config[key];
}
This is first used in Functions.cs in a TimeTrigger:
public class Functions
{
readonly IConfig _config;
public Functions(ILogger<Functions> logger, IConfig config)
{
_logger = logger;
_config = config;
}
public void Run([TimerTrigger("00:00:01", RunOnStartup = true, UseMonitor = true)]TimerInfo myTimer)
{
...
}
}
But when I start the console application an error is thrown
System.InvalidOperationException: Unable to resolve service for type 'DataPurger.IConfig' while attempting to activate 'DataPurger.Functions'.
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired)
at lambda_method(Closure , IServiceProvider , Object[] )
at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IServiceProvider serviceProvider) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs:line 37
at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstance[T](IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\DefaultJobActivator.cs:line 32
at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.<>c__DisplayClass1_1.<.ctor>b__0(IFunctionInstanceEx i) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs:line 20
at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory`1.Create(IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\ActivatorInstanceFactory.cs:line 26
at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`2.CreateInstance(IFunctionInstanceEx functionInstance) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionInvoker.cs:line 44
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ParameterHelper.Initialize() in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 846
at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.TryExecuteAsyncCore(IFunctionInstanceEx functionInstance, CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Executors\FunctionExecutor.cs:line 117
This injection works without Autofac, but I'm "forced" to implement it since Autofac is used in every other project where I'm working.
Here is the Program.cs
static void Main(string[] args)
{
RegisterServices();
CreateHostBuilder(args).Build().RunAsync().Wait();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((context, config) =>
{
config.AddEnvironmentVariables();
config.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);
config.AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true,
reloadOnChange: true);
})
.ConfigureLogging((context, b) =>
{
b.AddConsole();
})
.ConfigureServices(s =>
{
s.AddLogging();
s.AddOptions();
})
.ConfigureWebJobs(builder =>
{
builder.AddAzureStorageCoreServices();
builder.AddExecutionContextBinding();
builder.AddTimers();
})
.UseConsoleLifetime()
.UseServiceProviderFactory(new AutofacServiceProviderFactory());
static void RegisterServices()
{
var collection = new ServiceCollection();
var builder = new ContainerBuilder();
builder.RegisterModule<BaseModule>();
builder.Populate(collection);
var container = builder.Build();
_serviceProvider = new AutofacServiceProvider(container);
}
public class BaseModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Config>().As<IConfig>().SingleInstance();
}
}
What am I doing wrong, I'm sure there is something missing or that I did not understand correctly?
It is my sample for ASP .Net core 3.1
in Program.cs I changed
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory(new AutofacServiceProviderFactory()) //<-like yours
.UseSerilog()
.ConfigureLogging((context, builder) => builder.AddSerilog())
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
and I added to Startup.cs
public void ConfigureContainer(ContainerBuilder builder)
{
builder.RegisterType<QuartzWrapper>().As<IQuartzWrapper>().SingleInstance();
builder.Register(provider => new JobFactory(provider)).As<IJobFactory>().InstancePerDependency();
builder.RegisterType<JobClass>().As<IJob>().InstancePerDependency();
}
and I used the next packages:
Autofac - Version="5.1.2"
Autofac.Extensions.DependencyInjection - Version="6.0.0"
You need to try and check how it works without the module, change
builder.RegisterModule<BaseModule>();
to
builder.RegisterType<Config>().As<IConfig>().SingleInstance();

Unable to create an object of type ApplicationDbContext that inherits from IdentityDBContext after migration to 3.0

When I try to add a migration after migration to .net core 3.0 and ef core 3.0 I get the error: Unable to create an object of type 'ApplicationDbContext'.
Dependencies are as follows:
My code is as follows:
ApplicationDbContext.cs
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, ILocalizationDbContext
{
private readonly IServiceProvider _serviceProvider;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options,
IServiceProvider serviceProvider)
: base(options)
{
_serviceProvider = serviceProvider;
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly("Infrastructure")),
ServiceLifetime.Transient);
services.AddDefaultIdentity<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
}
Program.cs
public class Program
{
public static void Main(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>();
})
.Build();
host.Run();
}
}
As the link in the error message says, update your Program class to look like this.
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args)
.Build();
host.Run();
}
// EF Core uses this method at design time to access the DbContext
public static IHostBuilder CreateHostBuilder(string[] args)
=> Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>();
});
}

Asp.net core get logger in ConfigureAppConfiguration

I would like to use logger in "TODO" line, because I need to log when I add a "AddJsonConfigurationSourceDecryption" method, Is there any way to get a logger?
Logging in ASP.NET Core
public class Program
{
public static void Main(string[] args)
{
ILogger<Program> logger = null;
try
{
var host = CreateWebHostBuilder(args).Build();
ApplicationLogging.LoggerFactory = host.Services.GetRequiredService<ILoggerFactory>();
logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("start thin API service...");
host.Run();
}
catch (Exception ex)
{
logger?.LogError(ex, "Stopped program because of exception");
throw;
}
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args)
{
return WebHost.CreateDefaultBuilder(args)
.UseKestrel(option => option.AddServerHeader = false)
.ConfigureLogging((host, builder) => { builder.SetMinimumLevel(LogLevel.Trace); })
.UseNLog()
.ConfigureServices(services => services.AddAutofac())
.ConfigureAppConfiguration((context, builder) =>
{
//TODO: Logger.............
builder.SetBasePath(Directory.GetCurrentDirectory());
builder.AddJsonConfigurationSourceDecryption();
})
.UseStartup<Startup>();
}
}
#0xced answered this question here
How to create a LoggerFactory with a ConsoleLoggerProvider?
as of dotnetcore3.1 the code could be written this way
private static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args).ConfigureAppConfiguration(
(hostContext, config) =>
{
var loggerFactory = LoggerFactory.Create(
builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("YourProgramNamespsace.Program", LogLevel.Debug)
.AddConsole();
});
var logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Hello from ConfigureAppConfiguration");
...
})