Equivalente ASP.NET 5 / MVC 6 di HttpException

In MVC 5 potresti lanciare una HttpException con un codice HTTP e questo imposterà la risposta in questo modo:

throw new HttpException((int)HttpStatusCode.BadRequest, "Bad Request."); 

HttpException non esiste in ASP.NET 5 / MVC 6. Qual è il codice equivalente?

Ho implementato la mia HttpException e il middleware di supporto che cattura tutti gli HttpException e li trasforma nella risposta all’errore corrispondente. Un breve estratto può essere visto sotto:

È ansible utilizzare il pacchetto Boilerplate.AspNetCore Nuget oppure è ansible visualizzare il codice sorgente completo nel seguente progetto GitHub ASP.NET MVC Boilerplate oppure creare un nuovo progetto utilizzando il modello di progetto ASP.NET MVC Boilerplate che consente di triggersre facoltativamente questa funzione quando si crea un nuovo progetto (basta spuntare la casella, accenderla).

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

Dopo una breve chat con @davidfowl , sembra che ASP.NET 5 non abbia tale nozione di HttpException o HttpResponseException che “magicamente” si trasformi in messaggi di risposta.

Quello che puoi fare è colbind la pipeline di ASP.NET 5 tramite MiddleWare e crearne una che gestisca le eccezioni per te.

Ecco un esempio dal codice sorgente del loro middleware di gestione degli errori che imposterà il codice di stato della risposta a 500 in caso di un’eccezione più in alto sulla pipeline:

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

E devi registrarlo con StartUp.cs :

 public class Startup { public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerfactory) { app.UseMiddleWare(); } } 

In alternativa, se si desidera semplicemente restituire un codice di stato arbitrario e non si è interessati all’approccio basato sull’eccezione, è ansible utilizzarlo

 return new HttpStatusCodeResult(400); 

Aggiornamento: da .NET Core RC 2, il prefisso Http viene eliminato. È adesso:

 return new StatusCodeResult(400); 

La class base Microsoft.AspNet.Mvc.Controller espone un HttpBadRequest(string) che accetta un messaggio di errore per tornare al client. Quindi dall’interno di un’azione del controller, puoi chiamare:

 return HttpBadRequest("Bad Request."); 

In definitiva, il mio naso dice che qualsiasi metodo privato chiamato dall’interno di un’azione del controller dovrebbe essere completamente http-context-aware e restituire un IActionResult , o eseguire qualche altro piccolo compito completamente isolato dal fatto che sia all’interno di una pipeline http. Certo, questa è la mia opinione personale, ma una class che esegue una parte della logica di business non dovrebbe restituire i codici di stato HTTP e dovrebbe invece lanciare le proprie eccezioni che possono essere rilevate e tradotte a livello di controller / azione.