tag net mvc component asp c# .net asp.net-core asp.net-core-mvc httpexception

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.