I am trying to connect to database with connection string which is written in appsetting.json. I try to pass it in UseSqlServer("...") in AddDbContext but it just doesn't work. When I write it in Context class it works.
So, program runs without errors but it doesn't connect to Db.
Does someone know what is wrong here?
Below is Program.cs code:
using IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService(options =>
{
options.ServiceName = "Subscriber Service";
})
.ConfigureServices(services =>
{
services.AddHostedService<DeliveryService>()
.AddSingleton<IQueueService, QueueService>()
.AddSingleton<IMailTransport, MailTransport>()
.AddSingleton<IHttpTransport, HttpTransport>()
.AddDbContext<nbiot_core_svctestContext>(
options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));
})
.Build();
await host.RunAsync();
IHostBuilder.ConfigureServices accepts an action with two parameters, the first one is HostBuilderContext exposing configuration property (the one you are using comes from HostingHostBuilderExtensions), so try:
.ConfigureServices((ctx, services)=>
{
services
...
.AddDbContext<nbiot_core_svctestContext>(
options => options.UseSqlServer(ctx.Configuration.GetConnectionString("DefaultConnection"));
})
Related
I don't want to use CreateDefaultBuilder and ConfigureWebHostDefaults in Program.cs file. Both of these functions make certain assumptions, that I am not comfortable with, also I don't want to rely on ASP.net defaults. I want to setup builder myself but don't know how to do that
I want to replace following code with my own builder
var host = Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder =>
{
builder.Sources.Clear();
...
})
.ConfigureWebHostDefaults(webBuilder =>
{
...
})
.ConfigureServices((context, services) =>
services.Configure<...>(
context.Configuration.GetSection("...")))
.Build();
You can create an instance of HostBuilder directly:
var host = new HostBuilder()
.Build();
HostBuilder has a number of useful methods, such as ConfigureServices, ConfigureAppConfiguration, etc:
var host = new HostBuilder()
.ConfigureAppConfiguration(builder =>
{
// ...
})
.ConfigureServices((context, services) =>
{
// ...
})
.Build();
To configure the WebHost, without the defaults, use ConfigureWebHost:
var host = new HostBuilder()
.ConfigureWebHost(webHostBuilder =>
{
})
.Build();
I am trying to test my SignalR connections in my integration tests.
The client looks like this:
var connection = new HubConnectionBuilder()
.WithUrl(
$"{client.BaseAddress}meeting-notifications",
o =>
{
o.HttpMessageHandlerFactory = _ => Server?.CreateHandler();
})
.Build();
connection.On<BoardDto>("BoardStateChanged", board => { Do Something... });
await connection.StartAsync();
I am calling the method in my ASP-NET Core backend like so:
public async Task BroadcastBoardStateAsync(int boardId, BoardDto board)
{
await _notificationHub.Clients.All.BoardStateChanged(board);
}
The client is able to call a method on the server but not the other way around.
Does anyone know what I am missing here?
Edit: I debugged the server call and the _notificationHub contains the connection-id of the client.
Turns out SignalR v3.x does json serialization via System.Text.Json which had some problem with my POCO's.
To fix this, I had to explicitly tell SignalR to use NewtonsoftJson for serialization via this method call:
var connection = new HubConnectionBuilder()
.WithUrl(
$"{client.BaseAddress}meeting-notifications",
o =>
{
o.HttpMessageHandlerFactory = _ => Server?.CreateHandler();
})
----> .AddNewtonsoftJsonProtocol()
.Build();
The current version of the Microsoft.Azure.Functions.Extensions package exposes an additional property that allows you easy access to the IConfiguration provided to the function. Previously this required manually building a service provider, which was obviously problematic.
Using that package my FunctionsStartup.cs looks like this:
public override void Configure(IFunctionsHostBuilder builder)
{
base.Configure(builder);
var config = builder.GetContext().Configuration; // new in v1.1.0 of Microsoft.Azure.Functions.Extensions
var mySetting = config["MySetting"];
int.Parse(mySetting, out var mySetting);
// ... use mySetting...
}
In order to test my HTTP-triggered functions I've used this article as a base, which details how to manually build and start a host to execute my function as if it was running in Azure, similar to how TestServer works in ASP.NET Core:
var host = new HostBuilder()
.ConfigureWebJobs(new FunctionsStartup().Configure)
.Build();
var functionsInstance = ActivatorUtilities.CreateInstance<MyFunctions>(host.Services);
I can then execute the function methods defined on MyFunctions to test their responses:
var request = new DefaultHttpRequest(new DefaultHttpContext());
var response = (OkObjectResult)functionsInstance.HttpTriggerMethod(request);
... assert that response is valid
The problem is that when I run my tests, builder.GetContext().Configuration is returning null in FunctionsStartup.Configure, which of course causes those tests to fail. How can I work around this?
The article I linked to hasn't been updated to take into account the existence of builder.GetContext().Configuration, but you can make this work for testing purposes with a little tweaking. Instead of using:
var host = new HostBuilder()
.ConfigureWebJobs(new FunctionsStartup().Configure)
.Build();
you need to explicitly copy the host's settings into a new WebJobsBuilderContext that you then pass to your function's startup:
var host = new HostBuilder()
.ConfigureWebJobs((context, builder) => new FunctionsStartup().Configure(new WebJobsBuilderContext
{
ApplicationRootPath = context.HostingEnvironment.ContentRootPath,
Configuration = context.Configuration,
EnvironmentName = context.HostingEnvironment.EnvironmentName,
}, builder))
.Build();
I'm not sure if this is the completely correct way to achieve this, but it has worked well for me.
I'm using MassTransit with RabbitMqTransport.
Assume I have run IBusControl using:
var control = Bus.Factory.CreateUsingRabbitMq(c =>
{
var host = confgurator.Host(config.BuildHostUri(), h =>
{
...
});
...
});
await control.StartAsync();
Later I connected new endpoint to this running instance, using:
host.ConnectReceiveEndpoint(Configuration.QueueName, this.ConfigureEndpoint);
Is there a way to configure Publish/Send for new Message types at this moment also? By "configure Publish/Send" I mean using methods like existing on IRabbitMqBusFactoryConfigurator:
confgurator.Send<MessageContract>(_ =>
{
_.UseRoutingKeyFormatter(__ => Configuration.QueueName);
});
confgurator.Message<MessageContract>(x => x.SetEntityName(nameof(MessageContract)));
confgurator.Publish<MessageContract>(_ =>
{
...
}
As per Chris Patterson comment, configuring Publish/Send for message type can only be done during configuration, prior to starting the bus.
I am using the .NET Core Generic Host (not Web Host) to build a Console app that needs a rather lengthy graceful shutdown. From the source code in
aspnet/Hosting/src/Microsoft.Extensions.Hosting/HostOptions
it seems pretty clear that the ShutdownTimeout option can be used to change the shutdown timeout in the cancellation token that is provided as a parameter to ShutdownAsync. By default it is 5 seconds.
However, I can't figure out where and how to write the code to specify this option in the HostBuilder configuration code that you typically put in the Program.cs file.
Can someone post some code that shows how to do this?
OK, I finally figured it out ... Here's an outline the configuration code in my Program.cs Main function, with most of the items elided, to show where the configuration for HostOptins.ShutdownTimeout goes.
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.ConfigureHostConfiguration(configHost => {...})
.ConfigureAppConfiguration((hostContext, configApp) => {...})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<ApplicationLifetime>();
...
services.Configure<HostOptions>(
opts => opts.ShutdownTimeout = TimeSpan.FromSeconds(10));
})
.ConfigureLogging(...)
.UseConsoleLifetime()
.Build();
try
{
await host.RunAsync();
}
catch(OperationCanceledException)
{
; // suppress
}
}
To make the this work, here is the StopAsync method in my IHostedService class:
public async Task StopAsync(CancellationToken cancellationToken)
{
try
{
await Task.Delay(Timeout.Infinite, cancellationToken);
}
catch(TaskCanceledException)
{
_logger.LogDebug("TaskCanceledException in StopAsync");
// do not rethrow
}
}
See Graceful shutdown with Generic Host in .NET Core 2.1 for more details about this.
Btw, the catch block in Program.Main is necessary to avoid an unhandled exception, even though I am catching the exception generated by awaiting the cancellation token in StopAsync; because it seems that an unhandled OperationCanceledException is also generated at expiration of the shutdown timeout by the framework-internal version of StopAsync.
A relevant answer for ASP.NET Core 6+:
Solution 1:
var builder = WebApplication.CreateBuilder(args);
//...
builder.WebHost.UseShutdownTimeout(TimeSpan.FromSeconds(30));
//...
var app = builder.Build();
Solution 2:
var builder = WebApplication.CreateBuilder(args);
//...
builder.Services.Configure<HostOptions>(
opts => opts.ShutdownTimeout = TimeSpan.FromSeconds(30));
//...
var app = builder.Build();
Solution 3:
var builder = WebApplication.CreateBuilder(args);
//...
builder.Services.PostConfigureAll<HostOptions>(opts =>
opts.ShutdownTimeout = TimeSpan.FromSeconds(30));
//...
var app = builder.Build();
Solution 3 will be applied after all others.