Manejo de errores en ASP.NET Core

Este artículo presenta algunas formas de tratar los errores comunes en las aplicaciones web ASP.NET Core. API web relacionada, consulte Manejo de ASP.NET Core Web APIerrores.

Página de excepción para desarrolladores

La página de excepción del desarrollador muestra la información detallada de la excepción de solicitud. La plantilla ASP.NET Core genera el siguiente código:

if (env.IsDevelopment())
{
    
    
    app.UseDeveloperExceptionPage();
}
else
{
    
    
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

Cuando la aplicación se 开发环境está ejecutando, el código resaltado anteriormente habilita la página de excepción del desarrollador.

La plantilla se coloca en la parte frontal de la canalización de middleware UseDeveloperExceptionPagepara que pueda detectar las excepciones generadas en el middleware más adelante.

El código anterior habilita la página de excepción del desarrollador solo cuando la aplicación se ejecuta en el entorno de desarrollo. Cuando la aplicación se ejecuta en un entorno de producción, la información de excepción detallada no debe mostrarse públicamente. Para obtener detalles sobre la configuración de entornos, consulte Uso de varios entornos en ASP.NET Core.

La página de excepciones para desarrolladores incluye la siguiente información sobre excepciones y solicitudes:

  • Seguimiento de pila
  • Parámetros de la cadena de consulta (si corresponde)
  • Cookie (si corresponde)
  • Encabezamiento

Página del controlador de excepciones

Para configurar una página de gestión de errores personalizada para el entorno de producción, utilice el middleware de gestión de excepciones. Middleware:

  • Detecte y registre la excepción.
  • Vuelva a ejecutar la solicitud en la canalización alternativa utilizando la ruta indicada. Si se ha iniciado la respuesta, la solicitud no se volverá a ejecutar. /ErrorSolicitud de re-ejecución de ruta de código generada por plantilla .

En el siguiente ejemplo, UseExceptionHandleragregue middleware de manejo de excepciones en un entorno que no sea de desarrollo:

if (env.IsDevelopment())
{
    
    
    app.UseDeveloperExceptionPage();
}
else
{
    
    
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

La plantilla de la aplicación Razor Pages proporciona una página de "error" (.cshtml) y una clase PageModel (ErrorModel) en la carpeta Pages. Para las aplicaciones MVC, la plantilla del proyecto incluye el método de operación de error y la vista de error del controlador principal.

No utilice atributos de método HTTP (como HttpGet) para marcar los métodos de operación del controlador de errores. Los predicados explícitos pueden evitar ciertos métodos de acceso a solicitudes. Si los usuarios no autenticados deberían ver la vista de error, permita el acceso anónimo al método.

La excepción se maneja de diferentes maneras según el método HTTP original:

  • Para Razor Pages, cree varios métodos de controlador. Por ejemplo, usando el OnGetproceso GET excepciones, OnPostmanejando la excepción POST.
  • Para MVC, aplique atributos de verbo HTTP a múltiples operaciones. Por ejemplo, usando el [HttpGet]proceso GET excepciones, [HttpPost]manejando la excepción POST.

Para permitir que los usuarios no autenticados vean la página de manejo de errores personalizada, asegúrese de que admita el acceso anónimo.

Excepción de acceso

Use IExceptionHandlerPathFeature para acceder a la excepción y la ruta de solicitud original en el controlador o la página del controlador de errores:

[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public class ErrorModel : PageModel
{
    
    
    public string RequestId {
    
     get; set; }
    public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
    public string ExceptionMessage {
    
     get; set; }

    public void OnGet()
    {
    
    
        RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;

        var exceptionHandlerPathFeature =
            HttpContext.Features.Get<IExceptionHandlerPathFeature>();
        if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
        {
    
    
            ExceptionMessage = "File error thrown";
        }
        if (exceptionHandlerPathFeature?.Path == "/index")
        {
    
    
            ExceptionMessage += " from home page";
        }
    }
}

[! ADVERTENCIA]
No proporcione información confidencial sobre errores al cliente. Los errores en la prestación de servicios son un riesgo para la seguridad.

Para probar las excepciones en la aplicación de muestra:

  • Establezca el entorno en el entorno de producción.
  • Program.cs de los webBuilder.UseStartup<Startup>();comentarios eliminados.
  • Seleccione "Excepción de activación" en la página de inicio.

Para activar la página de manejo de excepciones anterior, configure el entorno en el entorno de producción y fuerce el lanzamiento de una excepción.

Manejador de excepciones lambda

Una alternativa a una página de controlador de excepciones personalizada es proporcionar un lambda a UseExceptionHandler. Con lambda, puede acceder al error antes de devolver la respuesta.
El siguiente ejemplo muestra cómo usar lambda para el manejo de excepciones:

if (env.IsDevelopment())
{
    
    
    app.UseDeveloperExceptionPage();
}
else
{
    
    
   app.UseExceptionHandler(errorApp =>
   {
    
    
        errorApp.Run(async context =>
        {
    
    
            context.Response.StatusCode = 500;
            context.Response.ContentType = "text/html";

            await context.Response.WriteAsync("<html lang=\"en\"><body>\r\n");
            await context.Response.WriteAsync("ERROR!<br><br>\r\n");

            var exceptionHandlerPathFeature = 
                context.Features.Get<IExceptionHandlerPathFeature>();

            if (exceptionHandlerPathFeature?.Error is FileNotFoundException)
            {
    
    
                await context.Response.WriteAsync("File error thrown!<br><br>\r\n");
            }

            await context.Response.WriteAsync("<a href=\"/\">Home</a><br>\r\n");
            await context.Response.WriteAsync("</body></html>\r\n");
            await context.Response.WriteAsync(new string(' ', 512)); // IE padding
        });
    });
    app.UseHsts();
}

En el código anterior, await context.Response.WriteAsync (new string ('', 512)); se agrega para que el navegador Internet Explorer muestre el mensaje de error correspondiente en lugar de mostrar el mensaje de error de IE. Para obtener más información, consulte este problema de GitHub.
consideración

No ofrecer al cliente mensajes de error IExceptionHandlerFeatureo de origen IExceptionHandlerPathFeature. Los errores en la prestación de servicios son un riesgo para la seguridad.

Para ver los resultados de la excepción que maneja lambda en la aplicación de muestra, utilice las directivas del preprocesador ProdEnvironment y ErrorHandlerLambda, y seleccione "Trigger Exception" en la página de inicio.

UseStatusCodePages

De forma predeterminada, las aplicaciones ASP.NET Core no proporcionarán una página de códigos de estado para los códigos de estado HTTP (como "404-No encontrado"). La aplicación devuelve un código de estado y un cuerpo de respuesta vacío. Para proporcionar una página de códigos de estado, utilice el middleware de la página de códigos de estado.
Este middleware se proporciona a través del paquete Microsoft.AspNetCore.Diagnostics.
Para habilitar el controlador de texto sin formato predeterminado para códigos de estado de error comunes, llame a UseStatusCodePages en el método Startup.Configure:

app.UseStatusCodePages();

Se llama antes del middleware de procesamiento de solicitudes UseStatusCodePages. Por ejemplo, se llama antes del middleware de archivos estáticos y del middleware de punto final UseStatusCodePages.

No se usa UseStatusCodePagescuando no hay un punto final para navegar a la URL, devolverá un mensaje de error asociado con el navegador, lo que indica que no se encuentra el punto final. Por ejemplo, navegue hasta Home/Privacy2. Llame UseStatusCodePages, el navegador devuelve:

Status Code: 404; Not Found

UseStatusCodePages Por lo general, no se usa en producción porque devuelve mensajes que no son útiles para el usuario.

El middleware de la página de códigos de estado no detecta excepciones. Para proporcionar una página personalizada de manejo de errores, utilice 异常处理程序页.

Contiene la cadena de formato UseStatusCodePages

Para personalizar el tipo de contenido y el texto de la respuesta, use la sobrecarga UseStatusCodePages que requiere el tipo de contenido y la cadena de formato:

app.UseStatusCodePages(
    "text/plain", "Status code page, status code: {0}");

En el código anterior, {0}es un marcador de posición para el código de error.

Que contiene lambda UseStatusCodePages

Para especificar el manejo de errores personalizado y los códigos de escritura de respuesta, use la sobrecarga UseStatusCodePages que requiere expresiones lambda:

app.UseStatusCodePages(async context =>
{
    
    
    context.HttpContext.Response.ContentType = "text/plain";

    await context.HttpContext.Response.WriteAsync(
        "Status code page, status code: " + 
        context.HttpContext.Response.StatusCode);
});

UseStatusCodePagesWithRedirects

UseStatusCodePagesWithRedirects Método de extensión:

  • Envíe un código de estado "302-Encontrado" al cliente.
  • Redirija al cliente al extremo de manejo de errores que se proporciona en la plantilla de URL. El extremo de manejo de errores generalmente muestra un mensaje de error y devuelve HTTP 200.
app.UseStatusCodePagesWithRedirects("/StatusCode?code={0}");

La plantilla de URL puede incluir {0}marcadores de posición de código de estado , como se muestra en el código anterior. Si la plantilla de URL tiene una tilde ~(tilde) al principio, ~será reemplazada por la aplicación PathBase. Al especificar el punto final en la aplicación, cree una vista MVC o una página de Razor para el punto final. Para ver ejemplos de Razor Pages, consulte Pages / StatusCode.cshtml en la aplicación de ejemplo.

Este método se suele utilizar cuando la aplicación:

  • El cliente debe ser redirigido a un punto final diferente (generalmente cuando diferentes aplicaciones manejan errores). Para las aplicaciones web, la barra de direcciones del navegador del cliente refleja el punto final de redirección.
  • El código de estado original no debe conservarse ni devolverse a través de la respuesta de redireccionamiento inicial.

UseStatusCodePagesWithReExecute

UseStatusCodePagesWithReExecute Método de extensión:

  • Devuelva el código de estado original al cliente.
  • Vuelva a ejecutar la canalización de solicitudes utilizando la ruta alternativa para generar el cuerpo de respuesta.
app.UseStatusCodePagesWithReExecute("/StatusCode","?code={0}");

Si apunta a un punto final en la aplicación, cree una vista MVC o una página de Razor para el punto final. Asegúrese de UseStatusCodePagesWithReExecutecolocarlo UseRoutingantes, para que la solicitud se pueda redireccionar a la página de estado. Para ver ejemplos de Razor Pages, consulte Pages / StatusCode.cshtml en la aplicación de ejemplo.

Este método se suele utilizar cuando la aplicación debe:

  • Procese la solicitud, pero no la redireccione a un punto final diferente. Para las aplicaciones web, la barra de direcciones del navegador del cliente refleja el punto final de la solicitud original.
  • Conserve el código de estado original y devuélvalo con la respuesta.

Las plantillas de URL y las plantillas de cadenas de consulta pueden incluir marcadores de posición para códigos de estado {0}. La plantilla de URL debe /comenzar con.

@page "{code?}"

El extremo de manejo de errores puede obtener la URL original que generó el error, como se muestra en el siguiente ejemplo:

var statusCodeReExecuteFeature = HttpContext.Features.Get<IStatusCodeReExecuteFeature>();
if (statusCodeReExecuteFeature != null)
{
    
    
    OriginalURL =
        statusCodeReExecuteFeature.OriginalPathBase
        + statusCodeReExecuteFeature.OriginalPath
        + statusCodeReExecuteFeature.OriginalQueryString;
}

Deshabilitar la página de códigos de estado

Para deshabilitar el controlador MVC o la página de códigos de estado del método de operación, use la [SkipStatusCodePages]función.

Para deshabilitar el método del controlador de Razor Pages o la página de códigos de estado de solicitud específica en el controlador MVC, use IStatusCodePagesFeature:

var statusCodePagesFeature = HttpContext.Features.Get<IStatusCodePagesFeature>();

if (statusCodePagesFeature != null)
{
    
    
    statusCodePagesFeature.Enabled = false;
}

Código de manejo de excepciones

El código de la página de manejo de excepciones también puede generar una excepción. Debe probar a fondo la página de error de producción y tener especial cuidado para evitar lanzar sus propias excepciones.

Encabezado de respuesta

Después de que se envía el encabezado de respuesta:

  • La aplicación no puede cambiar el código de estado de la respuesta.
  • No se puede ejecutar ninguna página de excepción o controlador. La respuesta debe completarse o la conexión debe cancelarse.

Manejo de excepciones del servidor

Además de la lógica de manejo de excepciones en la aplicación, también HTTP 服务器实现puede manejar algunas excepciones. Si el servidor antes de enviar el encabezado de respuesta capturado es anormal, el servidor envía una respuesta que no contiene el cuerpo de 500 - Internal Server Errorla respuesta. Si el servidor detecta una excepción después de enviar el encabezado de respuesta, el servidor cerrará la conexión. Las solicitudes que no puedan ser procesadas por la aplicación serán procesadas por el servidor. Cuando el servidor procesa la solicitud, cualquier excepción que ocurra será manejada por el manejo de excepciones del servidor. Las páginas de error personalizadas aplicadas, el middleware de manejo de excepciones y los filtros no afectarán este comportamiento.

Iniciar el manejo de excepciones

Las excepciones que ocurren durante el inicio de la aplicación solo se pueden manejar en la capa portadora. El host se puede configurar como 捕获启动错误y 捕获详细错误.

Solo cuando el error se produce después de la vinculación del puerto / dirección del host, la capa de alojamiento puede mostrar la página de error del error de inicio capturado. Si la encuadernación falla:

  • La capa de alojamiento registrará excepciones críticas.
  • El proceso de dotnet falló.
  • En el servidor HTTP no se Kestrelmostrará ninguna página de error.

Al ejecutar la aplicación en IIS (o Azure Application Service) o IIS Express, si el proceso no se puede iniciar, el módulo ASP.NET Core devolverá "502.5-Process failed". Para obtener más información, consulte Solución de problemas de ASP.NET Core en Azure App Service e IIS.

Página de error de la base de datos

El middleware de la página de error de la base de datos captura las excepciones relacionadas con la base de datos, y la migración de Entity Framework se puede utilizar para resolver estas excepciones. Cuando ocurren estas excepciones, se genera una respuesta HTML que contiene información detallada sobre posibles acciones para resolver el problema. Esta página solo debe habilitarse en un entorno de desarrollo. Habilite esta página agregando código a Startup.Configure:

if (env.IsDevelopment())
{
    
    
    app.UseDatabaseErrorPage();
}

UseDatabaseErrorPageRequiere el Microsoft.AspNetCore.Diagnostics.EntityFrameworkCorepaquete NuGet.

Filtro de excepciones

En las aplicaciones MVC, los filtros de excepción se pueden configurar global o individualmente para cada controlador o cada operación. En la aplicación Razor Pages, los filtros de excepción se pueden configurar global o individualmente para cada modelo de página. Estos filtros manejan cualquier excepción no controlada que ocurra mientras se realizan acciones del controlador u otros filtros. Para obtener más información, consulte ASP.NET Core 中的筛选器.

Los filtros de excepción son adecuados para detectar las excepciones que ocurren dentro de las operaciones MVC, pero no son tan 异常处理中间件 UseExceptionHandlerflexibles como los integrados . Recomendamos usarlo UseExceptionHandlera menos que necesite realizar el manejo de errores de diferentes maneras según la operación MVC seleccionada.

Error de estado del modelo

Para aprender a manejar los errores de estado del modelo, consulte 模型绑定y 模型验证.


Manejo de errores

Agregar página de manejo de errores

Al Startup.csconfigurar el middleware:

app.UseStatusCodePagesWithReExecute("/error/{0}");

Recomendado en UseStatusCodePagesWithReExecutelugar de UseStatusCodePagesWithRedirectsla ejecución anterior en la url de salto de error de canalización, que será redirigida a la url, lo que lleva al código de estado de error http se convierte en la ejecución normal de una nueva página de 200 yardas.

Luego escribe el controlador de errores:

public class ErrorController : Controller
{
    [Route("Error/{statusCode}")]
    public IActionResult Index(int statusCode)
    {
        var statusCodeResult = HttpContext.Features.
            Get<IStatusCodeReExecuteFeature>();
        var viewModel = new ErrorViewModel
        {
            Path = statusCodeResult.OriginalPath,
            QueryString = statusCodeResult.
                OriginalQueryString,
        };
        switch (statusCode)
        {
            case 404:
                viewModel.Message = "页面未找到";
                break;
        }
        return View("Error", viewModel);
    }
}

Por cierto, también definí ViewModel:

public class ErrorViewModel
{
    public int Code { get; set; }
    public string Message { get; set; }
    public string Path { get; set; }
    public string QueryString { get; set; }
}

El código de vista no se publicará, no es más que mostrar estos mensajes de error en el ViewModel ~

Establecer salto de excepción global

Agregar middleware

app.UseExceptionHandler("/exception");

Para escribir el controlador de procesamiento, debe agregar AllowAnonymousanotaciones aquí para permitir que los usuarios accedan a esta página de excepción cuando no hayan iniciado sesión para asegurarse de que la página de excepción se pueda mostrar de todos modos.

[AllowAnonymous]
[Route("exception")]
public IActionResult ExceptionHandler()
{
    var exception = HttpContext.Features.
        Get<IExceptionHandlerPathFeature>();
    var viewModel = new ExceptionViewModel
    {
        Path = exception.Path,
        Message = exception.Error.Message,
        StackTrace = exception.Error.StackTrace,
    };
    return View("Exception", viewModel);
}

Además, ViewModel se define de la siguiente manera:

public class ExceptionViewModel
{
    public string Path { get; set; }
    public string Message { get; set; }
    public string StackTrace { get; set; }
}

Supongo que te gusta

Origin blog.csdn.net/WuLex/article/details/113622749
Recomendado
Clasificación