c# - mvc - forms asp net core
ASP.NET Core equivalente de ASP.NET MVC 5''s HttpException (4)
En ASP.NET MVC 5, podría lanzar una HttpException con un código HTTP y esto establecería la respuesta de esta manera:
throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request.");
HttpException
no existe en ASP.NET Core.
¿Cuál es el código equivalente?
Alternativamente, si solo desea devolver un código de estado arbitrario y no le preocupa el enfoque basado en excepciones, puede usar
return new HttpStatusCodeResult(400);
Actualización: a partir de .NET Core RC 2, el prefijo Http se descarta. Esto es ahora:
return new StatusCodeResult(400);
Después de una
breve conversación con @davidfowl
, parece que ASP.NET 5 no tiene esa noción de
HttpException
o
HttpResponseException
que "mágicamente"
HttpException
a mensajes de respuesta.
Lo que puede hacer es conectarse a la tubería ASP.NET 5 a través de MiddleWare y crear una que maneje las excepciones por usted.
Aquí hay un ejemplo del código fuente de su middleware de controlador de errores que establecerá el código de estado de respuesta en 500 en caso de una excepción más adelante:
return new StatusCodeResult(400);
Y debe registrarlo con
StartUp.cs
:
return HttpBadRequest("Bad Request.");
Implementé mi propio
HttpException
y soporte de middleware que captura todos los
HttpException
y los convierte en la respuesta de error correspondiente.
Un extracto corto se puede ver a continuación.
También puede utilizar el paquete
Nuget
Boxed.AspNetCore.
Ejemplo de uso en Startup.cs
// Usage example in Startup.cs
public void Configure(IApplicationBuilder application)
{
application.UseIISPlatformHandler();
application.UseStatusCodePagesWithReExecute("/error/{0}");
application.UseHttpException();
application.UseMvc();
}
public static class ApplicationBuilderExtensions
{
public static IApplicationBuilder UseHttpException(this IApplicationBuilder application)
{
return application.UseMiddleware<HttpExceptionMiddleware>();
}
}
internal class HttpExceptionMiddleware
{
private readonly RequestDelegate next;
public HttpExceptionMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await this.next.Invoke(context);
}
catch (HttpException httpException)
{
context.Response.StatusCode = httpException.StatusCode;
var responseFeature = context.Features.Get<IHttpResponseFeature>();
responseFeature.ReasonPhrase = httpException.Message;
}
}
}
public class HttpException : Exception
{
private readonly int httpStatusCode;
public HttpException(int httpStatusCode)
{
this.httpStatusCode = httpStatusCode;
}
public HttpException(HttpStatusCode httpStatusCode)
{
this.httpStatusCode = (int)httpStatusCode;
}
public HttpException(int httpStatusCode, string message) : base(message)
{
this.httpStatusCode = httpStatusCode;
}
public HttpException(HttpStatusCode httpStatusCode, string message) : base(message)
{
this.httpStatusCode = (int)httpStatusCode;
}
public HttpException(int httpStatusCode, string message, Exception inner) : base(message, inner)
{
this.httpStatusCode = httpStatusCode;
}
public HttpException(HttpStatusCode httpStatusCode, string message, Exception inner) : base(message, inner)
{
this.httpStatusCode = (int)httpStatusCode;
}
public int StatusCode { get { return this.httpStatusCode; } }
}
Método de extensión
public class ErrorHandlerMiddleware
{
private readonly RequestDelegate _next;
private readonly ErrorHandlerOptions _options;
private readonly ILogger _logger;
public ErrorHandlerMiddleware(RequestDelegate next,
ILoggerFactory loggerFactory,
ErrorHandlerOptions options)
{
_next = next;
_options = options;
_logger = loggerFactory.CreateLogger<ErrorHandlerMiddleware>();
if (_options.ErrorHandler == null)
{
_options.ErrorHandler = _next;
}
}
public async Task Invoke(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError("An unhandled exception has occurred: " + ex.Message, ex);
if (context.Response.HasStarted)
{
_logger.LogWarning("The response has already started,
the error handler will not be executed.");
throw;
}
PathString originalPath = context.Request.Path;
if (_options.ErrorHandlingPath.HasValue)
{
context.Request.Path = _options.ErrorHandlingPath;
}
try
{
var errorHandlerFeature = new ErrorHandlerFeature()
{
Error = ex,
};
context.SetFeature<IErrorHandlerFeature>(errorHandlerFeature);
context.Response.StatusCode = 500;
context.Response.Headers.Clear();
await _options.ErrorHandler(context);
return;
}
catch (Exception ex2)
{
_logger.LogError("An exception was thrown attempting
to execute the error handler.", ex2);
}
finally
{
context.Request.Path = originalPath;
}
throw; // Re-throw the original if we couldn''t handle it
}
}
}
Middleware
public class Startup
{
public void Configure(IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerfactory)
{
app.UseMiddleWare<ExceptionHandlerMiddleware>();
}
}
HttpException
return new HttpStatusCodeResult(400);
La clase base
Microsoft.AspNet.Mvc.Controller
expone una
HttpBadRequest(string)
que toma un mensaje de error para volver al cliente.
Entonces, desde una acción del controlador, puede llamar a:
return HttpBadRequest("Bad Request.");
En última instancia, mi nariz dice que cualquier método privado llamado desde una acción del controlador debe ser totalmente consciente del contexto http y devolver un resultado
IActionResult
, o realizar alguna otra tarea pequeña completamente aislada del hecho de que está dentro de una tubería http.
De acuerdo, esta es mi opinión personal, pero una clase que realiza alguna lógica empresarial no debería devolver códigos de estado HTTP y, en cambio, debería lanzar sus propias excepciones que pueden detectarse y traducirse a nivel de controlador / acción.