'Exception not handling globally in .net core blazor
I have API calls utility in my blazor web project. I have added condition where if I get unauthorized response from API, I am throwing the unauthorized error and trying to catch it in program.cs file so I can redirect user to login page. while throwing error blazor engine returning error in browser.
Utitlity.cs
public async Task<CurrentResponse> GetAsync(IHttpClientFactory _httpClient, string url)
{
try
{
var request = new HttpRequestMessage(HttpMethod.Get, url);
request.Headers.Clear();
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", GetClaimValue(CustomClaimTypes.AccessToken));
var client = _httpClient.CreateClient("FSMAPI");
HttpResponseMessage httpResponseMessage = await client.SendAsync(request);
if(httpResponseMessage.StatusCode == System.Net.HttpStatusCode.Unauthorized)
{
ManageUnAuthorizedError();
}
CurrentResponse response = JsonConvert.DeserializeObject<CurrentResponse>(httpResponseMessage.Content.ReadAsStringAsync().Result);
return response;
}
catch (Exception exc)
{
throw exc;
}
}
private void ManageUnAuthorizedError(/*IHttpClientFactory _httpClient*/)
{
throw new UnauthorizedAccessException(HttpStatusCode.Unauthorized.ToString());
}
Program.cs
app.UseExceptionHandler(c => c.Run(async context =>
{
var exception = context.Features
.Get<IExceptionHandlerPathFeature>()
.Error;
var response = new { error = exception.Message };
if(exception.Message == HttpStatusCode.Unauthorized.ToString())
{
context.Response.Redirect("/Login");
}
}));
Solution 1:[1]
Here's a possible solution based on the information you've provided in the question.
You need to interact with the UI through Services
A notification service:
public class NeedToAuthenticateService
{
public string ErrorMessage { get; set; } = string.Empty;
public event EventHandler? AuthenticationRequired;
public void NotifyAuthenticationRequired()
=> AuthenticationRequired?.Invoke(this, new EventArgs());
}
This is a "simple" emulation of your API call done through a service that interfaces with the NeedToAuthenticateService and raises the AuthenticationRequired event.
public class APIReaderService
{
private NeedToAuthenticateService needToAuthenticateService;
public APIReaderService(NeedToAuthenticateService needToAuthenticateService)
{
this.needToAuthenticateService = needToAuthenticateService;
}
public void GetData()
{
// If you get an error
needToAuthenticateService.ErrorMessage = "You need to log in!";
needToAuthenticateService.NotifyAuthenticationRequired();
}
}
A simple demo Login page showing the message.
@page "/Logon"
<h3>Logon</h3>
@inject NeedToAuthenticateService needToAuthenticateService
<div class="p-3">
@this.needToAuthenticateService.ErrorMessage
</div>
@code {
}
A modified MainLayout page which registers and event handler with NeedToAuthenticateService and triggers a navigate event when AuthenticationRequired is raised.
@inherits LayoutComponentBase
@inject NeedToAuthenticateService needToAuthenticateService
@inject NavigationManager NavManager
@implements IDisposable
<PageTitle>BlazorApp1</PageTitle>
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
@code {
protected override void OnInitialized()
=> this.needToAuthenticateService.AuthenticationRequired += GoToLogIn;
private void GoToLogIn(object? sender, EventArgs e)
=> NavManager.NavigateTo("/Logon");
public void Dispose()
=> this.needToAuthenticateService.AuthenticationRequired -= GoToLogIn;
}
And finally the registered services in Program
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddScoped<APIReaderService>();
builder.Services.AddScoped<NeedToAuthenticateService>();
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MrC aka Shaun Curtis |

