【问题标题】:How to catch an exception and respond with a status code in .NET Core如何在 .NET Core 中捕获异常并使用状态码进行响应
【发布时间】:2019-01-03 07:12:18
【问题描述】:

我正在运行一个 .Net Core Web API 项目。 我有一个启动文件(如下)。在Startup.ConfigureServices(...) 方法中,我添加了一个创建IFoo 实例的工厂方法。我想捕获 IFooFactory 抛出的任何异常并返回带有状态代码的更好的错误消息。目前我收到一个带有异常消息的 500 错误。有人可以帮忙吗?

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
        });
    }
}

【问题讨论】:

    标签: c# .net dependency-injection exception-handling .net-core


    【解决方案1】:

    因此,当我以两种不同的方式阅读问题时,我发布了两个不同的答案 - 大量删除/取消删除/编辑 - 不确定哪一个真正回答了您的问题:

    要找出应用启动时出现的问题并且根本无法运行,请尝试以下操作:

    使用Startup中的开发者异常页面:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env,
                               ILoggerFactory loggerFactory)
    {
        app.UseDeveloperExceptionPage();
    }
    

    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();
    }
    

    如果您想在 api 正常工作时处理偶尔出现的异常,那么您可以使用一些中间件:

    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");
            }
        }
    }
    

    这有一个“陷阱” - 如果响应标头已经发送,则无法编写状态代码。

    您使用Configure 方法在Startup 类中配置中间件:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env,
                               ILoggerFactory loggerFactory)
    {
        app.UseMiddleware<ExceptionsMiddleware>();
    }
    

    【讨论】:

    • 这篇文章已经过去两年了,但是这个示例被链接了很多次。我有一个关于将其与 Authorize 一起使用的问题: [Authorize(Roles = Role.Admin)] public class UsersController : ControllerBase {} 当用户未获得授权时,此错误永远不会在中间件中处理。有什么具体原因吗?
    • 中间件的顺序很重要。您可能在异常处理中间件之前注册了身份验证中间件。
    猜你喜欢
    • 2019-09-13
    • 1970-01-01
    • 2017-04-22
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 2022-06-18
    • 2014-02-20
    相关资源
    最近更新 更多