Grails: Return 404 & show my "Not Found" page for invalid id

What is the best way to handle invalid identifiers in a Grails controller action?

When MyDomainClass.get(params['i']) returns null in my controller action, I want the user to see my custom page β€œNot Found” and the HTTP 404 response code that should be returned - I cannot determine the cleanest way to do it.

Thanks.

+7
source share
3 answers

I used the following in my controllers, where "notFound" is a 404 user page:

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

I also matched the custom error pages in UrlMapping.groovy, something like

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

or

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

Grails Docs - Matching Response Codes

+7
source

EDIT. I apologize for misunderstanding your question. The render method accepts a status code. Therefore, in the controller, if nothing is found, try

 render status: 404 

or

 render view: you_not_found_view 

or both (in one render call).

+4
source

Here is my magic formula for this. Maybe there is a better way, but this one works and ensures that the same view 404 displays whether you generate 404 or grails inside it (for example, the controller was not found).

First create a View class that extends AbstractView:

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

Then create an error controller:

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

Now create your error view in view / 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> 

It is very important to use the <g: applyLayout> tag. If you use your layout, it will be displayed twice and it is nested.

Now for URL mapping:

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

Now you should all send 404 from your controller:

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

This approach also makes it easy to record 404, try to resolve it, and send 301 or whatever you do.

0
source

All Articles