Grails: URL mapping with .gsp extension/format - grails

I have a url request like www.xyz.com/customer/list.gsp
When I try to map the url to remove .gsp:
"/customer/list.gsp"(controller: "customer") {
action = "list"
}
grails application won't recognize the url and is throwing 404 error. Am I missing something here?

If you want to remove .gsp from the url then you can use a mapping like this...
"/customer/list"(controller: "customer") {
action = "list"
}
You could also do this...
"/customer/list"(controller: "customer", action: "list")
If you want 1 mapping for all the actions in the controller, you could do this:
"/customer/$action"(controller: "customer")
The default generated mapping includes "/$controller/$action" which allows you map to any action in any controller.
With any of that, sending a request to /customer/list would work.

Update: apparently it is fine to map to GSPs. I still think that the info below may be helpful so I'm leaving the answer up, but perhaps I have misunderstood your question.
Original response:
You shouldn't be mapping to or requesting gsps at all. They're used to generate views, but are not viewable without rendering.
Instead, go to url like www.xyz.com/customer/list and map that like
"/customer/list" (controller: "customer") {
action = "list"
}
Or even better, you don't need a custom mapping for each endpoint. A default like this will work:
"/$controller/$action?/$id?" { }
Your CustomerController will render the list.gsp in the list action.

Related

Grails <g:link> rewriting links to match UrlMappings instead of controller/action

