【问题标题】:PlayFramework form validation with additional constraints带有附加约束的 PlayFramework 表单验证
【发布时间】:2017-04-24 16:56:03
【问题描述】:

免责声明:此处使用 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) 没有创建用户 (GOOD) 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"/")
      }
    )
}

但遗憾的是,这会导致每个发布请求都出现错误,即使是完全有效的请求:

错误:List(FormError(name,List(error.required),List()))

我做错了什么?

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

name=Teolha&dummy=true 作为 post 请求发送。

实际上,我输入什么并不重要,但是(渲染的)表单的 HTML5 部分确保我必须输入一些内容。我期望的是Ok,以防ReservedWords列表中NOT的任何内容,否则BadRequest

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

那些在 play 2.6 中运行:

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

我问,因为我在这里使用 Twirl(但 ScalaTags)来呈现表单!所以也许我错过了 twirl 实现将涵盖的一些隐含的东西(令牌或其他东西)?

【问题讨论】:

  • Errors: List(FormError(name,List(error.required),List())) 表明您没有发布姓名。您能具体说明您要发布的内容吗?
  • 我为“完全有效的请求”添加了一个示例,希望能够澄清它。
  • 我会记录 request 对象只是为了看看控制器实际得到了什么。
  • 已记录。你到底想看什么?
  • 顺便说一句,将 ReservedWords 重命名为 ForbiddenNames - 这很不妥。

标签: java scala validation playframework playframework-2.6


【解决方案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()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 2015-09-09
    • 1970-01-01
    • 2018-02-07
    • 1970-01-01
    相关资源
    最近更新 更多