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?
![](https://www.manongdao.com/static/images/pcload.jpg)
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
});
}
}
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
:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseDeveloperExceptionPage();
}
And in the Program
class:
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:
public void Configure(IApplicationBuilder app, IHostingEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseMiddleware<ExceptionsMiddleware>();
}