How to run sychronous tasks on IHost start up - .net-core

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.

Related

Adding MassTransit Consumer to a Asp.net Framework Web application

I am Tring to add MassTransit Consumer to a Asp.net Framework (.net 4.8) Web application. I not see any sample that use .net framework , all sample point to .NET Core .
Is this Supported by MassTransit in .net Framework (.net 4.8). Is this Long running calls will be killed Off by IIS ?
My sample Code for Global.asax.cs
public class MvcApplication : System.Web.HttpApplication
{
static IBusControl _bus;
static BusHandle _busHandle;
public static IBus Bus
{
get { return _bus; }
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
_bus = MassTransit.Bus.Factory.CreateUsingRabbitMq(cfg =>
{
cfg.Host(new Uri(ConfigurationManager.AppSettings["RabbitMQHost"]), h =>
{
h.Username("admin");
h.Password("admin");
});
cfg.ReceiveEndpoint(RA_Listener.RA_Listener0, e =>
{
e.Consumer<EventConsumer>();
});
});
_busHandle = MassTransit.Util.TaskUtil.Await<BusHandle>(() => _bus.StartAsync());
}
It's only a long-running call if the bus can't connect to your message broker. Otherwise, it should complete almost immediately. So if your broker is unreachable, that's likely the issue.
Also, you should be configuring an ILoggerFactory and providing it to MassTransit if you expect to see any useful log output to help you troubleshoot any issues. Configure logging using LogContext.ConfigureCurrentLogContext(loggerFactory); within the bus configuration closure.
You could just create the bus, as you've done, and use:
Task.Run(() => _bus.StartAsync());
It won't wait, but you also won't know if the bus actually started since you aren't observing the result of the task. But, at least it won't block your startup.

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.

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.

What role do the Build() and Run() function play in an ASP.Net Core web application?

I am really new for programming started to development on .NET core Web API development.
This is the piece of code :
namespace time_api
{
public class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
}
I have spent more hours to understand this code piece. I understand that it is calling a static method CreateWebHostBuilder. But I really do not understand what are those .Build() & .Run().
It is like a method(CreateWebHostBuilder) calling another method and another method ?
What is the meaning of having => here ?
Please help me to understand
Ok, here is what is happening in a nutshell.
You're calling your own static method that constructs an IWebHostBuilder which is an interface whose purpose is to allow you to configure an ASP.Net hosting environment.
You're then calling an instance method, Build, on the IWebHostBuilder object that your static function returned.
The Build function takes the configuration, extensions, and so on that is stored on the IWebHostBuilder implementation and uses it to construct the IWebHost instance that will actually be running listening for HTTP requests to handle.
You're finally calling the Run method on the IWebHost that the IWebHostBuilder.Build method returned.
This is the method that actually listens for HTTP requests, maps the requests to one of your controllers, instantiates that controller along with any dependencies, and invokes the action methods.
This method "blocks", or does not return, until something causes your program to exit (i.e. you hit Ctrl+C).
The => after the CreateWebHostBuilder(string[] args) declaration is a new-ish way of declaring a method body called an "expression-bodied member." In this case it is equivalent to the following
public static IWebHostBuilder CreateWebHostBuilder(string[] args) {
return WebHost.CreateDefaultBuilder(args).UseStartup<Startup>();
}
The same symbol => can be used to create a "lambda", or anonymous function, in a case where a delegate or expression is expected.

Push data server to client web app, how to?

(Regarding Web apps, asp.net 5)
I'm new to this stuff, i want to push data from the server to the client. Displaying 'real-time' data on a website. (something like a chat window).
How should i realize this? I've read about SingalR, but most information seems to be outdated? Is this still a good choice?
For example, one of the problems i run into is when i try to add this:
app.MapSignalR();
to my startup.cs
Error CS1061 'IApplicationBuilder' does not contain a definition for 'MapSignalR' and no extension method 'MapSignalR' accepting a first argument of type 'IApplicationBuilder' could be found
Can someone point me in the right direction?
I believe you can do this with a bridge between IAppBuilder and IApplicationBuilder as shown here:
public static IApplicationBuilder UseAppBuilder(this IApplicationBuilder app, Action<IAppBuilder> configure)
{
app.UseOwin(addToPipeline =>
{
addToPipeline(next =>
{
var appBuilder = new AppBuilder();
appBuilder.Properties["builder.DefaultApp"] = next;
configure(appBuilder);
return appBuilder.Build<AppFunc>();
});
});
return app;
}
Which you would then call from startup to start SignalR:
public void Configure(IApplicationBuilder app)
{
app.UseAppBuilder(appBuilder =>
{
appBuilder.MapSignalR();
appBuilder.Run(context =>
{
});
});
}
Some context, excerpted from the link above:
[In ASP.NET 5, now ASP.NET Core 1.0] the Startup class conventions
have been refined. Katana [the previous version] would search for an
assembly that specified the OwinStartup attribute and then fallback
to searching all assemblies for a class named Startup or
AssemblyName.Startup. ASP.NET does not define an attribute and it only
searches the primary application assembly for a type named Startup (in
any namespace). The Configuration(IAppBuilder app) method is now
Configure(IApplicationBuilder app)...
Middleware that can’t remove their IAppBuilder or OwinMiddleware
dependencies can use a modified approach to run in ASP.NET 5. See this
linked sample for an IApplicationBuilder extension that provides an
IAppBuilder for use with Katana v3 based middleware. This extension
creates a new AppBuilder instance and then wraps the OWIN pipeline
builder pattern around it to integrate into ASP.NET 5.

Resources