How to reference BlazorSignalRApp in a VS-Solution and start BlazorApp from console program

WIDMER Silvan 0 Reputation points
2024-01-11T08:32:37.88+00:00

I have a solution, which contains the SignalR-Tutorial project (SignalR-Chat) and a project which is basically a console application.

In the BlazorSignalRApp I created a static function called 'StartServerAsync' which is starting the web application. When I set the BlazorSignalRApp as Startup project, everything is running smoothly. Port set to 7283, stylesheet loaded and everything is working like in the tutorial (https://learn.microsoft.com/en-us/aspnet/core/tutorials/signalr?view=aspnetcore-8.0&tabs=visual-studio ).

When I try to start the webapplication with the the same 'StartServerAsync' function, the server starts (Port 5000 this time) but is not reachable and no textbox and no stylesheet is visible.

I know, there is not much missing... I must be related to some settings files not deployed. Are there any examples r documentation? I know, that I need to redirect the wwwroot for the static files. I tried, but it did not change anything.

Could somebody point me the right direction?

Here my implementation of StartServerAsync:

public class BlazorServerStartup  
{      
	public static async Task<WebApplication> StartServerAsync(Serilog.ILogger logger, CancellationToken cancellationToken, WebApplicationOptions? webApplicationOptions = null)      
{          
	WebApplicationBuilder builder;
    
	if (webApplicationOptions is null) 
    {              
		builder = WebApplication.CreateBuilder();          
	}
    else          
	{              
		builder = WebApplication.CreateBuilder(webApplicationOptions);
    }
           
	builder.Host.UseSerilog(logger);          
	builder.Services.AddRazorPages();          
	builder.Services.AddServerSideBlazor();
	builder.Services.AddSingleton<WeatherForecastService>();           

	builder.Services.AddResponseCompression(opts =>          
	{              
		opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(                    
				new[] { "application/octet-stream" });          
	});           

	var app = builder.Build();           
	app.UseResponseCompression();           

	if (!app.Environment.IsDevelopment())          
	{              
		app.UseExceptionHandler("/Error");              
		app.UseHsts();          
	}           

	app.UseHttpsRedirection();           
	app.UseStaticFiles();           
	app.UseRouting();           
	app.MapBlazorHub();         
	app.MapHub<ModuleNotificationHub>("/notificationHub");          
	app.MapFallbackToPage("/_Host");           
	await app.StartAsync(cancellationToken)              
		.ConfigureAwait(false);           
	
	return app;      
	}  
}

Here is the code from the console application to start the server:

public class Program 
{     
	private static Serilog.ILogger? Logger;     
	private static CancellationTokenSource? _cancellationTokenSource;     
	private static CancellationToken _cancellationToken;      

private static async Task Main(string[] args)     
{         
	_cancellationTokenSource = new CancellationTokenSource();         
	_cancellationToken = _cancellationTokenSource.Token;
    Console.CancelKeyPress += Console_CancelKeyPress;
    Logger = new LoggerConfiguration()
                     .WriteTo.Console()
                     .MinimumLevel.Debug()
                     .CreateLogger();
    Logger.Information("Starting Server");
          
	try         
	{             
		var currentDirectory = Directory.GetCurrentDirectory();
	    var webRootPath = Path.GetFullPath(Path.Combine(currentDirectory, "..", "..", "..", "..", "BlazorSignalRApp", "wwwroot"));
	
	    var webAppOptions = new WebApplicationOptions
		{
	        ContentRootPath = currentDirectory,                 
			WebRootPath = webRootPath,             
		};
	              
		var server = await BlazorServerStartup.StartServerAsync(Logger, _cancellationToken, webAppOptions).ConfigureAwait(false);
	
		while (!_cancellationToken.IsCancellationRequested)             
		{                 
			await Task.Delay(100).ConfigureAwait(false);             
		}              
	
		await server.WaitForShutdownAsync(_cancellationToken).ConfigureAwait(false);
	
	    Logger.Information("Stop Server");
	}         
	catch (Exception ex)         
	{             
		Logger.Error(ex, "{ErrorMessage:l}", ex.Message);         
	}     
}

Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,593 questions
Azure SignalR Service
Azure SignalR Service
An Azure service that is used for adding real-time communications to web applications.
146 questions
Visual Studio
Visual Studio
A family of Microsoft suites of integrated development tools for building applications for Windows, the web and mobile devices.
5,173 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,995 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Pinaki Ghatak 4,535 Reputation points Microsoft Employee
    2024-01-11T08:46:38.09+00:00

    Hello @WIDMER Silvan From the limited information you have provided, here are a few things you might want to check:

    1. Check your project references and NuGet Packages: Make sure all your project references are correct and your NuGet packages are up to date.
    2. Check your Startup.cs file: Ensure that you have correctly mapped SignalR inside your Startup.cs. The code should look something like this:
    public class Startup 
    {
        public void Configuration (IAppBuilder app) 
        {
            // Maps SignalR hubs to the app builder pipeline at "/signalr".
            app.MapSignalR ();
        } 
    }
    
    1. Check your Hub configuration: If you have a method on the server side that is not being called on the client side, make sure the method name and signature match exactly on both sides. Also, SignalR creates the hub proxy using camel-cased methods, so a method called MyMethod on the server would be called myMethod in the client proxy. Check your static files path: If your stylesheets and other static files are not loading, make sure you have set the correct path for your wwwroot directory. This is where SignalR looks for static files.
    2. Check your JSON parser: SignalR requires a JSON parser to serialize calls between the server and the client. If your client doesn’t have a built-in JSON parser, you’ll need to include one in your application.

    If you’ve checked all of these and are still having issues, you might want to go through the SignalR tutorial again to see if there’s anything you missed. You can also check out the SignalR Troubleshooting guide for more help. if this information helps you, please tag this as answered, so it helps other readers in the community who may have similar questions.


  2. brtrach-MSFT 16,506 Reputation points Microsoft Employee
    2024-02-06T05:30:37.9333333+00:00

    @WIDMER Silvan It seems that you are trying to start the BlazorSignalRApp from a console application. You have implemented the StartServerAsync method in the BlazorServerStartup class to start the web application. However, when you try to start the web application using this method, the server starts on port 5000 but is not reachable and no textbox and no stylesheet is visible. Based on the code you have provided, it seems that you have correctly set the WebRootPath to the path of the wwwroot folder in the BlazorSignalRApp. However, you also need to set the ContentRootPath to the path of the BlazorSignalRApp project. Here is the modified code for the Main method in the console application:

    private static async Task Main(string[] args)
    {
        _cancellationTokenSource = new CancellationTokenSource();
        _cancellationToken = _cancellationTokenSource.Token;
        Console.CancelKeyPress += Console_CancelKeyPress;
        Logger = new LoggerConfiguration()
                     .WriteTo.Console()
                     .MinimumLevel.Debug()
                     .CreateLogger();
        Logger.Information("Starting Server");
    
        try
        {
            var currentDirectory = Directory.GetCurrentDirectory();
            var contentRootPath = Path.GetFullPath(Path.Combine(currentDirectory, "..", "..", "..", "..", "BlazorSignalRApp"));
            var webRootPath = Path.GetFullPath(Path.Combine(contentRootPath, "wwwroot"));
    
            var webAppOptions = new WebApplicationOptions
            {
                ContentRootPath = contentRootPath,
                WebRootPath = webRootPath,
            };
    
            var server = await BlazorServerStartup.StartServerAsync(Logger, _cancellationToken, webAppOptions).ConfigureAwait(false);
    
            while (!_cancellationToken.IsCancellationRequested)
            {
                await Task.Delay(100).ConfigureAwait(false);
            }
    
            await server.WaitForShutdownAsync(_cancellationToken).ConfigureAwait(false);
    
            Logger.Information("Stop Server");
        }
        catch (Exception ex)
        {
            Logger.Error(ex, "{ErrorMessage:l}", ex.Message);
        }
    }
    
    
    

    In this modified code, we have set the ContentRootPath to the path of the BlazorSignalRApp project. This should allow the server to find the necessary files and serve them correctly.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.