2011-01-21 20 views
7

¿Cuál es la mejor forma de manejar identificadores inválidos en una acción del controlador Grails?Grails: devuelve 404 y muestra mi página "No encontrado" para el ID no válido

Cuando MyDomainClass.get(params['i']) devuelve nulo en la acción de mi controlador, quiero que el usuario vea mi página personalizada "No encontrado" y que se devuelva un código de respuesta HTTP 404. No puedo encontrar la manera más limpia de hacerlo.

Gracias.

Respuesta

4

EDITAR - Me disculpo por haber leído mal su pregunta. el método de render toma un código de estado. Así que en el controlador, si no se encuentra nada, trate

render status: 404 

o

render view: you_not_found_view 

o ambos (llamada en un render).

+1

Ya lo tengo, pero no entiendo cómo se supone que debo renderizarlo cuando no puedo encontrar mi objeto de dominio: 'if (! MyDomainClass.get (params ['i'])) {/ * Y que...? * /} '. Hacer 'response.sendError (404)' devuelve un '404' bien, pero no representa esa página de error, el usuario ve una página en blanco. –

+0

Acabo de volver a leer Grails en acción p.331 y dice que hay limitaciones para devolver los códigos de error: no puede proporcionar contenido para la respuesta y el tipo de contenido será 'text/html'. Que no sabía y me confunde aún más ... –

+0

@martin actualizó mi respuesta – hvgotcodes

7

He utilizado el siguiente en mis controladores, donde 'NOTFOUND' es una página 404 personalizada:

def show = { 
     def referenceData = ReferenceData.get(params.id)  
     if (referenceData) 
     { return [ referenceData : referenceData ] } 
     else 
     { redirect(uri:'/notFound') } 
    } 

También me asignan las páginas de error personalizadas en UrlMapping.groovy, algo así como

static mappings = { 
    "403"(controller: "errors", action: "forbidden") 
    "404"(controller: "errors", action: "notFound") 
    "500"(controller: "errors", action: "serverError") 
} 

o

static mappings = { 
    "403"(view: "/errors/forbidden") 
    "404"(view: "/errors/notFound") 
    "500"(view: "/errors/serverError") 
} 

Grails Docs - mapping to response codes

+1

Creo que es una mala práctica redirigir para un recurso no encontrado, al menos para las arquitecturas RESTful. –

+2

@JoshDiehl tiene razón. Esta implementación envía primero un 302 y luego un 404; debe devolver 404 de inmediato. – peterp

0

Aquí está mi fórmula mágica para hacer esto. Tal vez haya una mejor manera, pero esta funciona y garantiza que la misma vista 404 represente si usted genera el 404 o si grial lo hace internamente (no se encontró ningún controlador, por ejemplo).

En primer lugar, crear una clase de vista que se extiende AbstractView:

class NotFoundView extends AbstractView { 

@Override 
    protected void renderMergedOutputModel(Map<String, Object> model, 
     HttpServletRequest request, HttpServletResponse response) { 
     response.sendError(HttpServletResponse.SC_NOT_FOUND) 
    } 
} 

A continuación, cree un controlador de error:

class ErrorController { 

    def notFound = { 
     return render(view: '/error/notFound') 
    } 
} 

Ahora cree su vista de error en Vistas/error/notFound.gsp:

<g:applyLayout name="main"> 
<!doctype html> 
<html> 
<head> 
    <title>Oops! Not found!</title> 
</head> 

<body> 
    <h1>Not Found</h1> 

    <section id="page-body"> 
     <p>Nothing was found at your URI!</p> 
    </section> 

</body> 
</html> 
</g:applyLayout> 

Es crucial que utiliza el < g: applyLayout> tag. Si usa su diseño, se renderizará dos veces y se anidará.

Ahora para la asignación de dirección URL:

"404"(controller: 'error', action: 'notFound') 

todo ya está listo ahora para enviar que 404 desde su controlador:

def myAction = { 
    Thing thing = Thing.get(params.id) 
    if (!thing) { 
     return new ModelAndView(new NotFoundView()) 
    } 
} 

Este enfoque también permite fácilmente registrar el 404, intentar Resuélvelo y envía un 301, o lo que quieras hacer.

Cuestiones relacionadas