开发者

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

What's the best way to handle invalid ids in a Grails controller action?

When MyDomainClass.get(params['i']) returns n开发者_JAVA百科ull in my controller action I want the user to see my custom 'Not Found' page and for a 404 HTTP response code to be returned - I can't figure out the cleanest way to do this.

Thanks.


I've used the following in my controllers, where 'notFound' is a custom 404 page:

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

I also mapped 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 - mapping to response codes


EDIT - I apologize for misreading your question. the render method takes a status code. So in the controller, if nothing is found, try

render status: 404

or

render view: you_not_found_view

or both (in one render call).


Here's my magic formula for doing this. Maybe there's a better way, but this one works and ensures the same 404 view renders whether you generate the 404 or grails does it internally (no controller found, for example).

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)
    }
}

Next, create an error controller:

class ErrorController {

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

Now create your error view under views/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's crucial that you use the <g:applyLayout> tag. If you use your layout will render twice and nest itself.

Now for the URL mapping:

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

You're all set now to send that 404 from your controller:

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

This approach also lets you easily log the 404, try to resolve it and send a 301, or whatever you want to do.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