具有其他约束的PlayFramework表单验证

时间:2017-04-24 16:56:04

标签: java scala validation playframework playframework-2.6

免责声明:在这里使用PlayFramework 2.6.0-M4!

我显示一个表单,并希望添加额外的约束,禁止某些字符串用于给定字段。

现在我有两个问题:

def create() = Action(parse.form(createUserForm))
  {
   implicit request =>
      val formData: CreateUserData = request.body

      if(validate(formData).isDefined)
      {
        userRepository.create(formData.name, formData.dummy)

        Ok(s"Here should go success, if user was created: $formData")
      } else {
        BadRequest("No means no!")
      }
  }

  case class CreateUserData(name: String, dummy: Boolean)

  private val createUserForm = Form(
    mapping(
      "name" -> text,
      "dummy" -> boolean
    )(CreateUserData.apply)(CreateUserData.unapply)
    verifying("Failed form constraints!", fields => fields match
    {
      case data => validate(data).isDefined
    })
  )

  private def validate(formData: CreatUserData): Option[CreatUserData] =
  {
    ReservedWords.filter(
      _.equalsIgnoreCase(formData.name)
    ).isEmpty match
    {
      case true => Some(formData)
      case false => None
    }
  }

1)Ok(s"Here should go success, if user was created: $formData").as("text/html")适用于提供的数据有效的情况,但是如果用户输入了禁止的名称:

a)没有创建用户(好) b)BadRequest("No means no!")永远不会被退回! (虽然我得到一个http 400响应,只是空的)

我不明白为什么b)发生。

此外,我想关注https://www.playframework.com/documentation/2.6.x/ScalaForms

而是编写如下代码:

def create() = Action(parse.form(createUserForm))
{
  implicit request =>

    createUserForm.bindFromRequest.fold(
      formWithErrors =>
      {
        BadRequest("Errors: " + formWithErrors.errors).as("text/html")
      },
      formData =>
      {
        userRepository.create(formData.name, formData.dummy)
        Redirect(s"/")
      }
    )
}

但遗憾的是,这会导致每个帖子请求出错,即使是那些完全有效的错误:

  

错误:列表(FormError(名称,列表(error.required),列表()))

我做错了什么?

编辑:为了澄清“总有效请求”的含义,我举一个关于错误返回的示例。

name=Teolha&dummy=true以邮寄请求的形式发送。

实际上我输入的内容并不重要,但(渲染)表单的HTML5部分确保我必须输入内容。如果Ok列表中有任何 NOT ,则ReservedWords

,我期望的是BadRequest

edit2:可能是因为默认过滤器?

那些在游戏中运行2.6:

play.filters.csrf.CSRFFilter
play.filters.headers.SecurityHeadersFilter
play.filters.hosts.AllowedHostsFilter

我问,因为我在这里使用Twirl(但是ScalaTags)来渲染表单!所以也许我错过了一些隐含的东西,旋转实现会覆盖(一个令牌或什么)?

1 个答案:

答案 0 :(得分:1)

这是正确的行为:

https://playframework.com/documentation/2.6.0-M4/ScalaForms

val userPost = Action(parse.form(userForm)) { implicit request =>
  

在失败的情况下,默认行为是返回空的BadRequest响应。

接下来:

  

您可以使用自己的逻辑覆盖此行为。例如,以下代码完全等同于使用bindFromRequest和fold的前一个代码。

val userPostWithErrors = Action(parse.form(userForm, onErrors = (formWithErrors: Form[UserData]) => {
  implicit val messages = messagesApi.preferred(Seq(Lang.defaultLang))
  BadRequest(views.html.user(formWithErrors))
})) { implicit request =>
  val userData = request.body
  val newUser = models.User(userData.name, userData.age)
  val id = models.User.create(newUser)
  Redirect(routes.Application.home(id))
}

在你的情况下

在您的代码中调用验证之前,

Action(parse.form(createUserForm))会调用验证(if(validate(formData).isDefined)是多余的)。因此它调用验证,验证不成功并且播放返回空的错误请求。

修复: onError函数的parse.form处理程序中的进程错误。即Action(parse.form(createUserForm, onErrors = ...

第二个问题

您调用Action(parse.form(createUserForm)) - 它处理表单,然后您调用createUserForm.bindFromRequest但表单已经处理完毕,因此您获得了一个空表单。这也是正确的。

修复:删除parse.form(createUserForm),因此您必须只有Action()