Friday, 3 September 2010

Grails Redirect After Post

Currently in most of our applications we do not perform redirects after post to our controllers.

This is bad practice and needs changing (with all of our free time we have).

The current difficulty we have with this is that when we post a form to our controller and there are validation errors, we need to redirect to the form view again but keep the values that were posted in the first place.

For example :
  • Edit user.
  • Get user object.
  • Put user object in model
  • Populate input fields with properties from user object
  • Submit form.
  • Validation Errors.
  • Redirect back to edit user.
What now happens is that because the form gets the values from the user object it can't keep the changed values that are in the command.

Mark and myself came up with what we think is the best practice.

In our grails command we define a constructor that takes the object and populates the command.

In our controller we then get the object we wish to edit. Construct the command object and pass this into the model.

So now our model only ever deals with our command object.

When we redirect after post now all we have to do is place our command object in the flash scope and it will be accessible in our redirected method.

A simple check of existence and we can decide if we want to just place the command in the model or construct the command object again.

For example:
  • Edit User
  • Get User
  • Construct EditUserCommand using user object
  • Place command in the model
  • Populate input fields with properties from command object
  • Submit form.
  • Validation Errors.
  • Redirect back to edit user.
  • Check for command.
  • Place command back in model.

Below is some sample code for the User example case.

class UserCommand {
    String name

    public UserCommand() {}

    public UserCommand(User user) {
        name = user.name       
    }

    static constraints = {
        name(nullable:false, blank:false)
    }
}

class UserController {
    def edit = {      
        def user = getUser()       

        if (flash.form == null) {
            flash.form = new UserCommand(user)
        }

        return render(view:'edit', model:[form:flash.form])
    }

    def update = { UserCommand form ->       
        if (form.hasErrors()) {
            flash.form = form
            return redirect(action:'edit')
        }       

        return redirect(action:'detail', params:[id:form.id])           
    }
}


Our view will now only deal with the command object and can access all user fields it needs through the command object, as well as all error messages returned by the command validation.

Wednesday, 1 September 2010

Revisiting .NET

Its been a fair while since we've been commissioned to do any projects with .NET, and it looks like Microsoft have been busy in the interim!

First some background. Mark and myself both started out working for a Microsoft Certified Solution provider, and back then most of the coding work was in Visual Basic. Web applications were starting to get more sophisticated (our first "web" applications were old school ASP with Visual Basic ActiveX DLLs running on IIS3 and 4) but everything felt a bit hacked together. We then did some work with MTS (Microsoft Transaction Server) which improved things a bit, but it wasn't until the first versions of .NET came along and Mark and myself persuaded the company to let us do a major project using C# that web applications became the norm for the company.

Since we set up Digital Morphosis, however, our focus has been on cross-platform web applications, mostly written in Java (and more recently Groovy & Grails), although we've done a handful of .NET applications since, so its been a bit of a learning curve getting back into .NET development.

Our latest .NET project has allowed us to get right up-to-date with the latest and greatest .NET technologies, so I've learned quite a bit about the state of play of .NET and how it compares with how we do things in Java, and have lots of things to write about, notably:

  • ASP.net MVC 2 and how similar it is to Spring Web MVC and Grails
  • Getting Visual Studio 2010 express set up to run NUnit tests
  • Unit testing with NUnit and Moq
  • Continuous integration with .NET and Hudson

I'll be posting more over the next few weeks. Hopefully this should serve as some help for Java developers who have to make the switch.