2011-01-21 14 views
7

Qual è il modo migliore per gestire gli ID non validi in un'azione del controller Grails?Grails: restituisce 404 e mostra la mia pagina "Not Found" per ID non valido

Quando MyDomainClass.get(params['i']) restituisce null nella mia azione del controller, voglio che l'utente visualizzi la mia pagina personalizzata "Non trovata" e un codice di risposta HTTP 404 da restituire - Non riesco a capire il modo più pulito per farlo.

Grazie.

risposta

4

MODIFICA - Mi scuso per aver letto erroneamente la tua domanda. il metodo di rendering accetta un codice di stato. Così nel controllore, se non viene trovato, provare

render status: 404 

o

render view: you_not_found_view 

o entrambi (in un render di chiamata).

+1

Lo ho già, ma non capisco come dovrei renderlo quando non riesco a trovare il mio oggetto dominio: 'if (! MyDomainClass.get (params ['i'])) {/ * Allora cosa ...? * /} '. Facendo 'response.sendError (404)' restituisce un '404' bene, ma non rende quella pagina di errore - l'utente vede solo una pagina vuota. –

+0

Ho appena riletto Grails in Action p.331 e afferma che esistono limitazioni alla restituzione dei codici di errore: non è possibile fornire contenuti per la risposta e il tipo di contenuto sarà 'text/html'. Il che non conoscevo e mi confonde ulteriormente ... –

+0

@ Martin ha aggiornato la mia risposta – hvgotcodes

7

Ho usato il seguente nei miei controllori, dove 'notfound' è una pagina 404:

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

Ho anche mappate le pagine di errore personalizzate in UrlMapping.groovy, qualcosa di simile

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

Credo che sia cattiva pratica di reindirizzare per una risorsa non trovato, almeno per architetture RESTful. –

+2

@JoshDiehl ha ragione. Questa implementazione invia prima un 302, poi un 404, dovresti restituire subito 404. – peterp

0

Ecco la mia formula magica per fare questo. Forse c'è un modo migliore, ma questo funziona e garantisce che la stessa vista 404 restituisca se si genera il 404 o grails lo fa internamente (nessun controller trovato, per esempio).

In primo luogo, creare una vista classe che estende AbstractView:

class NotFoundView extends AbstractView { 

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

successivo, creare un controller di errore:

class ErrorController { 

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

ora Crea il tuo vista errore sotto vista/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> 

È fondamentale che si utilizza il < g: applyLayout> tag. Se utilizzi il layout, esegui il rendering due volte e annidi da solo.

Ora per la mappatura URL:

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

È tutto pronto ora per inviare che 404 dal controller:

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

Questo approccio anche permette di registrare facilmente il 404, cercare di risolvilo e invia un 301 o qualunque cosa tu voglia fare.