36 votos

¿Cómo implementar adecuada de error HTTP en .NET MVC 2?

He estado luchando todos los días para implementar el manejo de errores en mi ASP.NET MVC 2 app. He mirado en una variedad de técnicas, pero ninguno funciona correctamente. Estoy usando MVC2 y .NET 4.0 (iniciado el proyecto antes de MVC3 fue liberado; vamos a actualizar después de entregar nuestra versión inicial).

En este punto, voy a ser feliz para manejar adecuadamente 404 y 500 errores -- 403 (requiere autorización) sería genial, demasiado, seguida por varias otras respuestas específicas. Ahora, me los compre todos 404, todos 500s, todos los códigos 302 antes de la 404, o todos los códigos 302 antes de los 500.

Aquí están mis requisitos (que debe estar muy cerca de los requisitos básicos de HTTP):

  • Si no se encuentra un recurso, tirar un error 404, y mostrar un mensaje de error 404 de página específico con la dirección URL solicitada. NO devolver un intermedio código de respuesta como 302. Idealmente, mantener la dirección URL solicitada, en lugar de presentar una nueva dirección URL como /Error/NotFound - , pero si la segunda muestra, asegúrese de que no nos devuelva una respuesta de redirección para conseguirlo.

  • Si el error interno del servidor, lanzar un 500, y mostrar un 500-error específico con alguna indicación de lo que salió mal. De nuevo, no devolver un intermedio código de respuesta, y lo ideal sería no cambiar la dirección URL.

He aquí lo que me gustaría considerar un 404:

  1. Estática no se encuentra el archivo: /Content/non-existent-dir/non-existent-file.txt
  2. El controlador no encontrado: /non-existent-controller/Foo/666
  3. Controlador de encontrar, pero la Acción no encontrado: /Home/non-existent-action/666
  4. Controlador y acción, pero la acción no puede encontrar el objeto solicitado: /Home/Login/non-existent-id

He aquí lo que me gustaría considerar un 500:

  1. Publicar un mal valor: POST /User/New/new-user-name-too-long-for-db-column-constraint
  2. No de datos relacionados con el problema, como un extremo de los Servicios Web no responde

Algunos de estos es necesario identificar los problemas específicos de los controladores y modelos, y, a continuación, los controladores deberían tirar la adecuada HttpException. El resto debe ser manejado de manera más genérica.

Para 404 caso #2, traté de usar un custom ControllerFactory para lanzar un mensaje de error 404 si el controlador no puede ser encontrado. Para 404 caso #3, he tratado de usar un controlador de base para anular HandleUnknownAction y lanzar un mensaje de error 404.

En ambos casos, tengo un 302 antes de que el 404. Y, yo nunca conseguir 500 errores; si puedo modificar la Web.config para poner una errata en mi Web extremo de Servicio, aún puedo obtener 302, a continuación, un 404 diciendo la URL (controlador/acción), que utiliza el Servicio Web no puede ser encontrado. También tengo la URL solicitada como a(n no deseados) querystring param: /Error/NotFound?aspxerrorpath=/Home/non-existent-action

Ambos de estas técnicas de vino de http://www.niksmit.com/wp/?p=17 (Cómo obtener el normal 404 (Página no encontrada) páginas de error usando ASP.Net MVC), señaló que a partir de http://richarddingwall.name/2008/08/17/strategies-for-resource-based-404-errors-in-aspnet-mvc/

Si en la Web.config he <customErrors mode="On" defaultRedirect="~/Error/Unknown" redirectMode="ResponseRedirect" />, puedo obtener el correspondiente código de respuesta, pero mi Error de controlador nunca se llama. Sacar la redirectMode atributo que me pone el MVC error de puntos de vista, pero con una intervención 302 y un cambio de URL, y siempre el mismo controlador (Unknown = 500; si lo puedo cambiar a NotFound , todo parece como un 404).

Aquí están algunas de las otras cosas que he leído y tratado de implementar:

... junto con un montón de puestos de StackOverflow.

Me parece que este tipo de manejo de errores es bastante básico de aplicaciones Web, y en el marco de MVC debe tener los valores predeterminados de que ello fuera de la caja, y dejar que la gente se extienden a trabajar de otra manera. Tal vez voy a hacer en un futuro de liberación. Mientras tanto, alguien puede darme información detallada sobre cómo implementar un adecuado HTTP respuestas?

44voto

Darin Dimitrov Puntos 528142

Aquí es una técnica que podría utilizar. Definir un ErrorsController que sirva las páginas de error:

public class ErrorsController : Controller
{
    public ActionResult Http404()
    {
        Response.StatusCode = 404;
        return Content("404", "text/plain");
    }

    public ActionResult Http500()
    {
        Response.StatusCode = 500;
        return Content("500", "text/plain");
    }

    public ActionResult Http403()
    {
        Response.StatusCode = 403;
        return Content("403", "text/plain");
    }
}

y luego en Global.asax usted puede suscribirse para el Application_Error evento donde podría registrar la excepción y ejecutar la acción correspondiente de la ErrorsController :

protected void Application_Error(object sender, EventArgs e)
{
    var app = (MvcApplication)sender;
    var context = app.Context;
    var ex = app.Server.GetLastError();
    context.Response.Clear();
    context.ClearError();
    var httpException = ex as HttpException;

    var routeData = new RouteData();
    routeData.Values["controller"] = "errors";
    routeData.Values["exception"] = ex;
    routeData.Values["action"] = "http500";
    if (httpException != null)
    {
        switch (httpException.GetHttpCode())
        {
            case 404:
                routeData.Values["action"] = "http404";
                break;
            case 403:
                routeData.Values["action"] = "http403";
                break;
            case 500:
                routeData.Values["action"] = "http500";
                break;
        }
    }
    IController controller = new ErrorsController();
    controller.Execute(new RequestContext(new HttpContextWrapper(context), routeData));
}

Y ahora todo lo que queda es empezar a lanzar excepciones adecuadas:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        throw new HttpException(404, "NotFound");
    }
}

4voto

Hector Correa Puntos 10408

Errores HTTP 404 (sin redirecciones) tome un vistazo a mi blog el post sobre el tema. Esto podría darle algunas buenas ideas:

http://hectorcorrea.com/blog/RETURNING-http-404-in-ASP.NET-MVC

0voto

JK. Puntos 5517

Esto no contesta tu pregunta, pero es importante tener en cuenta que el Estado HTTP 500 indica que algo salió mal en el servidor, así que tu ejemplo:

POST /User/New/new-user-name-too-long-for-db-column-constraint

No es motivo válido para lanzar un 500, es un tema de validación de datos y deben ser manejado por las anotaciones de datos MVC o un marco de validación de jQuery o etc. Es mucho mejor que sólo muestra un mensaje de error al lado del cuadro de texto diciendo: "Nombre de usuario demasiado largo".

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X