Add an endpoint to .Net Core 3.1 Worker Service - backgroundworker

I have a Worker Service in .Net Core 3.1 created using the template in VS 2022
DI is Configured in Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
...
services.AddTransient<DapperContext>();
var workerSettings = new WorkerSettings();
hostContext.Configuration.Bind(nameof(WorkerSettings), workerSettings);
services.AddSingleton(workerSettings);
var dataReadSettings = new DataReadSettings();
hostContext.Configuration.Bind(nameof(DataReadSettings), dataReadSettings);
services.AddSingleton(dataReadSettings);
services.AddHostedService<Worker>();
});
This Worker Service is deployed in K8, which complains about not having a "healthz" endpoint like so:
Readiness probe failed: Get "the ip address of the service/healthz": dial "tcp the same IP"
I would like to learn on how to do this as this will require, I think, adding a Web API like functionality since we need an http endpoint.
Appreciate the help and thanks in advance.

Related

How to run sychronous tasks on IHost start up

I am working with Windows Service that is a .Net Core Console application.
It contains an instance of an IHostedService which reads messages from a queue and processes them.
Before reading the messages I want to do a short database call and populate a cache.
How do I prevent the hosted service from starting until I have finished populating my cache?
The hostbuilder is currently configured like this:
public static void Main(string[] args)
{
var hostBuilder = Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices((context, services) =>
{
services
.AddHostedService<MessageProcessor>()
.AddSingleton(provider => new ServiceBusClient(_connectionString))
.AddSingleton<ICachePopulator, CachePopulator>()
});
hostBuilder.Build().Run();
}
I looked at the IStartupFilter interface but it seems to be suitable for only ASP.Net Core services (please correct me if I'm wrong here).
I also looked at the Startup class but it seems to be suitable for configuration only rather than synchronous tasks.

Blazor Hosting Startup Assembly not being recognized

I am building a Blazor app (both wasm and server) which both share an API and a set of Services. I have the services broken out into its own class library. There are probably 50 or so services and I dont want to duplicate the service declarations in the Server and WASM configuration sections.
Current Situation
WASM
public static async Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("app");
var zooAPI = new Uri("http://localhost:51552/api/v1/");
builder.Services.AddHttpClient<IZooService, ZooService>(client => client.BaseAddress = zooAPI);
await builder.Build().RunAsync();
}
Server
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddServerSideBlazor();
var zooAPI = new Uri("http://localhost:51552/api/v1/");
services.AddHttpClient<IZooService, ZooService>(client => client.BaseAddress = zooAPI);
}
Since both of these register the services which will end up being over 50 services id like to add a Startup within my Services Class Library.
[assembly: HostingStartup(typeof(Zoo.Services.ServicesStartup))]
namespace Zoo.Services
{
public class ServicesStartup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
var zooAPI = new Uri("http://localhost:51552/api/v1/");
builder.ConfigureServices((context, services) =>
{
services.AddHttpClient<IZooService, ZooService>(client => client.BaseAddress = zooAPI);
});
}
}
}
The issue I have is that this Startup is not being recognized and the Services are not being registered. The exception is "An Unhandled exception occured while processing the request. InvalidOperationException: Cannot provide a value for property 'ZooService'. There is no registered service of type IZooService.
What am I missing to have this ServiceStartup recognized and the registered upon app start?
In order for the Blazor app to know there is a HostingStartup it needs to read you need to tell it the assemblies to look into.
For Server Hosting in the Program.cs you can add the StartupAssemblies Keys or you can add it to the enviornmentvariables ASPNETCORE_HOSTINGSTARTUPASSEMBLIES
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, "Zoo.Services").UseStartup<Startup>();
});
I have not figured out how to add it to the WASM yet

Call SignalR Hub From Another .Net Project

