La respuesta bien aceptada me ayudó mucho, pero quería pasar HttpStatusCode en mi middleware para administrar el código de estado de error en tiempo de ejecución.
De acuerdo con este enlace, tengo una idea para hacer lo mismo. Así que fusioné la respuesta de Andrei con esto. Entonces mi código final está abajo:
1. Clase base
public class ErrorDetails
{
public int StatusCode { get; set; }
public string Message { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
2. Tipo de clase de excepción personalizada
public class HttpStatusCodeException : Exception
{
public HttpStatusCode StatusCode { get; set; }
public string ContentType { get; set; } = @"text/plain";
public HttpStatusCodeException(HttpStatusCode statusCode)
{
this.StatusCode = statusCode;
}
public HttpStatusCodeException(HttpStatusCode statusCode, string message) : base(message)
{
this.StatusCode = statusCode;
}
public HttpStatusCodeException(HttpStatusCode statusCode, Exception inner) : this(statusCode, inner.ToString()) { }
public HttpStatusCodeException(HttpStatusCode statusCode, JObject errorObject) : this(statusCode, errorObject.ToString())
{
this.ContentType = @"application/json";
}
}
3. Middleware de excepción personalizado
public class CustomExceptionMiddleware
{
private readonly RequestDelegate next;
public CustomExceptionMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context /* other dependencies */)
{
try
{
await next(context);
}
catch (HttpStatusCodeException ex)
{
await HandleExceptionAsync(context, ex);
}
catch (Exception exceptionObj)
{
await HandleExceptionAsync(context, exceptionObj);
}
}
private Task HandleExceptionAsync(HttpContext context, HttpStatusCodeException exception)
{
string result = null;
context.Response.ContentType = "application/json";
if (exception is HttpStatusCodeException)
{
result = new ErrorDetails() { Message = exception.Message, StatusCode = (int)exception.StatusCode }.ToString();
context.Response.StatusCode = (int)exception.StatusCode;
}
else
{
result = new ErrorDetails() { Message = "Runtime Error", StatusCode = (int)HttpStatusCode.BadRequest }.ToString();
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
}
return context.Response.WriteAsync(result);
}
private Task HandleExceptionAsync(HttpContext context, Exception exception)
{
string result = new ErrorDetails() { Message = exception.Message, StatusCode = (int)HttpStatusCode.InternalServerError }.ToString();
context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
return context.Response.WriteAsync(result);
}
}
4. Método de extensión
public static void ConfigureCustomExceptionMiddleware(this IApplicationBuilder app)
{
app.UseMiddleware<CustomExceptionMiddleware>();
}
5. Configure el método en startup.cs
app.ConfigureCustomExceptionMiddleware();
app.UseMvc();
Ahora mi método de inicio de sesión en el controlador de cuenta:
try
{
IRepository<UserMaster> obj = new Repository<UserMaster>(_objHeaderCapture, Constants.Tables.UserMaster);
var Result = obj.Get().AsQueryable().Where(sb => sb.EmailId.ToLower() == objData.UserName.ToLower() && sb.Password == objData.Password.ToEncrypt() && sb.Status == (int)StatusType.Active).FirstOrDefault();
if (Result != null)//User Found
return Result;
else// Not Found
throw new HttpStatusCodeException(HttpStatusCode.NotFound, "Please check username or password");
}
catch (Exception ex)
{
throw ex;
}
Arriba puede ver si no he encontrado al usuario y luego levantar la HttpStatusCodeException en la que he pasado el estado HttpStatusCode.NotFound y un mensaje personalizado
en el middleware
catch (HttpStatusCodeException ex)
bloqueado se llamará que pasará el control a
Método privado Task HandleExceptionAsync (contexto HttpContext, excepción HttpStatusCodeException)
.
Pero, ¿qué pasa si tengo un error de tiempo de ejecución antes? Para eso he usado el bloque try catch que arroja la excepción y será atrapado en el bloque catch (Exception exceptionObj) y pasaré el control a
Task HandleExceptionAsync (contexto HttpContext, excepción de excepción)
método.
He usado una sola clase ErrorDetails para uniformidad.
UseExceptionHandler
middleware?