问题
ASP.NET Core Web Api Middleware Converts Custom Exception into Base Exception
I have created a custom exception class and use it throw an exception. The middleware catches it but throws base exception instead of custom exception. I am not able to understand why it does not catch custom exception.
Custom Exception
public class CustomException : Exception
{
public int HttpStatusCode { get; private set; }
public CustomException()
{
}
public CustomException(int httpStatusCode, string message):base(message)
{
HttpStatusCode = httpStatusCode;
}
}
Middleware
public class ExceptionMiddleware
{
public readonly RequestDelegate _next;
public ExceptionMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
catch(CustomException ex)
{
await HandleExceptionAsync(httpContext, ex);
}
catch(Exception ex)
{
await HandleExceptionAsync(httpContext, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception ex)
{
int statusCode = (int)HttpStatusCode.InternalServerError;
if (ex is CustomException)
{
CustomException se = ex as CustomException;
statusCode = se.HttpStatusCode;
}
context.Response.ContentType = "application/json";
context.Response.StatusCode = statusCode;
return context.Response.WriteAsync(JsonConvert.SerializeObject(new InternalServerErrorResponse(ex.Message)));
}
}
Exception thrown
throw new CustomException(StatusCodes.Status422UnprocessableEntity, "User is already registered!");
When exception is thrown, middleware does not catch custom exception but base Exception. It always goes to the below code block
catch(Exception ex)
{
await HandleExceptionAsync(httpContext, ex);
}
Please advise.
回答1:
You can use exception filter to handle exceptions and easily manipulate response.
public class ExceptionFilter : IExceptionFilter
{
public ExceptionFilter(IHostingEnvironment env, ILogger<JsonExceptionFilter> logger)
{
_env = env;
_logger = logger;
}
public void OnException(ExceptionContext context)
{
var error = new ApiResponse();
var exceptionName = context.Exception.GetType().Name;
var message = context.Exception.Message;
if (_env.IsDevelopment())
{
error.Message = context.Exception.Message;
error.Detail = context.Exception.StackTrace;
}
else
{
//Prevent To Show Exception Messages On Production
error.Message = "Server Error Occured";
error.Detail = "Something wrong happened";
}
context.Result = new ObjectResult(error)
{
//Manipulate Status Code
StatusCode = 500
};
}
}
And register to Startup.cs
public void ConfigureServices(IServiceCollection services){
services.AddMvc(options =>
{
//Catch the exceptions
options.Filters.Add<ExceptionFilter>();
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
回答2:
you have to tell your app to use this middleware
in configure
method in your startup
class like this -
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerManager logger){
app.ExceptionMiddleware();
}
来源:https://stackoverflow.com/questions/56811113/asp-net-core-web-api-middleware-custom-exception