Grails 3.2 - defaultAction ignored on scaffolded controllers? - grails

Curious if this is an issue or if I'm doing something wrong. Given the following controller:
class MetaDataTypeController {
static scaffold = MetaDataType
static defaultAction = 'list'
def list() {
render("You meant ${g.link(action: 'index', '/index')}")
}
def index() {
[metaDataTypeList: MetaDataType.list()]
}
}
accessing the application at "/app/metaDataType", I would expect to see the "list" action, with a link to "index". What I see is the "index" action. If I remove the static scaffold declaration, it works and I'm shown the link.
Is this intentional? Am I just overlooking something.
Edit: typo fixed

Do as like that
class MetaDataTypeController {
static scaffold = MetaDataType
def index() {
redirect(controller:'MetaDataType',action:'list')
}
def list() {
[metaDataTypeList: MetaDataType.list()]
}

Related

Grails actions getting called twice

The getStarted action redirects to companyInfo action which renders companyInfo.gsp and immediately after the page rendering, companyInfo action getting called one more time. I don't understand what the problem is.
class MyController {
#Secured('ROLE_USER')
def getStarted(){
def renderParams = [view: 'getStarted', model: [:]]
if(request.method != 'POST') {
render(view: 'getStarted')
} else {
def company = new Company()
.......
redirect(action: 'companyInfo', params: [id: company.id])
}
}
#Secured('ROLE_USER')
def companyInfo() {
def renderParams = [view: 'companyInfo', model: [:]]
if (request.method != 'POST') {
renderParams.model.cmpId = params?.id
render(renderParams)
}
}
}
See this answer. Grails trys to map get* to properties. And when the controller is called grails tries to map getStarted to a property called started, calling the method. So, Never Use get**** as your action name

Grails 2.2.0 URLMappings: Any way to use same URL with Different Verb

I have the following:
"/api/users"(controller: "user") {
action = [GET:"list"]
}
Doing a call to http://localhost:8080/platform/users I get a list of users back. Then I added this:
"/api/users"(controller: "user") {
action = [POST:"save"]
}
And now I get a 404 and it is not hitting either method in UserController. I'd like to be able to use the same URL with the verb controlling which action. Am I doing this wrong or does Grails not support this?
From the Grails docs: URL Mappings
static mappings = {
"/product/$id"(controller:"product") {
action = [GET:"show", PUT:"update", DELETE:"delete", POST:"save"]
}
}
For your case:
"/api/users"(controller: "user") {
action = [GET:"list",POST:"save"]
}
Check your userController to see if there is allowedMethods defined accordingly like this:
class UserController {
static allowedMethods = [save: "POST", list: "GET"]
def list() {
.....
}
def save() {
.....
}
}

Why can't I access injected service from scaffolding template for controller?

I have a controller which looks like this:
class CategoryController {
static scaffold = true
def messageSource
def categoryService
...
}
I want to modify Controller template to use service when needed:
class ${className}Controller {
static allowedMethods = [save: "POST", update: "POST", delete: "POST"]
def list() {
def domainObjectsProperty = ... //long complex line
render view: "/${domainClass.propertyName}/list", model: [(domainObjectsProperty): ${domainClass.propertyName}Service.list()]
}
...
}
Expression ${domainClass.propertyName}Service is evaluated to categoryService, but I get message:
No such property: categoryService for class:
mypackage.CategoryController
At the same time, when I call not scaffolded methods of CategoryController, which use CategoryService, everything is fine.
What causes this behavior and how to work around the issue? Thanks!
I think you forgot the service injection
class ${className}Controller {
def ${domainClass.propertyName}Service
...
}

Confusion about URLMapping

I'm running Grails 1.3.6. I have this in my URLMappings.groovy file ...
static mappings = {
"/$folder?/$page?"{
controller = "Home"
action = "index"
}
"/"(view:"/index")
"500"(view:'/error')
}
and this is my HomeController ...
class HomeController {
def IOService
def index = {
def folder = params.folder;
def page = params.page;
def contents = IOService.getFileContents(folder, page)
response.setContentType("application/json")
response.text = contents
}
}
however, when I visit my URL "/context-path/folder1/page1", I'm getting an Apache Tomcat 404 error (complaining about "/context-path/folder1"). I'm new to Grails but can't figure this out. How can I adjust my mappings to make this work?
Thanks, - Dave
I'm not sure if controller/action definitions are case-insensitive. I've always used lowercase names. Try changing
controller = "Home"
to
controller = 'home'

Best practices for grails index page

What is the right way to populate the model for the index page in a grails app? There is no IndexController by default, is there some other mechanism for getting lists of this and that into the model?
I won't claim that this is the right way, but it is one way to start things off. It doesn't take much to have a controller be the default. Add a mapping to UrlMappings.groovy:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"500"(view:'/error')
"/"
{
controller = "quote"
}
}
}
Then add an index action to the now default controller:
class QuoteController {
def index = {
...
}
}
If what you want to load is already part of another action simply redirect:
def index = {
redirect(action: random)
}
Or to really get some reuse going, put the logic in a service:
class QuoteController {
def quoteService
def index = {
redirect(action: random)
}
def random = {
def randomQuote = quoteService.getRandomQuote()
[ quote : randomQuote ]
}
}
I couldn't get Ed T's example above to work. Perhaps Grails has changed since then?
After some experimentation and some rummaging on the net, I ended up with this in UrlMappings.groovy:
"/"(controller: 'home', action: 'index')
My HomeController looks like this:
class HomeController {
def index = {
def quotes = = latest(Quote.list(), 5)
["quotes": quotes, "totalQuotes": Quote.count()]
}
}
And in views/home, I have an index.gsp file. That makes the index.gsp file in views unnecessary, so I removed it.
The good answer: If you need to populate a model for the index page, it's time to change from using a straight index.gsp to an index controller.
The evil answer: If you create a filter whose controller is '*', it'll get executed even for static pages.
In grails 1.3.6 for just adding
"/index.gsp"(uri:"/")
to UrlMappings.groovy worked fine for me. It has the same effect as adding a new controller and mappings like described before.
Below is my complete UrlMappings.groovy:
class UrlMappings {
static mappings = {
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
"/index.gsp"(uri:"/")
}
}

Resources