Grails "loses" custom URL mapping when following any links on the page - grails

I have an application where users can browse maps in two ways (like thumbnails and in a list)
/map/browse
/map/list
Now, I would like to restrict these views to just show maps of a specific user, for example through
/user/3/browse
/user/3/list
So I created the mapping:
"/user/$userId/browse" {
controller = "map"
action = "browse"
}
"/user/$userId/list" {
controller = "map"
action = "list"
}
Now, I can go to /user/3/browse, but as soon as I click on a pagination link or change the pagination filters, the URL goes back to /map/browse.
Also, if I set the userId to null in the controller, I get the error:
Error 500: Error processing GroovyPageView: Error executing tag : Unable to create URL for mapping [/user/(*)/list] and parameters [["action":"list", "controller":"map", "max":20, "offset":0, "sort":"uploadDate", "order":"desc", "userId":null, "totalMaps":30]]. Parameter [userId] is required, but was not specified! at /views/map/browse.gsp:26
The pagination works as follows:
<div class="paginateButtons">
<g:paginate controller="map" action="browse" total="${mapInstanceTotal}"></g:paginate>
</div>
What can I do against that or what would be the correct way of implementing what I want?
I don't necessarily need to have that URL mapping, I only need a nice way of saying: "Display maps of only one user"

It seems that the problem is not at your URL mapping configuration ,but in your way to create link. I think it's better if you use Named URL Mapping : it's clearer than your approach now, and when create link for pagination you only need to specify the url name. For example:
In UrlMappings.groovy:
static mappings = {
name accountDetails: "/details/$acctNumber" {
controller = 'product'
action = 'accountDetails'
}
}
In view - gsp page:
<g:link mapping="accountDetails" params="[acctNumber:'8675309']">
Show Account
</g:link>

Related

How to resolve links to content items inside a rich text ? (Kontent.ai - ASP.NET framework)