I've got SignalR hubs in one .NetCore project and SignalR clients in another .NetCore project (to comply with internal infrastructure guidelines). I'm struggling with how to implement the client code that will provide the connection to the hubs. All my projects build fine, I'm just missing the connectivity part.
Client Project:
public class MyClientController
{
private readonly IHubContext<MyHub, IMyHubClient> _hub;
public MyClientController(IHubContext<MyHub, IMyHubClient> hub)
{
_hub = hub;
// THIS NEVER GETS CALLED/HIT BECAUSE I DON'T KNOW HOW TO REGISTER IT
_hub.Clients.All.BroadcastMessage("Notify", $"Hello everyone. This has been constructed");
}
}
I'm guessing I need to do some configuration in the Startup.Configure() method? I've installed the client package already,
EDIT: I added the following code, but it's complaining about the format (remember, this is not a relative path, it's in another service).
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<MyHub>("http://localhost:60913/myHub");
}
Am I on the right path here?
The connection is made by mapping a route to your hub class. The docs have a good example. This includes:
// Add to services collection
services.AddSignalR();
// Map the route "/chathub" to a ChatHub class
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<ChatHub>("/chathub");
});
By the way, a hub can be a standalone class not associated to a controller.

.NET Core Worker project "Start" with "0" argument(s)

I got a worker project and I prepared a few things in it (mainly log4net with a config and a worker). When I run it from Visual Studio, it works perfectly fine, however...
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: true);
config.AddJsonFile($"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json", optional: true);
config.AddEnvironmentVariables();
})
.UseWindowsService()
.ConfigureLogging(logging =>
{
logging.AddLog4Net("log4net.config");
logging.AddConsole();
logging.SetMinimumLevel(LogLevel.Debug);
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<SomeWorker>();
// DI...
});
After using it as a Windows service, I receive an error. Am I missing something here? It seems that there isn't really much that could actually go wrong.
2020-04-28T14:11:27.2038348Z ##[section]Starting: Start Windows Service: ServiceName
2020-04-28T14:11:27.2038348Z ==============================================================================
2020-04-28T14:11:27.2038348Z Task : Start Windows Service
2020-04-28T14:11:27.2038348Z Description : Start a windows service.
2020-04-28T14:11:27.2038348Z Version : 8.0.0
2020-04-28T14:11:27.2038348Z Author : Michael Barry
2020-04-28T14:11:27.2038348Z Help : [More Information](https://github.com/jabbera/my-vsts-tasks)
2020-04-28T14:11:27.2038348Z ==============================================================================
2020-04-28T14:11:28.3796348Z Starting Windows Services ServiceName and setting startup type to: Automatic.
2020-04-28T14:11:28.9180348Z ##[error]Exception calling "Start" with "0" argument(s): "Cannot start service ServiceName on computer '.'."
2020-04-28T14:11:28.9648348Z ##[section]Finishing: Start Windows Service: ServiceName
You probably start the service without arguments. When you start the service from VS the Main method is called with a single startup argument (%LAUNCHER_ARGS%). When starting it as a Windows service this argument is probably missing.

Configuring Rebus in a .net core Worker Service (or a Console App)

I have seen that Adding rebus in the ASP.NET Core execution pipeline is very neat using Startup.cs.
I wonder if there is a same neat way to do the same for Worker service or generally a console app.
Most .net core console apps I have seen are very simple demo applications.
Kindly if there is any concrete sample configuration using .net core console application.
Regards
Amour Rashid
One way would be to add Microsoft's Microsoft.Extensions.Hosting package and build your background service as a BackgroundService:
public class MyBackgroundService : BackgroundService
{
readonly IServiceCollection _services = new ServiceCollection();
public BackgroundService()
{
// configure the bus
services.AddResbus(
configure => configure
.Transport(t => t.Use(...))
);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using var provider = _services.BuildServiceProvider();
// start the bus
provider.UseRebus();
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(1), stoppingToken);
}
}
}
which you then add by going
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<MyBackgroundService>();
});
in your startup.
Thanks Mogens,
Another way is to
var host =CreateHostBuilder(args).Build();
host.UseRebus();
host.Run();
Or in ConfigureServices method
....
var provider=services.CreateServiceProvider();
provider.UseRebus();
It helped me I could create Worker Services using rebus.

Resources