表单验证错误:渲染还是重定向?

时间:2011-06-12 12:09:05

标签: validation playframework

在play框架文档中,有两种不同的方法来处理带有验证错误的操作:

  • 重定向到索引(文档的验证部分):
    if (validation.hasErrors()) {
        params.flash(); // add http parameters to the flash scope
        validation.keep();  // keep the errors for the next request
        index();
    }
  • 渲染到表单模板(在教程中):
    if (validation.hasErrors()) {
        render("@form", post);
    }

最好的方法是什么?渲染还是重定向?

3 个答案:

答案 0 :(得分:7)

两种方法都有利弊。

我个人的偏好是使用重定向方法,原因是浏览器URL正确指出了您在应用程序中的位置。例如,如果您的索引页面调用登录操作,如果您不使用重定向,那么当您实际在索引页面上有错误时,浏览器URL将显示登录。

但是,这种方法存在问题。要实现重定向并保留验证错误消息,您需要使用validation.keep()params.flash()(有关详细信息,请参阅此post here),以便为下一个请求保留验证错误。这是在幕后通过将验证错误和用户输入的参数存储在Cookie中来实现的(以确保Play保持无状态)。您可能已经知道,HTTP规范将Cookie限制为4Kb,因此如果您输入的数据大于4Kb(这对于您输入大块文本的表单可能是这样),那么您的Cookie会溢出,你会丢失数据。

Play使用的原始方法是重定向方法,但由于Cookie限制,第二种方法作为解决方法专门添加到文档中。

第三种,可能更清晰的选择是使用javascript从客户端执行验证,该javascript使用AJAX来调用某些服务器端逻辑。在samples-and-test/validation示例应用程序的第10个示例中可以看到此示例。

答案 1 :(得分:2)

我更愿意再次渲染表单模板,因为我认为重定向在这种情况下没用。如果用户按F5,他仍然可以再次发送相同的数据。用户唯一的问题是取消操作。

为了避免COdemwnci提到的url问题,你可以在routes.conf中使用以下技巧

GET  /customer/edit     CustomerController.load()
POST /customer/edit     CustomerController.save()

然后你总是有一个干净的URL。

答案 2 :(得分:1)

我也会去重定向,以便拥有干净的网址。但是,从一个变体切换到另一个变体通常需要的不仅仅是保持验证结果和http参数,即处理所有其他渲染参数。

我最近的例子是表单验证和地址更正:

public static void step2(@Valid Address address)
{
    AddressResult result = ....; // perform address check

    if (result.isCorrected())
    {
        validation.addError("address.streetAndHouseNumber", "Street has been corrected.");
        address.streetAndHouseNumber = result.getStreet();
        render("step1.html", address);
    }
    ... // continue
}

public static void step2(@Valid Address address)
{
    AddressResult result = ....; // perform address check

    if (result.isCorrected())
    {
        validation.addError("address.streetAndHouseNumber", "Street has been corrected.");
        // ----- note this line --------
        params.put("address.streetAndHouseNumber", result.getStreet());
        // ----------------------------- 
        params.flash();
        validation.keep();      
        step1();
    }
    ... // continue
}

虽然可以在变体2中轻松填充本地范围变量,但我们需要更新http参数resp。直接写在闪存范围内。

任何具有适当抽象级别的人都可以轻松地在两种变体之间切换?