Confusion about URLMapping - grails

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'

Related

Grails Urlmapping 404 for group

I organized my url mappings in grails with groups.
Example from UrlMappings:
class UrlMappings {
static mappings = {
group "/rest", {
"/" {
controller = "rest"
action = "index"
}
"/method1" {
controller = "rest"
action = "method1"
}
}
"/webservice/" {
controller = "webservice"
action = "index"
}
}
What I want: When the Url is called /rest/notexists, I want a 404 for this path. But only for /rest group, so the 404 should belong to the group rest. Other 404 are handled by my backbone router.
Any ideas?
I solved it with a catch all at the end of the rest group:
"/**" {
controller = "rest"
action ="notFound"
}

Grails 3.2 - defaultAction ignored on scaffolded controllers?

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()]
}

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() {
.....
}
}

Grails: Can't figure out why I'm getting a 404

I'm using Grails 1.3.6. I have this file ...
grails-app/views/home/design/index.gsp
Here is what is defined in my HomeController. Sadly, whenever I visit, "http://localhost:port/context-path/design/", I get a 404 error. The server starts normally and there are no errors in the logs. What can I do to get my page instead of the 404?
def index = {
def folder = params.folder;
def page = params.page;
if (page) {
try {
def contents = IOService.getFileContents(folder, page)
response.setContentType("application/json")
response << contents
} catch (FileNotFoundException e) {
response.status = 404;
} // try
} else {
render(view: "/home/${folder}/index")
} // if
}
My URLMappings file consists of ...
static mappings = {
"/$folder?/$page"{
controller = "home"
action = "index"
}
"/"(view:"/index")
"500"(view:'/error')
}
Thanks, - Dave
If you want to be able to access
/context-path/home/design
Your action needs to be named design, i.e.
class HomeController {
def design = {
}
}
The Grails convention is always /context-path/controllerName/actionName (unless you have it mapped differently in grails-app/conf/URLMappings.groovy).
Your example's a bit unclear which path you're trying to access. To address both:
If you want /context-path/design, you need a DesignController with an index action (because if no action is supplied in the URL, Grails looks for the index action).
If you want /context-path/home/design, you need a HomeController with a design action.
Edit:
In the comments, you express the want to be able to have /context-path/design map to the HomeController index action. You can do this with grails-app/conf/URLMappings.groovy:
"/design"(controller: 'home', action: 'index')
Since it seems you have two distinct actions, I would set things up a bit differently:
def indexWithPage = {
def folder = params.folder;
def page = params.page;
try {
def contents = IOService.getFileContents(folder, page)
response.setContentType("application/json")
response << contents
} catch (FileNotFoundException e) {
e.printStackTrace();
response.status = 404;
} // try
}
def index
def folder = params.folder;
render(view: "/home/${folder}/index")
}
with a URLMaping of:
static mappings = {
"/$folder/$page"{
controller = "home"
action = "indexWithPage"
}
"/$folder"{
controller = "home"
action = "index"
}
"/"(view:"/index")
"500"(view:'/error')
}
I also threw a e.printStackTrace(); in there to help us determine whether you're getting YOUR 404 or the action is truely not being called.

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