How to catch an exception and respond with a status code in .NET Core

Multi tool use


How to catch an exception and respond with a status code in .NET Core
I am running a .Net Core Web API project.
I have a startup file (below). In the Startup.ConfigureServices(...)
method, I add a factory method that creates an instance of IFoo. I want to catch any exceptions that the IFooFactory throws and return a better error message with a status code. At the moment I getting a 500 Error with the exception Message. Can anyone help?
Startup.ConfigureServices(...)
public interface IFooFactory
{
IFoo Create();
}
public class FooFactory : IFooFactory
{
IFoo Create()
{
throw new Exception("Catch Me!");
}
}
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooFactory,FooFactory>();
services.AddScoped(serviceProvider => {
IFooFactory fooFactory = serviceProvider.GetService<IFooFactory>();
return fooFactory.Create(); // <== Throws Exception
});
}
}
1 Answer
1
So I've posted two different answers as I read the question in two different ways - lots of deleting/undeleting/editing - not sure which one actually answers your question:
To figure out what is going wrong when the app starts and doesn't work at all try this:
Use the developer exception page in Startup
:
Startup
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseDeveloperExceptionPage();
}
And in the Program
class:
Program
public static void Main(string args)
{
var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.UseApplicationInsights()
.CaptureStartupErrors(true) // useful for debugging
.UseSetting("detailedErrors", "true") // what it says on the tin
.Build();
host.Run();
}
If you want to handle an occasional exception when the api is generally working then you can use some middleware:
public class ExceptionsMiddleware
{
private readonly RequestDelegate _next;
/// <summary>
/// Handles exceptions
/// </summary>
/// <param name="next">The next piece of middleware after this one</param>
public ExceptionsMiddleware(RequestDelegate next)
{
_next = next;
}
/// <summary>
/// The method to run in the piepline
/// </summary>
/// <param name="context">The current context</param>
/// <returns>As task which is running the action</returns>
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch(Exception ex)
{
// Apply some logic based on the exception
// Maybe log it as well - you can use DI in
// the constructor to inject a logging service
context.Response.StatusCode = //Your choice of code
await context.Response.WriteAsync("Your message");
}
}
}
There is one 'gotcha' with this - You can't write the status code if the response header has already been sent.
You configure the middleware in the Startup
class using the Configure
method:
Startup
Configure
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseMiddleware<ExceptionsMiddleware>();
}
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.