====== Controller ====== Grails controller mainly handle the HTTP request. It also automatically map a URL to its method. The controller class must located at ''/grails-app/controllers/'' directory. ===== Creating a Controller ===== Grails Console: Type the following code with your own controller name, and a controller with your app package will be created. create-controller YOUR_CONTROLLER_NAME Intellij: Right click the controller directory in Project View, and select **New->Grails Controller** in the pop up menu. Input the controller name in the pop up dialog, and Intellij will do the rest. ===== URL Mapping ===== By default, the controller name will be path of the URL. Assume our controller named TestingController: class TestingController { def index() { render "/testing/index" } def a() { render "/testing/a" } def b() { render "/testing/b" } } When we run the app, we will have 3 new URLs * http://127.0.0.1:8080/testing/index * http://127.0.0.1:8080/testing/a * http://127.0.0.1:8080/testing/b They are related to the controller's name, and method's name by **grails convention**. ===== Flash, Params, Session, Request, Response ===== Like Spring Boot, we can access params, session, request, response,... in the controller. To use them in controller, simply type ''flash'', ''request'', ''response'', ''session'', ''params'' inside a method. You do not need to add them into your method header as parameters as spring boot does. You can use it inside your controller such as: def methodB() { String path = request.getPathInfo() response.setStatus(200) session.setAttribute("ATTRIBUTE_KEY", "My Object") String token = params.get("token") flash.message = "OK" render "/testing/methodB" } ==== Flash (FlashScope) ==== Flash, or more correctly FlashScope, is a map for temporarily storage for next request, and it will be cleaned up afterward. You can put value in flash by flash.YOUR_KEY = YOUR_VALUE, and then in the view, gsp for instant, read the value and render it. It can store any type of Object. ==== Params ==== Params, or more correctly GrailsParameterMap, is a mapping for any kind of input from HTTP GET or POST. Assume we have a HTTP GET request like http://127.0.0.1/testing/methodB?token=MY_TOKEN, we can get this input by calling ''String token = params.get("token")'' in our ''methodB'' method. ==== Session, Request, Response ==== They are just Java servlet session, request, and response. ===== Method Taking Command Object as Parameter ===== It is possible to map a HTML form input to a parameter of a method in a controller. Assume we have a TestController, and a method called methodA which table a parameter (command object) CommandObject. CommandObject: class CommandObject implements Validateable { Long start Long end static constraints = { start nullable: true end nullable: true } String toString() { return start != null ? start : "" + " to " + end != null ? end : "" } } TestController: class TestController { def methodA(CommandObject commandObject){ render(commandObject.start+" "+commandObject.end) } } The URL for this method would be http://127.0.0.1/test/methodA. In order to pass such command object to methodA, we can do a HTTP GET request by http://127.0.0.1:8080/test/methodA?commandObject.start=1&commandObject.end=10, or by a HTTP POST request with a from in GSP like: Note that the command object need to **implements Validateable**, and you need to add the **constraints{...}**. In the controller by default, the command object **will be created** once the method is called even if nothing has passed in. Grails will create the command object with its default constructor. The command object you can .validate() the command object if needed. You can pass **multiple command objects** in to a method as soon as their names match to the one in the function prototype. It is even possible to pass ''MultipartFile'' attachment to a command object, but you need to make sure that HTTP form enctype is multipart/form-data: ===== Passing Values, Objects to GSP View ===== When creating a controller, a directory with the same name as the controller will be created under ''/grails-app/views/''. We can pass the values from controller to view by using the following code. The model is the key here. it is a map with the key as the name we access the object in the view, and the value as the object name in the controller. respond([], view: "YOUR_VIEW_NAME", model: [object1NameInView: object1InController, object2: object2, object3: object3])