Reputation: 12324
I have added a webapi project to my solution with a controller to do an HttpGet. The Blazor server project can access it fine locally and deployed. I can make a postman call to the service locally, but the deployed version is giving me the Blazor connection failed message from my _Host file. How would I configure webapi access externally without Blazor interfering?
I think it may be a routing issue of some kind that I need to work out. I am using .NET5 and my webapi startup has this:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "myapp.WebApi v1"));
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
WebApi Program.cs:
namespace myapp.WebApi
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
Blazor Program.cs:
namespace myapp.UI
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}
My blazor project Startup:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UsePathBase("/myapp");
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
//TelemetryDebugWriter.IsTracingDisabled = true;
}
else
{
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();
}
// SD2: app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
// SD2: app.UseMvc();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
// prior fallback setting
// endpoints.MapFallbackToPage("/_Host");
// 1/4/22 https://stackoverflow.com/questions/61268117/how-to-map-fallback-in-asp-net-core-web-api-so-that-blazor-wasm-app-only-interc
endpoints.MapFallbackToPage("{*path:regex(^(?!api).*$)}", "/_Host"); // don't match paths beginning with api
});
}
I am investigating ways to route .../api/... calls to the webapi project and everything else to the blazor project.
In VS, my call that works is https://localhost:44368/api/controller/GetFoos/Year=2020
My deployed call (tried several variations) https://serverName/appName/api/controller/GetFoos/Year=2020
Fails in Blazor. I want Blazor to ignore and have the WebApi handle it.
Upvotes: 9
Views: 20469
Reputation: 12455
For .Net 7 or 8 you need two lines in your minimal Program.cs to add a Web.API Controller to a Blazor Server App::
var builder = WebApplication.CreateBuilder(args); // Existing line
builder.Services.AddControllers(); // Must go between CreateBuilder and Build
var app = builder.Build(); // Existing line
app.MapControllers(); // Must go between Build and Run
app.Run(); // Existing line
Upvotes: 11
Reputation: 38099
As of .net 6, you only need to add one line of code to program.cs to enable an API Controller to a Blazor Server App:
builder.Services.AddControllers();
Sample Controller:
[ApiController]
[Route("api")]
public class ApiController : Controller {
private static readonly string[] Summaries = new[]
{
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
};
private readonly ILogger<ApiController> _logger;
public ApiController(ILogger<ApiController> logger) {
_logger = logger;
}
[HttpGet("GetWeatherForecast")]
public IEnumerable<WeatherForecast> Get() {
return Enumerable.Range(1, 5).Select(index => new WeatherForecast {
Date = DateTime.Now.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
}
You blazor app will then return a response to an api call of:
http://yourapp/api/getweatherforecast
Upvotes: 12
Reputation: 486
You can also try this (from brief testing it seems working). Try to map fallback inside app.Map
.
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<LocationsServiceV1>().EnableGrpcWeb();
endpoints.MapControllers();
endpoints.MapRazorPages();
});
app.Map("",
builder =>
{
builder.UseRouting();
builder.UseEndpoints(endpoints =>
{
// Fallback for blazor front-end
endpoints.MapFallbackToAreaPage("{*path:nonfile}", "/_Host", "Frontend");
});
});
Upvotes: 1
Reputation: 30350
This is just some code to show how you run API controllers and Blazor on the same site.
You normally add controllers to a Blazor Server project like this:
Add the services
services.AddControllers();
Or if the controllers are in another project/assembly
services.AddControllers().PartManager.ApplicationParts.Add(new AssemblyPart(typeof(Blazr.Database.Controllers.WeatherForecastController).Assembly));
Then set up the middleware pipeline like this:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapRazorPages();
endpoints.MapFallbackToPage("/_Host");
});
_Host.cshtml
being the Blazor Server SPA launch file.
endpoints.MapControllers();
intercepts and fulfills all requests for the controllers. The Blazor App startup page is the final fallback.
Upvotes: 11