Is there any way to create a .NET Core console application which can host a WebSocket server?
I see a lot of stuff but only for using with ASP.NET Core dependency injection.
The NuGet package I end up using must be .NET Core and not full .NET.
If I can use Microsoft.AspNetCore.WebSockets in a console application, how would I do it?
Self-hosted ASP.net Core applications are in fact console applications, using Kestrel as the server you can run it in non-blocking and continue the program as a regular console one, something like this:
public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseKestrel()
.Build(); //Modify the building per your needs
host.Start(); //Start server non-blocking
//Regular console code
while (true)
{
Console.WriteLine(Console.ReadLine());
}
}
The only downside of this is you will get some debug messages at the begining, but you can supress those with this modification:
public static void Main(string[] args)
{
ConsOut = Console.Out; //Save the reference to the old out value (The terminal)
Console.SetOut(new StreamWriter(Stream.Null)); //Remove console output
var host = new WebHostBuilder()
.UseKestrel()
.Build(); //Modify the building per your needs
host.Start(); //Start server non-blocking
Console.SetOut(ConsOut); //Restore output
//Regular console code
while (true)
{
Console.WriteLine(Console.ReadLine());
}
}
Source about the console output.
Related
Background services deployed as Windows Services stopped working. It happened after we migrated from .Net core 3.1 to .Net 6. Services are created using IHosted Service. Services are type of Time Interval and Messaging Queue service and all stopped working. As soon as we start the service, after some initial processing Like connecting to Queuing server successfully or fetching data from DB, the service stops. No logging error is generated and windows event viewer shows service terminated unexpectedly. It has done this x time(s) without any details. When we run the service as console, it gives no error or exception but close after the same steps. In debug mode, the console application is working on all type of services as expected without exiting. Our initial thought by observing all services is, as soon as the service becomes idle, it exits.
We also have a Web App, which is deployed on same server and is working fine. Our server is Windows Server 2012 R2. We have installed Runtime as well as SDK for .Net6.
This is our Program.cs file code
public static void Main(string[] args)
{
var isService = !(Debugger.IsAttached || args.Contains("--console"));
var builder = CreateHostBuilder(args, isService);
var task = isService ? builder.StartAsync() : builder.RunConsoleAsync();
task.Wait();
}
public static IHostBuilder CreateHostBuilder(string[] args, bool isService)
{
var hostBuilder = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<MyHostedService>();
})
.ConfigureLogging(logging =>
{
logging.ClearProviders().AddConsole().AddNLog();
if (isService){
logging.AddEventLog(config =>
{
config.LogName = serviceName;
config.SourceName = serviceName;
});}
});
if (isService){
hostBuilder.UseWindowsService();
}
return hostBuilder;
}
And our service code is below
public class MyHostedService: IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Timed Hosted Service running.");
Start();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
logger.LogInformation("Timed Hosted Service is stopping.");
Stop();
return Task.CompletedTask;
}
}
Just found the solution . After creating the hostbuilder and attaching all services by using this code,
var hostBuilder = Host.CreateDefaultBuilder(args);
we were calling StartAsync to start the service
var task = builder.StartAsync();
task.Wait();
instead, host should be Build and then Run to start the service
var task = builder.Build().RunAsync();
task.Wait();
In .Net Core 3.1 we were using StartAsync which was working fine. After migrating to .Net6, this stoppped working. By using the same code in .Net6, background service when become idle, gets shutdown. Build().RunAsync() keeps the service alive, even after it become idle.
I am working with some sort a small RESTful layer to expose (to the internet) the local application data in a host machine.
It behaves like a typical web service that listens incoming request to a port. I wrote it with ASP .NET Core 3.1 with a tiny layer wrapper called Carter, it has also a DLL / COM Reference (used for querying the data).
I followed the following guides to configure it as a windows service, publish the service, and then to create it.
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-5.0&tabs=visual-studio
https://dotnetcoretutorials.com/2019/12/21/hosting-an-asp-net-core-web-app-as-a-windows-service-in-net-core-3/
I did successfully created a service but it won't start and windows is showing this error dialog.
I am relatively new to .NET development and I am not sure what's wrong here or how to fix this.
Program.cs
namespace Adapter
{
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;
public class Program
{
public static void Main(string[] args)
{
var host = Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>())
.Build();
host.Run();
}
}
}
Startup.cs
namespace Adapter
{
public class Startup
{
public Startup()
{
// load the env values during start up
new Env().Load();
}
public void ConfigureServices(IServiceCollection services)
{
// interface binding for dependency injection
services.AddSingleTonServices();
// carter and routing services
services.AddCarter();
services.AddRouting();
services.AddHostedService<Worker>();
}
public void Configure(IApplicationBuilder app)
{
app.UseRouting();
app.UseEndpoints(builder => builder.MapCarter());
}
}
}
BTW My project is running correctly when you run or debug it in visual studio.
Any help or idea will be much appreciated.
Error 1053: The service did not respond to the start or control request in a timely fashion is the problem caused by the timeout after the particular request.
This error has many variants.You can read this article to try to solve:
[Fix] Error 1053: The service did not respond to the start or control request in a timely fashion
Alternatively, to resolve this issue, you can download the following registry fix for your operating system:
Windows Search “Error 1053” Fix for Windows 7
Windows Search “Error 1053” Fix for Windows 8.1
Windows Search “Error 1053” Fix for Windows 10
So I am trying to run NLog on dotnet core (let's say 2.1.202) so I specifically want it to work with the console output stream. And I want to get as many messages as possible (yeah, logging..) so I've implemented a simple Tracer : TraceListener. So far so good and even if I try to run it via dotnet run it still works pretty well (everything is printed at console as it should be). However, if I try to run the web application via
dotnet publish
dotnet MyProjectName.dll
It fails. No log messages are actually being displayed and the project runs smoothly. So does anyone knows a way to print log messages on console via "publish" method.
Here is my Program.cs file (That's the only place where I mention Nlog, no specific services/configurations in Startup.cs)
public class Program
{
public static void Main(string[] args)
{
var host = BuildWebHost(args);
var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
Trace.Listeners.Add(new Tracer(logger));
try
{
Trace.WriteLine("init main");
host.Run();
}
catch (Exception ex)
{
Trace.Fail(ex.ToString());
}
finally
{
NLog.LogManager.Shutdown();
}
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureLogging(logging =>
{
logging.ClearProviders();
logging.SetMinimumLevel(LogLevel.Trace);
})
.UseNLog()
.Build();
}
To be fair I've checked the given example from NLog and it actually works (from publish) but still I cannot find my problem in my app.
So if somebody done something like that and knows what I am missing here to run logs via publish it would be very helpful. Cheers!
So the problem was that there was internal second nlog.config (in a class library project) which was overriding my default nlog.config from the web project.
Shoutout to Julian for giving the idea to check internal nlog log - very helpful indeed.
As part of my application I have a .Net Core API project. Unlike most cases where this project would run as its own process, I have the API run in a thread, among others, in a single process. Also for my project, I have implemented a custom logging system to suit my needs. However, I have come across a slight problem. Every time I run my program, once the API starts, this message is printed to the console:
Hosting environment: Production
Content root path: C:\Users\Path\To\Code
Now listening on: http://*:8000
Application started. Press Ctrl+C to shut down.
I would like to disable this message as there is no need for it, and it clutters up the otherwise well organized console log. I have a screenshot below so you know exactly what I'm talking about:
I have already disabled all other logging for the mvc (removed ILoggerFactory from ConfigureServices and set all logging to "None" in appsettings.json).
How do I go about disabling/suppressing this message?
.NET Core 3.x
Good news!
These annoying messages are not being written by ASP.NET Core using plain Console anymore. Now abstract Logger is used, so startup messages will be written by your logger in configured format, just like any other logs.
But if you want to get rid of these logs all along, you can use one of two following approaches
The first way is to use .ConfigureLogging(...) method on host builder to remove all default providers from logger:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders(); // <-- here
})
.ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
The other way is to configure .NET Core 3 logger with ConsoleLifetimeOptions in your Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// ...
services.Configure<ConsoleLifetimeOptions>(opts => opts.SuppressStatusMessages = true);
// ...
}
NOTE: second approach won't disable Kestrel logs about an app being listened on port (but first will)
info: Microsoft.Hosting.Lifetime[0]
Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[0]
Now listening on: http://localhost:5000
.NET Core 2.x
These messages can be disabled in 2 ways (besides already mentioned console settings):
1) You can disable them with Environment variable:
"ASPNETCORE_SUPPRESSSTATUSMESSAGES": "true"
2) Or through code (in Program.cs):
WebHost.CreateDefaultBuilder(args)
.UseSetting(WebHostDefaults.SuppressStatusMessagesKey, "True")
or
WebHost.CreateDefaultBuilder(args)
.SuppressStatusMessages(true);
In ASP.NET Core 2.1, use the SuppressStatusMessages method on the WebHostBuilder.
WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.SuppressStatusMessages(true);
You could also do this:
var host = BuildWebHost(args);
host.Start();
host.WaitForShutdown();
This will bypass the Console.WriteLine()s.
Removing logger factory won't help, because it is Console.WriteLine() (Ref : Github issue comment) . You need to suppress the Console.WriteLine outputs. In the Main method, write code like this. This will ignore the Console.WriteLine outputs.
public static void Main(string[] args)
{
Console.SetOut(new StreamWriter(Stream.Null));
BuildWebHost(args).Run();
}
In MVC5, I had a console application that would use Microsoft.Owin.Hosting.WebApp.Start(...) to host a bunch of controllers that would be dynamically loaded from assemblies placed in an external folder and run some custom initialization on them via API call. This way I could pass parameters to the initialization method that were determined at runtime (and would not be as clunky as maintaining config files).
In MVC6, the self-hosting is now done, as far as I know, by the DNX runtime using Microsoft.AspNet.Hosting, but this is all done via command line. Is there a way I can self-host from within a C# console application so I can keep this initialization architecture?
...I had a console application that would use Microsoft.Owin.Hosting.WebApp.Start(...) to host [and to] pass parameters to the initialization method that were determined at runtime...
In ASP.NET 4.x we self-host within a console application using an OWIN host. We run our MyApp.exe directly. Its Main() method calls WebApp.Start() to create the OWIN host. We use an instance of an IAppBuilder to build up the HTTP pipeline via appBuilder.Use() and chain it all together with appBuilder.Build(). This is all within the Microsoft.Owin.Hosting namespace.
Is there a way I can self-host from within a C# console application so I can keep this initialization architecture?
In ASP.NET Core rc2 we self-host inside a console application using an IWebHost. (This is not an OWIN host though OWIN inspired it.) We run our MyApp.exe directly. The Main() method creates a new WebHostBuilder(), which we use to build up the HTTP pipeline via webHostBuilder.Use(), chaining it all together with webHostBuilder.Build(). This is all within the Microsoft.AspNet.Hosting namespace.
Regarding Pinpoint's answer, in ASP.NET Core rc1 we need to run dnx.exe instead of running our app directly. The work of the WebHostBuilder is hidden inside the dnx.exe executable. Dnx.exe also starts-up our application. Our application's Main() method calls WebApplication.Run(), after which we use an instance of IApplicationBuilder to add middleware to the HTTP pipeline via calls to appBuilder.Use(). Both our application and dnx.exe shared the responsibility of creating/configuring the host. It's convoluted and I am glad that this changed in rc2. I supposed that in rc1 the equivalent of OWIN's WebApp.Start() is WebApplication.Run().
ASP.NET 4.x ASP.NET Core rc1 ASP.NET Core rc2
N/A Dnx.exe N/A
MyApp.exe MyApp.dll MyApp.exe
Main(args) Main(args) Main(args)
WebApp.Start() WebApplication.Run(args) N/A
appBuilder.Use() appBuilder.Use() webHostBuilder.Use()
appBuilder.Build() N/A webHostBuilder.Build()
Some References
http://www.asp.net/web-api/overview/hosting-aspnet-web-api/use-owin-to-self-host-web-api
https://msdn.microsoft.com/en-us/library/microsoft.owin.hosting.webapp%28v=vs.113%29.aspx
Katana's WebApp static class has been replaced by WebHostBuilder, that offers a much more flexible approach: https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNet.Hosting/WebHostBuilder.cs.
You've probably already used this API without realizing it, as it's the component used by the hosting block when you register a new web command in your project.json (e.g Microsoft.AspNet.Hosting server=Microsoft.AspNet.Server.WebListener server.urls=http://localhost:54540) and run it using dnx (e.g dnx . web):
namespace Microsoft.AspNet.Hosting
{
public class Program
{
private const string HostingIniFile = "Microsoft.AspNet.Hosting.ini";
private const string ConfigFileKey = "config";
private readonly IServiceProvider _serviceProvider;
public Program(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
}
public void Main(string[] args)
{
// Allow the location of the ini file to be specified via a --config command line arg
var tempBuilder = new ConfigurationBuilder().AddCommandLine(args);
var tempConfig = tempBuilder.Build();
var configFilePath = tempConfig[ConfigFileKey] ?? HostingIniFile;
var appBasePath = _serviceProvider.GetRequiredService<IApplicationEnvironment>().ApplicationBasePath;
var builder = new ConfigurationBuilder(appBasePath);
builder.AddIniFile(configFilePath, optional: true);
builder.AddEnvironmentVariables();
builder.AddCommandLine(args);
var config = builder.Build();
var host = new WebHostBuilder(_serviceProvider, config).Build();
using (host.Start())
{
Console.WriteLine("Started");
var appShutdownService = host.ApplicationServices.GetRequiredService<IApplicationShutdown>();
Console.CancelKeyPress += (sender, eventArgs) =>
{
appShutdownService.RequestShutdown();
// Don't terminate the process immediately, wait for the Main thread to exit gracefully.
eventArgs.Cancel = true;
};
appShutdownService.ShutdownRequested.WaitHandle.WaitOne();
}
}
}
}
https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNet.Hosting/Program.cs