Rendering grails views on different sub URL - grails

I am creating a rest based web application. i want all the rest based pages (HTML pages) should go into webapps folder and should be accessible at from there with the below URL
http://localhost:8080/myapp.
Above URL should render index.html lying in webapps folder. And all the subsequent pages should open from webapps folder only.
For the admin part i want to use grails views(GSP) and they should be accessible at
http://localhost:8080/myapp/admin
Above url should render the index.gsp page lying in grails-app/views/index.gsp.
To list all users on admin site, i want URL to be some thing like this
http://localhost:8080/myapp/admin/user/list and this should point to grails-app/views/user/list.gsp and userController with action list
Is there a way this can be achieved in Grails

Grails exposes your controllers and views using conventions by default. However, if you want to break that convention you can. There is nothing stopping you from re-working how the URL mappings are done in your application. In fact there is an entire section of the documentation dedicated to it.
Let's pretend for a second you wanted all your controllers to be under /admin/ you could easily change your UrlMappings.groovy to look like this:
class UrlMappings {
static mappings = {
"/admin/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
}
Once you read through the documentation you should be able to map things however you want. The key is you have to define how you want them mapped.

Related

Applying a master page template in Sling with HTL

Is there any simple way to apply a page template to multiple Apache Sling scripts?
I'm looking for something akin to the JSP 2.0 Tag option. However, I'm using HTL, which doesn't support such tags.
I could, of course, use HTL includes, such as data-sly-include="${'header.html'}, but these would then have to be manually included in every page I then create.
Ideally I'd like to be able to have a master page containing the layout, which is then automatically applied to all pages of specified resource types, leaving a customisable area for content specific to each resource. I'd then be able to limit my add.html, edit.html, html.html (etc) files to include only a block of code for the content section of the page, preventing unnecessary duplication of layout code across multiple files.
I thought I might be able to achieve this by creating a master page resource (e.g. "page"), then setting sling:resourceSuperType on the individual resources but since this acts as a fallback, it'll only kick in if there's no matching script for the sling:resourceType - and there will be such scripts.
You could use a Sling Decorator to wrap your resources so that they always get handled by the common scripts before everything else. This way you can impose the template and include the actual resource to fill in the actual values/blocks/custom scripts.
Another option would be to impose a (nested) content tree where the root points to the template scripts (using JCR type, for example) while the children/content point to the custom scripts (using resource type). This is pretty much what AEM does with cq:Page and its jcr:content.
I ended up using the following approach:
Add a new resource type page
Create a Sightly/HTL template file for the page resource type (/apps/page/html.html); this is the 'master' page template
Include common elements in that template
Within that template, call the 'child' templates by adding the view selector through the following HTL element: <div data-sly-resource="${request.pathInfo # selectors='view', addSelectors=request.requestPathInfo.selectors, requestAttributes=request.requestParameterMap}">
For each sling:resourceType that's to be rendered as a page, add a view subfolder (/apps/example_type/view) and place its HTL templates within that folder (e.g. add.html, html.html)
On each resource that should be rendered with the master template, set sling:resourceSuperType to page
When a request comes in to, for example, /content/example_type_instance.add.html, Sling resolution will therefore try to find a script in /apps/example_type/add.html; there isn't one, so it falls back to the resourceSuperType script in apps/page/html.html, which in turn will use the script in /apps/example_type/view/add.html.
This seems to work for the moment. #Vlad's approach with a Sling ResourceDecorator may be more elegant.

asp.net mvc display image external to the mvc deployment

I want to deploy my ASP.NET MVC site to some location C:\home\MySite\, and I want to give it a config value to point to a different location on that server: C:\home\SomeOtherLocation\Albums, and display images from that location on my page.
My controller returns a list of AlbumLinks, which contain a property called ImagePath, which looks like "C:\home\SomeOtherLocation\Albums\Album1\Image1.jpg". My view looks like this:
#model IEnumerable<AlbumLink>
#{
ViewBag.Title = "Albums";
}
#foreach (AlbumLink l in Model)
{
<p><img src="#l.ImagePath" /></p>
}
But the image is not displayed. I verified that the image is in the right location. Is this the proper way to display an external image on a View? I know that I can add the album into the solution along with all its images, but I don't want to do that. I want to deploy the site and configure it to point to a collection of images to display. I know it's doable. What's the best way to achieve this? Thanks.
2 problems here:
Firstly, you can't use ImagePath, as the path is local to the server, not the client. You need to provide the full URL
Second, IIS cannot see directories out of your directory structure. You can add a directory within IIS that redirects to the location like
Root
MySite -> c:\home\MySite
SomeOtherLocation -> c:\home\SomeOtherLocation
MVC will not find a matching controller and so will fall back to IIS to find the content.
You cannot have links to files like C:\something it is because browser cannot access such path. All images must be hosted by your webserver.
You should use something like Server.MapPath.

