【问题标题】:Grails 3: Binding multiple command objects via POSTGrails 3:通过 POST 绑定多个命令对象
【发布时间】:2020-05-18 18:17:53
【问题描述】:

我有一个控制器,它的方法也想绑定多个命令对象。当我通过 GET 调用该方法时,它工作得很好,并且两个对象都被绑定了。问题是如果我通过 POST 调用该方法,则只有第一个命令对象被绑定,而第二个命令对象被完全忽略。

简单示例:

def register(MembershipCommand cmd1, RegisterCommand cmd2) {
        println(cmd1.email);
        println(cmd2.pass);
        respond([:]);
}

如果我打电话给/register?email=test&pass=test,那么cmd1cmd2 就会被填充

如果我用 POST 数据 {email:test,pass:test} 调用 /registercmd1 会被填充,cmd2.passnull

有没有办法使用 POST 使这个数据绑定工作?我不能真正使用 GET,因为涉及文件上传,而且表格相当大。

我知道另一种选择是将每个对象的方法拆分为 2、1,并让我的表单分别提交给每个对象,但如果可以的话,我想避免这种情况。

有什么想法吗?

【问题讨论】:

    标签: post grails data-binding grails-controller command-objects


    【解决方案1】:

    我创建了一个最小的工作项目来测试您的想法。它就像一个魅力。下面是sn-ps。

    RegisterCmd.groovy

    class RegisterCmd {
        String email
    }
    

    edit.gsp

    <g:form resource="${this.player}" method="POST" action="customisedUpdate">
            <g:hiddenField name="version" value="${this.player?.version}" />
            <fieldset class="form">
                <f:field bean="player" property="name" />
                <f:field bean="player" property="game" />
                <f:field bean="player" property="region" />
                <label>Email</label><g:field type="text" name="email"/>
            </fieldset>
            <fieldset class="buttons">
                <input class="save" type="submit" value="${message(code: 'default.button.update.label', default: 'Update')}" />
            </fieldset>
        </g:form>
    

    PlayerController.groovy

        @Transactional
        def customisedUpdate(Player player, RegisterCmd registerCmd) {
            println "Calling save ${player.dump()}"
            println "RegisterCmd: ${registerCmd.dump()}"
            //end::save[]
            //tag::save-handleErrors[]
            if (player == null) {
                render status: HttpStatus.NOT_FOUND
                return
            }
    
            if (player.hasErrors()) {
                respond player.errors, view: 'create'
                return
            }
            //end::save-handleErrors[]
    
            player.save flush: true
    
            request.withFormat {
                form multipartForm { redirect player }
                '*' { respond player, status: HttpStatus.CREATED }
            }
            //tag::save[]
        }
    

    输出如下:

    Calling save <com.itersdesktop.javatechs.grails.Player@1c25113d name=Alexis Barnett game=Pandemic region=EAST wins=96 losses=30 id=1 version=4 org_grails_datastore_mapping_dirty_checking_DirtyCheckable_
    _$changedProperties=[name:HUE THI MY NGO] org_grails_datastore_gorm_GormValidateable__errors=org.grails.datastore.mapping.validation.ValidationErrors: 0 errors org_grails_datastore_gorm_GormValidateable
    __skipValidate=false>
    RegisterCmd: <com.itersdesktop.javatechs.grails.RegisterCmd@7ee6bb8c email=alexis.barnett@gmail.com grails_validation_Validateable__beforeValidateHelper=org.grails.datastore.gorm.support.BeforeValidateH
    elper@3409999e grails_validation_Validateable__errors=grails.validation.ValidationErrors: 0 errors>
    

    如果您对该项目感兴趣,请咨询https://bitbucket.org/itersdesktop/command-objects/src/master/

    【讨论】:

    • 提交时请求正文是什么样的?我有一种感觉,g:form 设置可能有助于将所有内容绑定在一起,因为这是 Grails 的一部分。对于我的场景,我使用的是 REST 服务,所以我的帖子数据很少{email:test,pass:test}
    • 我敢肯定,如果您准确地应用命令对象或 DTO 的设计方式,您可以绑定任何您想要的东西。我在我的主项目中使用 AJAX 调用来命中 grails 控制器,以这种方式完成了很多数据绑定。这里的关键是设置你的命令对象发送到服务器端。
    【解决方案2】:

    使 POST 工作的解决方案是将我的表单数据重组为对象样式格式。

    所以不是{email:test,pass:test}

    我会{cmd1:{email:test}, cmd2:{pass:test}}

    【讨论】:

    • 这对我不起作用(我使用的是 grails 3.3.12)。
    【解决方案3】:

    似乎不支持具有多个命令对象的 Grails 3.3.X。

    【讨论】:

      猜你喜欢
      • 2015-12-12
      • 2011-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多