Currently using grails 4.0.3.
I'm trying to generate a link to a controller action using a simple <g:link> tag:
<g:link controller="myController" action="myAction" params="[someParam:'myValue']">Link text</g:link>
In my UrlMappings file, I have this controller mapped to a common URL for external calls. This mapping forces some parameters that I want forced when coming to this mapping:
class UrlMappings {
static mappings = {
"/service/someExposedUrl" {
controller = "myController"
action = "myAction"
someParam = "defaultValue"
}
}
}
However, the link that gets written to the page in my application gets written using the UrlMapping definition.
http://serverUrl/service/someExposedUrl?someParam=<ignored>
instead of
http://serverUrl/myController/myAction?someParam=myValue
In this case, the parameters are ignored on the /service URL because they're hard-coded in the UrlMapping.
Is there a way to force grails to link to the specified controller/action instead of the mapping?
Up front caveat: I have not tested this for this specific situation, though I have used these pieces individually. Second caveat: I would not be remotely surprised to learn there's an even better way to do this...grails has a lot of options sometimes!
You should be able to create a named mapping in your UrlMappings, then reference that in your createLink.
UrlMappings:
name arbitraryName: "/myController/myAction" {
controller = "myController"
action = "myAction"
}
Link:
<g:link mapping="arbitraryName" params="[someParam:'myValue']">Link text</g:link>
You may be able to get what you need with a combination of Custom URL mapping and the exclude keyword in the original URLMappings.
Create MyControllerUrlMappings. This guide gives several examples of different ways of writing them out. I found it helpful.
class MyControllerUrlMappings {
static mappings = {
// Url Mappings specific only to this controller
}
}
https://guides.grails.org/grails_url_mappings/guide/index.html#_multiple_urlmappings_files
Your app will still be running the original UrlMappings file though. So you'll have the new custom Url mappings and the default ones. To fix that you can exclude your controller and it's methods in the original UrlMappings file.
class UrlMappings {
static excludes = [
"/myController",
"/myController/*"
]
static mappings = {...}
...
Not as elegant as I'd like, but in a similar situation this is how I got it working.

Grails dynamic url mapping

I have a product list I'm trying to create SEO-friendly URLs for.
Example
domain.com/product/cell-phone-razor
"cell-phone-razor" is dynamic from the db
I have successfully achieved this behavior with the following code
"/product/$url"(controller: "product", action:"show")
However there becomes an issue when trying to map other actions non related to the page URL. Example I have an Ajax URL domain.com/product/setPrice which is being mapped to the show action.
I was able to work around this by adding the following to my urlmapping in addition to the previous mapping.
"/product/setPrice" {
controller = "product"
action = "setPrice"
}
Is there a better way to config my url mapping so that I don't need to add rules for every action mapping?
In our application we use the following approach - not saying the perfect one. Basically we're appending URL fragments (that are happily ignored by search engines) to the SEO parts of the URL.
name product: "/$productName-p$productId" {
controller = 'product'
action = 'show'
constraints {
productName matches: '.+'
productId matches: '^[0-9]+$'
}
}
In your case the url should look like domain.com/product/cell-phone-razor-p123455 where 123456 is the product id.
Although not as dynamic as I'd like, but this seems to be the best solution.
"/product/$url"(controller: "product", action:"show") {
constraints {
url(validator: {
return !(it in
['setPriceAction', 'setAnotherAction']
)
})
}
}

different mapping for the same url

I would like to use a different mapping for the same url http://localhost:8080/myapp/ when the user is logged in (session.user)
Actually, as default Im giving the path when the url is "/" to AppController and 'index' action... but if I try to redirect inside the index action when the user is logged to my UserController (also index action), the path changes to http://localhost:8080/myapp/user/index . Thats not what I`m looking for.
There is a plenty of website (twitter, facebook..) that apply this method, but couldn`t understand how can it be done in Grails, without using the same action for example (AppControlle>index) and render different views when user is active.
static mappings = {
"/"(controller:"app",action:"index")
"/$controller/$action?/$id?"{
constraints {
// apply constraints here
}
}
"500"(view:'/error')
"404"(view:'/notFound')
}
About your mention about twitter, facebook... I think it's possible that they use different mapping based on the request is POST or GET. In Grails, we can do that kind of mapping like this:
name home: "/" {
controller = [GET: "app", POST: "user"]
action = [GET: "index", POST: "userIndex"]
}

How to create canocical from controller in grails?

In grails, I have a link like /myapp/questions/all
The all is a parameter (all, replied, ...) passed to my controller.
I have a form to search question depending of type : in all, in replied, ...
In the search form, I have an hidden field to pass parameter.
But the url displayed is /myapp/questions/ ans not /myapp/questions/all
So I tried with url : url="[action:'question', controller:'mycontroller', params:['monparam':'${mavariable}']]"
but it's not working.
Any idea ?
Thanks
You can do it like this:
class UrlMappings {
static mappings = {
name nameOfTheMapping: "/question/$para/" {
controller = "mycontroller"
action = "question"
}
...
Then you can access the mapping by:
<a href='${createLink(mapping: 'nameOfTheMapping', params: [para: para.encodeAsUrl()])}' title='test'>Test</a>
The above code is created in my taglib, so it maybe a little different if you want to use it in a view.
I don't completely understand your question, but it seems you are not following the grails convention. the url is of the form
/app/controller/action
so grails is interpreting the 'all' part of your url as the action to invoke on the questions controller (what I got from your 'link like /myapp/questions/all').
Where I got confused was with your url specification.
url="[action:'question', controller:'mycontroller', params:['monparam':'${mavariable}']]"
Based on that, you should have a controller called 'mycontroller', with an action called 'question' on it. The url you will see in the browser would be
/app/mycontroller/question?monparam:whatever
See here for details on controllers in general.
You need to edit grails-app/conf/UrlMappings.groovy and create a mapping to the controller that omits the action. (since you're handling this all within one action)
something like
"/questions/$question_type" (controller: 'questions', action: 'your_action')
where "your_action" is the name of the action that is processing these requests.
Then in QuestionsController.groovy:
def your_action = {
// use question_type as needed
def questions = Questions.findByQuestionType(params.question_type)
// etc.
}
You can do a variety of things to affect the mapping of urls to requests, check out the UrlMapping section in the Grails User Guide.

URL Mapping prefix in Grails

Recently, I'm trying to migrating my application from CakePHP to Grails. So far it's been a smooth sailing, everything I can do with CakePHP, I can do it with much less code in Grails. However, I have one question :
In CakePHP, there's an URL Prefix feature that enables you to give prefix to a certain action url, for example, if I have these actions in my controller :
PostController
admin_add
admin_edit
admin_delete
I can simply access it from the URL :
mysite/admin/post/add
mysite/admin/post/edit/1
mysite/admin/post/delete/2
instead of:
mysite/post/admin_add
mysite/post/admin_edit/1
mysite/post/admin_delete/2
Is there anyway to do this in Grails, or at least alternative of doing this?
Grails URL Mappings documentation doesn't help you in this particular case (amra, next time try it yourself and post an answer only if it's any help). Daniel's solution was close, but wouldn't work, because:
the action part must be in a closure when created dynamically
all named parameters excluding "controller", "action" and "id" are accessible via the params object
A solution could look like this:
"/admin/$controller/$adminAction?/$param?"{
action = { "admin_${params.adminAction}" }
}
The key is NOT to name the parameter as "action", because it seems to be directly mapped to an action and can not be overriden.
I also tried a dynamic solution with generic prefixes and it seems to work as well:
"/$prefix/$controller/$adminAction?/$param?"{
action = { "${params.prefix}_${params.adminAction}" }
}
I didn't test it, but try this:
"mysite/$prefix/$controller/$method/$id?"{
action = "${prefix}_${method}"
}
It constructs the action name from the prefix and the method.
Just take a look on grails URL Mappings documentation part

Resources