KarloX
KarloX

Reputation: 987

Howto implement ASP.NET Core Blazor Server app and a Web API app in the same procress?

I want to implement both

in the same process using .NET 6 and run it self-hosted with Kestrel, i.e. without IIS.

I assume the key is the service and middleware pipeline configuration as found in the according Program.cs templates. Here are the two templates that VS 2022 (17.1.5) creates for me:

For the Blazor Server App:

using BlazorApp1.Data;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
  app.UseExceptionHandler("/Error");
  // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
  app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

For the ASP.NET Core Web API App:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
  app.UseSwagger();
  app.UseSwaggerUI();
}

app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();

app.Run();

So the question is how can I combine these two into one?

I want to:

Upvotes: 8

Views: 6239

Answers (1)

poke
poke

Reputation: 387507

You should be able to combine these without any issues:

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();

app.UseRouting();
app.MapControllers();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");

app.Run();

The service configuration supports registring all dependencies anyway. And between AddRazorPages() and AddController(), there are quite a lot of shared ones anyway.

The only thing that can be tricky is the pipeline configuration since you need to make sure that both API requests and Blazor requests are handled by the correct handlers.

The good thing is that MapControllers is usually means a fixed set of routes. Since your controller actions have specific routes, having the MapControllers first will make sure that those specific routes will be handled properly by your controllers.

All other requests, those that don’t match any controller action, will then go to the next route handler in the pipeline. So MapBlazorHub is next which will host the SignalR hub for Blazor. That’s also a very specific route which is provided here.

So finally, all remaining requests will land at MapFallbackToPage(). This is a fallback-handler which means that it will handle any route. This allows Blazor to have a single entry-point for which it will then use client-side routing. As long as this fallback call is the last in the pipeline, it should not be able to interfere with any other route handler.

With that combined configuration, both your API and your Blazor should work just fine.

If you do have a situation which is more complicated, then you can use app.MapWhen to branch off the pipeline. There is an example in the documentation if you are interested in this functionality. But as I said, for your situation, you shouldn’t need it.

Upvotes: 10

Related Questions