another grails urlmapping question - grails

ok, so i asked, and got an answer on how to make a single controller instance case-insensitive vis-a-vis urls. I can do
"/mycontroller/$action?/$id?"(controller: "myController")
so when an app outside tries to reference link in our app, their lowercase urls ( :( sigh ) will work.
I need to extend this to include actions as well. So the question is, following the above approach, do i need put a url mapping in for each action?
/mycontroller/methodone/(controller: "myController", action: methodOne)
/mycontroller/methodtwo/(controller: "myController", action: methodTwo)
Something like the above?

This is similar to the question below which I have answered and included source code
How to make my URL mapping case insensitive?

You can use a closure to calculate the action (or other parameters) programmatically:
"/mycontroller/$a?/$id?" {
controller = 'myController'
action = { params.a?.toLowerCase() }
}

Related

Grails: URL mapping with .gsp extension/format

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.

Routing with dashes and non-english characters

I have a specific routing need that I can't get to work. I've found quite a few answers here on StackOverflow that takes me a bit on the way, but not all the way.
Im naming my controllers and actions in the standard C# way, i.e. the first letter of every word is uppercase:
MyController.MyAction()
To reach this action method, I'd like all of these urls to work:
/my-controller/my-action
/my-cöntroller/my-äction
/MyController/MyAction
/MyCöntroller/MyÄction
(the two last ones are not super important though...)
So there's two things here:
Dashes may be used to separate the words (for readability and SEO
purposes).
Some non-english characters can be used (all replacements
specified - no "magic").
I want to create the links with helpers like this:
#Html.ActionLink("My link text", "MyController", "MyAction")
i.e. the standard way, and this will create the following link:
/my-controller/my-action
Hopefully this could be done without making my routing configuration too messy (e.g. with one route for every action or something), or putting attributes on all action methods, but if thats the only solution I'd like to know.
What I've tried so far is implementing a custom route class overriding GetRouteData() and GetVirtualPath(). It got me closer but not all the way, but I might do something wrong
I had an idea for solving the problem with non-english characters by doing the replacement before the routing is performed, but I haven't found a way to do this yet (see this question).
I'd be really greatful if someone could help me with this, or at least point me in the right direction! :)
Edit: Note that the example urls above are just to describe what I want. In reality there is a lot of urls that must be handled, so I'd prefer some generic solution and not one involving one route for every action or something like that.
Create your resource file
Name Value
myaction1 my-äction
myaction2 my-action
mycontroller1 my-cöntroller
mycontroller2 my-controller
Add following routes in RegisterRoute method in global.asax
routes.MapRoute(
name: "route1",
url: Resources.Actions.mycontroller1 + "/" + Resources.Actions.myaction1 ,
defaults: new { controller = "mycontroller1", action = "myaction1" }
);
routes.MapRoute(
name: "route2",
url: Resources.Actions.mycontroller2 + "/" + Resources.Actions.myaction2,
defaults: new { controller = "mycontroller2", action = "myaction2" }
);
In controller,
[HttpGet]
public ActionResult myaction1()
{
return View("");
}
[HttpGet]
public ActionResult myaction2()
{
return View("");
}
In _Layout.cshtml
#Html.ActionLink(Resources.Actions.myaction1, "myaction1", "mycontroller1")
#Html.ActionLink(Resources.Actions.myaction2, "myaction2", "mycontroller2")

How to set urls from controller action in cakephp?

I was creating a social networking site, in that each profile page needs to show using a seo friendly url.
Now its like www.siteprof.com/profile/23
i need to add aditioanl string 'jake-web-developer' at the end of this url. result will be like www.siteprof.com/profile/23/jake-web-developer. I know that this can be done when we create profile links. But if someone access this profile using www.siteprof.com/profile/23 this link, can i add that previous text to the url ?
Also is there any method to add these kind of particular string into url from controller actions ?
That doesn't look correct, by CakePHP convention, it should look like:
**www.siteprof.com/profiles/view/23**
After that you set up the profiles_controller to have the action view($id=0,$name="")
I don't know why that is important, but you can generate links with the name parameter and it would still work:
www.siteprof.com/profiles/view/23/jake-web-developer
If it's important to add the last string, then you should do a redirect in the view controller. Check if the $name is specified, and if it isn't, redirect to the URL with the name, although I'd advise against it since it's a performance hit.
My solution would be to put a custom redirect header in the page if the url doesn't contain the SEO friendly title which redirects to the full url
One method would be:
public function view($id = null, $slug = null) {
$data = $this->Profile->findById($id);
if ($slug == null) {
$this->redirect(array('action'=>$view, $id, $data['Profile']['slug']));
}
// .. rest of view logic
}
Hope this helps :-)

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