Grails:在 beforeInterceptor 中渲染页面

发布于 2024-10-17 23:16:47 字数 561 浏览 8 评论 0原文

在我的一个控制器中,我在 beforeInterceptor 闭包中编写了一些错误检查代码。

 if (getUser()?.courses?.size() == 0) {
        render(view: '/base/errorMessage', model: [errorMessage: "You don't have any courses!"]);
        return false;
 }

该渲染调用显示了一个漂亮的、程序范围的错误页面。

但是,如果我返回 false,则不会显示任何内容!如果我返回 true,错误页面显示得很好,但操作无论如何都会执行(它不会被渲染,但逻辑仍然会被执行)。这需要重复的错误检查,从而违背了拦截器的目的。

redirect() 调用仍然可以正常工作,但是将错误显示移动到不同的操作会很混乱。用户将在其 URL 中看到 /app/error/errorMessage,而不是 /app/courses,并且可以直接转到错误页面。接下来的问题是如何获取该操作的消息 - flash.message?会话.var?

有更好的办法吗?

In one of my controllers, I've written some error checking code in the beforeInterceptor closure.

 if (getUser()?.courses?.size() == 0) {
        render(view: '/base/errorMessage', model: [errorMessage: "You don't have any courses!"]);
        return false;
 }

That render call shows a nice, program-wide error page.

However, if I return false, nothing gets displayed! If I return true, the error page shows up just fine, but the action executes anyway (it doesn't get rendered, but the logic still gets executed). This requires duplicate error checking, defeating the purpose of the interceptor.

redirect() calls still work fine, but moving the error display to a different action is messy. Instead of /app/courses, the user would see /app/error/errorMessage in their URL, and it's possible to go right to the error page directly. Then there's the question of getting the message to that action - flash.message? session.var?

Is there a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我不是你的备胎 2024-10-24 23:16:47

我知道这已经有几年了,但我认为这个问题仍然相关。

Grails 通过使用命令对象和 i18n message.properties 提供了一种更方便的方法来验证表单输入并返回 flash 错误消息。

本质上,您不需要编写拦截器。您可以在控制器中创建一个命令对象,其中包含您希望在提交时获得的所有表单字段。然后为每个字段创建验证约束,并为违反约束的错误创建 i18n 消息。

现在,当您定义控制器操作并将命令对象插入为参数时:

def someAction(MyCommandObject command) {}

命令对象参数的作用有点像 beforeInterceptor,因为 Grails 自动将表单提交中的数据绑定到命令对象的匹配属性 —— 但是等等!这还不是全部! Grails 还将约束应用于表单中的数据,并在操作中执行任何代码之前运行 command.validate()。这就是为什么在操作中执行任何其他代码之前检查命令对象实例是否有错误是一种很好的常见做法,如下所示:

def someAction(MyCommandObject command) {
    if(command.hasErrors()){
        //do something -- set flash message error and redirect, etc.
    }
    //other importand code follows ...
}

我希望这可以帮助其他可能发现此问题相关的人。这只是命令对象多么有用和强大的示例之一。

I know this is a few years old but I think the question is still relevant.

Grails has provided a more convenient way to validate form input and return flash error messages by using Command Objects and i18n message.properties.

Essentially, you don't need to write an interceptor. You create a command object in your controller with all the form fields you expect to get when submitted. Then create validation constraints for each field and create your i18n messages for constraint violation errors.

Now, when you define a controller action and insert the command object as a parameter:

def someAction(MyCommandObject command) {}

The command object parameter acts somewhat like a beforeInterceptor, in that Grails automatically binds data from the form submit to matching attributes of the command object -- but wait! That's not all! Grails also applies the constraints to the data from the form and essentially runs command.validate() all BEFORE any code is executed in the action. That's why it is a good, and common practice to check your command object instance for errors before you execute any other code in your action, like so:

def someAction(MyCommandObject command) {
    if(command.hasErrors()){
        //do something -- set flash message error and redirect, etc.
    }
    //other importand code follows ...
}

I hope this helps others who may find this question relevant. This is just one example of how useful and powerful command objects can be.

墨落成白 2024-10-24 23:16:47

更新:过滤器显然不会遇到这个问题。然而,这需要将逻辑与控制器分开。不是世界末日。

我会留下这个问题,以防我错过了更好的方法。

Update: Filters apparently do not suffer this problem. However, that requires separating the logic from the controller. Not the end of the world.

I'll leave the question up in case there's a better way that I've missed.

︶葆Ⅱㄣ 2024-10-24 23:16:47

我建议您查看 Grails URL 映射,部分6.4.4(通过响应代码映射):您可以将请求重定向到“共享500服务器错误页面”

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

此外,我认为您可能不知道您可以更改控制器/操作的URL,即上面的链接中也提到了。

I suggest you have a look at Grails URL Mapping, Section 6.4.4 (mapping by response code): you can redirect you request to a "shared 500 server error page"

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

Moreover, I think you may not know that you can change the URL to your controller/action, which is also mentioned in the link above.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文