So I followed the Kontent doc from the github which allows to retrieve content from a link (https://github.com/Kentico/kontent-delivery-sdk-net/wiki/Resolving-links-to-content-items)
First I implement a resolver to redirect when we click on the link like this :
public class CustomContentLinkUrlResolver : IContentLinkUrlResolver
{
public string ResolveBrokenLinkUrl()
{
return "/404";
}
public string ResolveLinkUrl(ContentLink link)
{
switch(link.ContentTypeCodename)
{
case "author":
return $"/author/{link.UrlSlug}";
default:
return $"/not_found";
}
}
}
Then I register my resolver within a IDeliveryClient
client = DeliveryClientBuilder
.WithProjectId(myid)
.WithContentLinkUrlResolver(new CustomContentLinkUrlResolver())
.Build();
At this moment if i click on the link it will redirect to /author/linkName with an error on the page what I think is normal
I don't get the last part of the doc (how just by doing a getString on the contentItem the link will work ?) so I would like to know how to display the content on the redirect page
I don't know if i was clear enough and sorry for my english
Here is the error thrown on the redirect page
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
The last part of the wiki article refers to something that you already have:
At this moment if i click on the link
If you have a link that you can click on, then you have done what that part of the article describes.
What you need is to resolve the request. If you are getting a 404 that you expect, then you know that you need to add a route to your application to handle the request. In the handler (a controller, a component, etc.) extract the urlSlug from the route and use it with a IDeliveryClient to retrieve the item and then render the content. You will need to filter the GetItems call with something like new EqualsFilter("elements.urlSlug", urlSlug).

How to check route parameter exists in layout page asp.net MVC

I have 2 parameters in url id & text. I am trying to check whether 'text' exists in layout page because initially I will have only Id and later I am addding 'text' to url from different action but same controller.
I have following code in my layout page but it works only when both parameters are available.
var Newid,Newtext;
Newid = ViewContext.RouteData.Values["id"];
Newtext = ViewContext.RouteData.Values["text"].ToString();
I am trying to check when my url is localhost:8122/products/12
#
{
if(ViewContext.RouteData.Values["text"].ToString()!=null)
{
}
}
but it gives object reference error.
I have to include .tostring() since I am checking like below in the same page
#if (Newtext =="t") {}

How do I redirect a URL in Grails to go to a specific Controller/action?

So, I am running my grails application and the URL generated from the localhost is http://localhost:8888/appname/
When I enter the above link in the URL, I want it to be redirected to http://localhost:8888/appname/controller1/action1
This is my UrlMappings,
static mappings = {
"/"(controller: 'controller1', view: 'action1')
.
.
.
}
When I do this, I am not getting the desired output. The URL doesn't change. But, I am getting the page desired. However, certain elements of the page don't load (For example, I have a jqGrid).
Please help!
you should do
"/"(controller: 'controller1', action: 'action1')
i.e in place of view it should be action
"/"(redirect: [controller: 'controller1', action: 'action1'])
https://grails.github.io/grails-doc/latest/guide/theWebLayer.html#redirectMappings

Reconstructing a Razor URL using referring URL and language selection

To implement language selection in an MVC Razor application, I use a leading path segment in the route mapping like www.mydomain.com/lang/controller/action/id?param= where lang is a 2 letter ISO country code like fr, de, it, en etc
I use the following route mapping (which works fine):
// Special localisation route mapping - expects specific language/culture code as first param
routes.MapRoute(
name: "Localisation",
url: "{lang}/{controller}/{action}/{id}",
defaults: new { lang = "en", controller = "Home", action = "Index", id = UrlParameter.Optional },
constraints: new { lang = #"[a-z]{2}|[a-z]{2}-[a-zA-Z]{2}" }
);
Previously I generated my language selection links in the master page, so that they were simply variations of the current URL (with only the first segment changed). Now I need to be able to create the links from within a partial view, that may be loaded dynamically via Ajax and the menu items (countries) are data driven.
That means I need to take the referring URL instead (the actual loaded page) and modify it to have a new language inserted, for each available language. The menu items are all database driven, so only contain the 2 letter language code and the display name.
Googling for "how to separate a URL into controller and action" I found an interesting link here: http://average-joe.info/url-to-route-data/
Based on that link, this is what I tried, but it blows up on a root URL like http://localhost:51176/ or with a full URL like http://localhost:51176/en/home/index. I would have expected it to return the defaults of home (controller) and index (action). Instead I get a Null reference exception.
string path = Request.UrlReferrer.ToString();
string queryString = ""; // Blank for now
System.Web.Routing.RouteData routeFromUrl = System.Web.Routing.RouteTable.Routes.GetRouteData(new HttpContextWrapper(new HttpContext(new HttpRequest(null, new UriBuilder(Request.Url.Scheme, Request.Url.Host, Request.Url.Port, path).ToString(), queryString), new HttpResponse(new System.IO.StringWriter()))));
// Blows up with Null exception as routeFromUrl is always null
string controller = (string)routeFromUrl.Values["controller"];
string action = (string)routeFromUrl.Values["action"];
string id = (string)routeFromUrl.Values["id"];
The idea being I can then generate links with href values like these using the referrers controller, action and parameters and therefore stay on the "same page" (except for the obvious language change):
http://localhost:51176/en/home/index
http://localhost:51176/de/home/index
http://localhost:51176/fr/home/index
What is wrong with the way I have used that piece of code (or does it just not work as I expected)?
Do'h... so simple.
Just needed to supply the path part of the URL only as it uses the current scheme, host & port applied to that path.
string path = Request.UrlReferrer.AbsolutePath;
Also note (valuable tip):
If you follow that example I linked, like I did, you need to adjust the following to use ToString() as they do not cast to string when empty:
string controller = routeFromUrl.Values["controller"].ToString();
string action = routeFromUrl.Values["action"].ToString();
string id = routeFromUrl.Values["id"].ToString();
This will give controller="home", action="index" and id="" as expected! Phew

Redirection in Grails Web-flow

I have question regarding redirection in Grails web-flow.
I am in a view state which will allow users to enter the answers for a question. On 2 wrong attempts I should be able to re-direct the user to view page from different controller. What i mean is
challengeQuestionOne{
onRender() {
//Display question
}
on('next') {BuildQuestion command ->
bindData(flow.recovery,command)
[return the model to flow]
if(command.hasErrors()) {
flow.command = command
return error()
}
if(check for status. If doesnot pass){
flash.message=message(code:'loginForm.account.locked', default: 'Please Contact Admin.')
redirect(controller : "login",action: "login")//how to redirect from here to diff controller
}
if (//compare answer entered) {
}
else{
//set status not active
}
}.to("challengeQuestionTwo")
on(Exception).to("error")
on('cancel').to('finish')
}
I have tried to redirect from onRender . It was redirecting to the page. But how do I display the error msg on the redirected page. How can i forward the error message from one controller to other??
Ivo Houbrechts wrote an excelent tutorial about grails webflow:
Webflow defines its own flash scope. Although it has the same semantics as the standard grails flash scope (the main purpose is to store objects only until after the next request), it is a different scope. This means that objects stored in webflow's flash scope are not visible in standard grails actions.
import org.springframework.web.context.request.RequestContextHolder
....
RequestContextHolder.currentRequestAttributes().flashScope.message = "YourMessage"
You can read more here:
http://livesnippets.cloudfoundry.com/docs/guide/
Flash scope will not work in this case as expected.
Try to use another approach to show error. E.g. you can pass parameters with redirect. Or you can throw some exception and check it on rendered page as follow:
<g:if test="${flowExecutionException}">
<div class="error"><g:message code="loginForm.account.locked"/></div>
</g:if>

Resources