Grouping umbraco pages in folders without affecting URL

One of our Umbraco sites is getting a bit messy and I was wondering if there was a way of grouping pages in folders without affecting the URL. So for example if under the homepage I have some top level sections, some footer links and various other system pages. I'd like to group the footer pages in a footer folder, the system pages in a system folder but I don't want all the URLs to become /footer/page1, system/contact etc.
Is there a nice way of doing this, maybe something with umbracoUrlName?
There are two answers, first you could turn on the 'hide root folder' option in web.config - then you can have as many folders in the root as you like - without them forming part of the url.
umbracoHideTopLevelNodeFromPath Causes the top level content items to
be excluded from any url paths. For example, this is pre-set to True,
so:
[Content]Home = /home.aspx or /home/
[Content]Home\Projects = /projects.aspx or /projects/
[Content]Footer\Page1 = /page1.aspx or /page1/
[Content]Home\Projects\About = /projects/about.aspx or /projects/about/
http://our.umbraco.org/wiki/reference/webconfig
Secondly there are four 'hidden' redirect fields on every umbraco node (which you can add into the document type) which can change the url routing:
umbracoRedirect (content picker) - Umbraco will redirect to the picked page
umbracoInternalRedirectId (content picker) - Umbraco will load the picked page without changing the url
umbracoUrlName (textstring) - Umbraco will override the page’s default url
umbracoUrlAlias (textstring) - You can have several urls for the same page (not sure when this is useful)
So I guess in your scenario umbracoUrlName will pick out a page in your combined folder but with a url that you choose.
So you have
homepage
|- footer
|-page1 (umbracoUrl = "/footer-page1/")
and /footer-page1/ would render your page stored in the footer folder.
You could also hack things about and make umbracoRedirect & umbracoInternalRedirectId work but I'm not sure that it would help.

Using MVC Routes as Shortcodes

We have been trying to implement shortcodes on an ASP.NET MVC web app that allow users to uniquely invoke a given article/page using an assigned short code.
For e.g.: www.mysite.com/power would map to an actual URL: www.mysite.com/Power/Home/.
I have created various routes throughout the site that map these shortcodes to various actions and controllers within the application. From a shortcode/route point of view, everything is working great.
I, however, noticed a couple of interesting things. I have hyperlinks that I use Url.Action method to generate the URL pointing pages. Many of these pages also have short codes associated with them. For e.g.: I have a link that says:
Go to Power page
This is a page that also has the previously mentioned short-code assigned to it. When I use Url.Action, I ideally expect it to create a link as /Power/Home/Index or /Power/Home, but since I also have a route constraint mapped to it, it now generates the link as /power.
Is there a way I can just use the actual link URL when generating links? I only want short-codes when I am sending out emails etc. I want the site to generate actual URLs.
This may or may not be possible, but I wanted to see if there were any ideas out there that I could use.
Anup
Index and Home are likely defined in your route table as defaults for the Action and Controller element. When you generate the Url it wont include the defaults if they aren't needed.
You could write your own Action overload or helper, which would allow you to take more direct control of the generated URL or action link. You could approach it from two different ways: 1) a helper to generate short-code specific urls and links, and/or 2) a helper to generate the full url and/or link. If Url.Action is returning the short-code version due to your routing configuration, I'd think a good place to start would be the second option, creating a helper/extension method that will generate the full url for you.
Here's how I solved this:
Instead of naming a route with short code to point to the action url, I made the route point to a different Controller action which would then redirect to the actual route that I want it to.
For e.g.: Originally I had the code "power" defined in the route table such that it would point to www.mysite.com/Power/Home.
Now instead of pointing it to that action - Index, controller - Home, area - Power, I make it resolve to: action - Power, Controller - Home, Area - ShortCode.
In the controller now, I simply do a RedirectToAction("Index", "Home", new { Area = "Power" });
This ensures that the actual links to /Power/Home do not resolve to the shortcode "power".
This is a simple fix increased the work by a little bit, but works like a charm.

Rails include page

How would I include a page from the public folder in one of my views? I want to include a single header like I do in PHP so when I make a change it affects all the other pages. (It is for multiple views)
For the most part, the only web pages in the public folder will be purely static (custom 404 pages, FAQ, etc). If you have a piece of static HTML that you'd like to be displayed in a lot of pages, a partial is what you're looking for.
A partial doesn't have to be tied to a controller. You can create the sub-directory:
/views/static
and fill it with a whole bunch of partials, so you would have:
/views/static/_my_first_partial.html.erb
/views/static/_my_second_partial.html.erb
and anywhere you want those fragments, you can do:
render :partial => "static/my_first_partial"
and voila, you're done!
I'm pretty new to rails, but I guess for such task you would use Layouts:
Layouts and Rendering

Resources