Portal Engine Questions on portal engine and web parts.
Version 6.x > Portal Engine > Redirect/Transfer Parent Page Requests View modes: 
User avatar
Member
Member
robert-tailor.co - 9/6/2012 9:17:57 PM
   
Redirect/Transfer Parent Page Requests
Hi,

I have a document (a menu item) with multiple children. The parent document represents a group, while the child documents represent group items.

I want to link to the first child document in the group, but I do not want the link to point directly to the specific group item. I want the link to just point to the parent document URL, and display the specified group item instead.

I have tried using the 'Properties' -> 'Menu -> 'URL Redirection' to redirect the request to the specified page, but the redirect causes the URL in the browser to change to the child document's URL.

I'd really like to use a Server.Transfer instead of the Response.Redirect used in the 'URL Redirection' option.

Is this possible? If so, how?

Thanks!

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 9/7/2012 1:55:09 AM
   
RE:Redirect/Transfer Parent Page Requests
Hi,

Have you tried using just the Visual inheritance? I would do a similar approach like with the master page. On the parent node I would use the page placeholder web part and load given child node content to it.

Best regards,
Juraj Ondrus

User avatar
Member
Member
robert-tailor.co - 9/10/2012 5:28:34 AM
   
RE:Redirect/Transfer Parent Page Requests
kentico_jurajo wrote: Hi,

Have you tried using just the Visual inheritance? I would do a similar approach like with the master page. On the parent node I would use the page placeholder web part and load given child node content to it.

Best regards,
Juraj Ondrus

Hi Juraj,

That won't work for me. The pages stored under the parent document all have different document types, and many use different templates.

I do not think those will work with Visual Inheritance. It seems Visual Inheritance is only designed to work with documents that all share the parent's template.

Unless I have misunderstood? If so, I'd be grateful to hear how to use Visual Inheritance with different document types and page templates.

Thanks.

User avatar
Member
Member
robert-tailor.co - 9/10/2012 5:42:30 AM
   
RE:Redirect/Transfer Parent Page Requests
Also, when I *do* try to enable Visual Inheritance, I am unable to see the hierarchy levels options mentioned in the Visual Inheritance page.

I have created a page template which contains a CMSPlaceHolder:

<cms:CMSPagePlaceholder ID="plcZone1" runat="server">
</cms:CMSPagePlaceholder>


When I apply this template to the parent page, I click to 'Edit template properties' but the hierarchy tree is not visible.

unfortunately, the document you link to doesn't provide any explanation of how visual inheritance works, nor what is needed from a development perspective in order to enable it to work. It simply says what buttons to push to modify the News page, which is unhelpful from a development perspective.

I thought I would look at the example template for the 'News' index used on the Visual Inheritance page. I figured I might be able to get a better understanding of how it works if I saw the template source code. But no - there is no reference to an actual file/ASPX page that the template is created from.

I thought all page templates had to be created from a TemplatePage file, but obviously that is not the case, since none of the built in templates have actual source templates I can refer to.

Can you shed any light on this?
What do I actually need to include in my Page Template source file if I wanted to enable Visual Inheritance?

Thanks.

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 9/10/2012 6:55:51 AM
   
RE:Redirect/Transfer Parent Page Requests
Hi,

Are you using Portal engine or ASPX templates?
If you will take a look e.g. on the sample Coporate site - using the portal engine, you will see that it works with different document types and page templates as well - there are news, articles, page menu item document types and they are also using many different page templates.

The idea is to have the page place holder on the parent document - then the documents which will be under neath this one will be loaded inside this placeholder and the parent template is like an envelope - just like the master page concept.

This blog post is about using multiple placholders but it may clarify how it works.

You posted this into the the Portal engine forums but I guess you are using ASPX page templates - the Visual inheritance works in a similar way here - there is just standard place holder control and you specify what should be displayed inside it - in the ASPX sample templates the PortalManager control is used.
However, when using ASPX templates you can use the code behind and do the logic in the code directly - get the parent node information and do what you need - build the link to the item you want.

Best regards,
Juraj Ondrus

User avatar
Member
Member
robert-tailor.co - 9/10/2012 7:27:31 AM
   
RE:Redirect/Transfer Parent Page Requests
kentico_jurajo wrote: Hi,

Are you using Portal engine or ASPX templates?

Sorry. Yes I'm using the APSX templates method.

kentico_jurajo wrote:
You posted this into the the Portal engine forums but I guess you are using ASPX page templates - the Visual inheritance works in a similar way here - there is just standard place holder control and you specify what should be displayed inside it - in the ASPX sample templates the PortalManager control is used.
However, when using ASPX templates you can use the code behind and do the logic in the code directly - get the parent node information and do what you need - build the link to the item you want.


I think I might be misunderstanding what you mean here. Why would the *child* document need to get the *parent* node information? Since I want a parent page to display the contents of a child document, wouldn't I want to programmatically get the information I need from one of the Child nodes?

Also, I suppose this means I would need to either create an identical copy of the page template but with different logic in the code-behind to get the child document information. Or use the same template but with logic in the code-behind to find the value of a custom field that indicates this document is a 'parent', and to therefore show the child document information. Is that correct?

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 9/11/2012 1:36:31 AM
   
RE:Redirect/Transfer Parent Page Requests
Hi,

I am sorry for the confusion - I miced it up however it also applies vice versa.

I do not see any reason to create extra page template. In the code behind you can do an easy check using IF statement to determine where you are, whether you are on the document you want to be and if so, get the child node information you want. Maybe I am missing some important detail here, but I do not see this to be so complicated to achieve. Or, you can use something like sub-master page for given section of your site.

Best regards,
Juraj Ondrus

User avatar
Member
Member
robert-tailor.co - 9/11/2012 3:30:35 PM
   
RE:Redirect/Transfer Parent Page Requests
kentico_jurajo wrote: I do not see any reason to create extra page template. In the code behind you can do an easy check using IF statement to determine where you are, whether you are on the document you want to be and if so, get the child node information you want.

Yes - that's one way to do it, but I was hoping to avoid having to put all the logic in the code-behind.

kentico_jurajo wrote: Maybe I am missing some important detail here, but I do not see this to be so complicated to achieve. Or, you can use something like sub-master page for given section of your site.

There are 2 important details that make this tricky to achieve:

1. I want the target child page to be an editable option through the CMSDesk, so that if a child page is deleted, it is easy to choose another page without having to edit the code-behind.
2. There are some values that are reliant on the relative path, and expect the document to be at a certain level in the CMS Tree. If the parent page displays child data, I have to add extra logic to account for that in the path expressions.

I can create all the logic in the code-behind, but it feels unnecessary. Both these issue could be most easily solved by having an option in the CMSDesk -> Page -> Properties -> Menu -> URL Redirection that allows me to choose between a 'Redirect' (URL changes to new path) and a 'Server Transfer' (URL remains unchanged).

What do you think? Would this be simple to implement in a future release?

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 9/12/2012 2:07:31 AM
   
RE:Redirect/Transfer Parent Page Requests
Hi,

I am still not getting why the master page concept won't apply for you. You can create a sub section of the site using another master page template for given document and this master page will be the envelope for the child document's page template. Just like now you are using master page template and the sub page's template is displayed inside it, you can use the same idea on lower levels.

At this moment these are the only two ways I see you can do it - adding the logic to the code behind or using the master page concept.

Best regards,
Juraj Ondrus

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 9/12/2012 5:34:20 AM
   
RE:Redirect/Transfer Parent Page Requests
After some research, I think that the best way would be to load the content of the child document dynamically in the code behind or, use the same page template for the parent and given child document.

Best regards,
Juraj Ondrus

User avatar
Certified Developer 8
Certified Developer 8
Jiveabillion - 9/12/2012 8:30:58 AM
   
RE:Redirect/Transfer Parent Page Requests
I haven't tried this, so it's just a theory and probably won't work. I was thinking that you could maybe set the DocumentUrlPath of the parent item to something other than it's nodealiaspath and then set the DocumentUrlPath of the first child item to the NodeAliasPath of the parent item. At this moment, I am not sure if the DocumentUrlPath trumps the NodeAliasPath in the procedure used to map request urls to their appropriate document. It's worth a shot though.

User avatar
Certified Developer 8
Certified Developer 8
Jiveabillion - 9/12/2012 10:24:37 AM
   
RE:Redirect/Transfer Parent Page Requests
I think I've got a perfect plan for you. This will be easiest if you create a custom macro method (you know how to make those right?).

First do one of these things

A: Use a special document type to use for the documents where you want them to redirect to the first child. (Drawback: If you change your mind later, it's not easy to change the document type of a document, especially if it has child documents)

B: Add a boolean field to the Page (CMS.MenuItem) document type (or whatever document type you want) named something like "ShowFirstChildContent"

Once you have done that, you can create your custom macro method that does this


public static string GetFirstChildIfShowFirstChild()
{
//no need to check the ClassName of the current document,
// ValidationHelper will return default if columnname does not exist.
if(ValidationHelper.GetBoolean(CMSContext.CurrentDocument["ShowFirstChildContent"],false))
{
// I don't have a kentico solution on this computer,
//so I can't see the exact code to do this, experiment until you get it right


var currentNode = CMSContext.CurrentDocument;
currentNode.Children.OrderBy = "NodeOrder";

//Not sure if this works
currentNode.Children.SelectTopN = 1;

//you can try this either way, I'm not sure which will make it get the data from the database

var firstChild = currentNode.Children[0];
var firstChild = currentNode.Children.FirstOrDefault();
if(firstChild != null)
{
return firstChild.NodeAliasPath;
}
//OR
foreach( var child in currentNode.Children)
{
return child["NodeAliasPath"];
}
//Basically do whatever you need to do to return the first child's NodeAliasPath;


//No Child
return string.empty;
}
return string.empty;
}


After you have that in your solution, go to the design tab of the root (or document with your masterpage) and edit the PagePlaceHolder webpart.

In the PagePlaceHolder webpart, put this macro in the "Document to display" field:
"{%GetFirstChildIfShowFirstChild()%}"

I am assuming here that the Document to display field stores the NodeAliasPath, but I am not sure it does. If not, change your custom macro method to return whatever property of the document it stores.

Now, if the document you are viewing has the "ShowFirstChildContent" property and it is "true" and there is a child document, then the content from that document will be displayed as if it WERE the page you were on.

This, however, does not make the page output all of the properties of the document to display. If you want things like the Page Title, Page Meta info, etc. to be that of the first document, you will need to use macros in those fields (which are, unfortunately, inherited by child documents)


User avatar
Member
Member
robert-tailor.co - 9/13/2012 5:03:48 PM
   
RE:Redirect/Transfer Parent Page Requests
Hi Jiveabillion and Juraj,

Thanks for your suggestions. Jiveabillion's suggestion comes close to what I'm thinking is required to get this to work.

I guess the overall problem here is that the way Kentico is designed, it's assumed that all child documents under a parent document will all share the same template. But that is not always the case.

Consider:

An 'About' parent page. It has 3 child pages:

'About Us' (mostly text)
'Case Studies' (slideshow and other images)
'Contact Us' (feedback form)

The 'About' parent page doesn't contain any content - it should just display the content of 'About Us'.

That's not a problem if 'About Us' uses the same template, but all the other child pages use different page templates. If a content editor decides they want to instead show 'Case Studies' by default when someone clicks on 'About', then they can't. They can only do this using the URL Redirect option I am using at the moment.

But this changes the URL, and is not good for SEO, and can be confusing for the user.

It would be good if, in a later version of Kentico, there could be an option to perform a URL rewrite and allow the content editor to select which other page in the CMS Tree they wish to show instead.

Does anyone else think this would be a useful option?

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 9/14/2012 2:10:17 AM
   
RE:Redirect/Transfer Parent Page Requests
Hi,

This is already possible to do - easily using portal engine and page placeholder web parts - you can specify what content should be displayed within the place holder - the very the same idea as the master page - it is an envelope and inside it is the place holder which is displaying e.g. the home page - which is different page template.

The same applies for ASPX templates - on the parent template you will place the page placeholder - the same idea as the master page is built. You have page template on the parent with the placeholder which will display inside itself content of another document even with different page template.

Best regards,
Juraj Ondrus

User avatar
Member
Member
robert-tailor.co - 9/16/2012 11:04:57 PM
   
RE:Redirect/Transfer Parent Page Requests
kentico_jurajo wrote: The same applies for ASPX templates - on the parent template you will place the page placeholder - the same idea as the master page is built. You have page template on the parent with the placeholder which will display inside itself content of another document even with different page template.

Best regards,
Juraj Ondrus


Which method/function of CMSPagePlaceholder should I use to display the contents of a page beneath it in the CMS Tree hierarchy?

Can you give me an API example showing the steps required to go from retrieving a Node in the CMS Tree, to displaying the Node contents in the CMSPagePlaceholder in the Code-Behind?

Sorry if this sound elementary, but I really can't see anything obvious in the list of available methods for the CMSPageHolder class.

Thanks!

User avatar
Kentico Support
Kentico Support
kentico_jurajo - 9/17/2012 12:42:36 AM
   
RE:Redirect/Transfer Parent Page Requests
Hi,

I am still not getting why you can't use the master page concept like it is now. You have a root document (parent) which is an envelope for the documents under it - even with different page templates. There is no need for additional code.

But if you want to do it via the API, you can use the SelectSingleNode method to get the data about given node and then use e.g. a repeater or, maybe even better use a repeater with custom query where using the SQL query you will get the data you want and display them on given document.
Then, when you would like to change the displayed document you will just change the path in the repeater.

Best regards,
Juraj Ondrus

User avatar
Member
Member
robert-tailor.co - 9/17/2012 4:47:42 PM
   
RE:Redirect/Transfer Parent Page Requests
kentico_jurajo wrote: Hi,

I am still not getting why you can't use the master page concept like it is now.


I think you are misunderstanding my request. Child pages will inherit master page and parent page templates. That's fine. I understand that.

I don't understand how you can set a parent page to display the contents of a specific child page when the requested URL is that of the parent page only.

kentico_jurajo wrote: But if you want to do it via the API, you can use the SelectSingleNode method to get the data about given node and then use e.g. a repeater or, maybe even better use a repeater with custom query where using the SQL query you will get the data you want and display them on given document.
Then, when you would like to change the displayed document you will just change the path in the repeater.


OK, 2 points here:

1. I already know how to select the data contents of a specified node. I just don't know how to set a CMSPagePlaceHolder control to display the contents of the specified Node Document via the CodeBehind. Can you provide an example?
2. Why would I use a repeater to display the document contents? I only want to display the contents of a single document. What is the equivalent CMS control to display the contents of a single document? Again, can you provide an example?

Thanks.

User avatar
Certified Developer 8
Certified Developer 8
Jiveabillion - 9/17/2012 12:20:18 PM
   
RE:Redirect/Transfer Parent Page Requests
You can use the method that I mentioned. The bulk of what I wrote about is just the logic to check and see if the current page needs to show the first child node's content or not, and return the nodealias of that child node if so.

You can use any other method of getting that nodealias that you can think of, but that is ultimately what you need to pass your CMSPagePlaceholder.

You can use something like this to get the first child of the current document, you will still need to add a property to the document type so you can specify that a document should show it's first child's content:


public TreeNode GetFirstChildIfShowFirstChild()
{
if (ValidationHelper.GetBoolean(CMSContext.CurrentDocument["IsShowFirstChildContent"], false))
{
var currentNode = CMSContext.CurrentDocument;
var firstChild = currentNode.TreeProvider.SelectSingleNode(CMSContext.CurrentSiteName, string.Empty, string.Empty, true, String.Empty, String.Format("NodeParentID = {0}", currentNode.NodeID), "NodeOrder", 1, true);
if (firstChild != null)
{
return firstChild.NodeAliasPath;
}
}
}

User avatar
Member
Member
robert-tailor.co - 9/17/2012 4:41:04 PM
   
RE:Redirect/Transfer Parent Page Requests
Hi Jiveabillion,

Thanks for the sample code.

But what I'm really after is an example showing how to assign the NodeAliasPath returned form your sample code to the specified CMSPagePlaceholder control, so that hte CMSPagePlaceholder control will display the contents of the specified NodeAliasPath.

As far as I can tell, none of the fields in the CMSPagePlaceholder control take a NodeAliasPath as a parameter.

Thanks.

User avatar
Member
Member
robert-tailor.co - 9/17/2012 4:41:59 PM
   
RE:Redirect/Transfer Parent Page Requests
By the way, I should mention that I'm using the ASPX template engine, not the Portal engine.

User avatar
Certified Developer 8
Certified Developer 8
Jiveabillion - 9/17/2012 4:57:52 PM
   
RE:Redirect/Transfer Parent Page Requests
It's the "Path" property of the PagePlaceHolder control that you must set.

You can also set the PageTemplate property so that it will use the same page template as the first child item. You will have to use the DocumentPageTemplateID property of the child node to return the CodeName of the PageTemplate. You can use PageTemplateInfoProvider.GetPageTemplateInfo(firstChild.DocumentPageTemplateID).CodeName to do that.

User avatar
Member
Member
robert-tailor.co - 9/17/2012 5:00:08 PM
   
RE:Redirect/Transfer Parent Page Requests
Jiveabillion wrote: It's the "Path" property of the PagePlaceHolder control that you must set.


Are we talking about the same control here?

I am looking all the properties for CMSPagePlaceholder and it has no 'Path' property.

User avatar
Certified Developer 8
Certified Developer 8
Jiveabillion - 9/17/2012 5:12:24 PM
   
RE:Redirect/Transfer Parent Page Requests
Sorry, that's the property of the webpart control. I've never needed to use ASCX templates before, but can't you still use the webpart controls?

Either way, look at the code inside /CMSWebParts/Genera/pageplaceholder.ascx.cs to see how it takes the Path property and applies it to the CMSPagePlaceholder control.

User avatar
Member
Member
robert-tailor.co - 9/17/2012 10:26:41 PM
   
RE:Redirect/Transfer Parent Page Requests
Jiveabillion wrote: Sorry, that's the property of the webpart control. I've never needed to use ASCX templates before, but can't you still use the webpart controls?

Either way, look at the code inside /CMSWebParts/Genera/pageplaceholder.ascx.cs to see how it takes the Path property and applies it to the CMSPagePlaceholder control.

Well, using the WebPart out of the box doesn't work. Attempting to do so results in the following error:

System.Exception: [CMSAbstractWebPart.PagePlaceholder]: Parent CMSPagePlaceholder not found.


So I tried enclosing it within a CMSPagePlaceholder control:

<cms:CMSPagePlaceholder ID="plcZone1" runat="server">
<LayoutTemplate>
<uc1:pageplaceholder ID="pageplaceholderRange" runat="server" />
</LayoutTemplate>
</cms:CMSPagePlaceholder>

Now the pageplaceholder cannot be found in the code-behind.

What now?

To re-iterate:

1. I'm using ASPX Templates, not Portal.
2. I want to show the contents of a child document in a parent.

Thanks.

User avatar
Certified Developer 8
Certified Developer 8
Jiveabillion - 9/18/2012 11:13:30 AM
   
RE:Redirect/Transfer Parent Page Requests
After you get the path of the child document (using the examples I gave you or your own code), you can use this code that I copied from the Web Part in /CMSWebParts/General/pageplaceholder.ascx). It will get the document and the template to use for setting the properties on your CMSPagePlaceholder control.

In this code, the "partPlaceholder" is the CMSPagePlaceHolder and it is from the context of a CMSAbstractWebPart, so there are some things that you will need to change if they are not available in the context you are using. Also, this code is from V7, which is only slightly different (I am at Kentico Connection, and I don't currently have access to V6 code). I hope this at least points you in the right direction.


ViewModeEnum viewMode = ViewModeEnum.Unknown;

// Process template only if the control is on the last hierarchy page
PageInfo currentPage = PagePlaceholder.PageInfo;
PageInfo usePage = null;
PageTemplateInfo ti = null;

if (String.IsNullOrEmpty(path))
{
// Use the same page
usePage = PagePlaceholder.PageInfo;

if (UseDefaultTemplateOnSubPages || (currentPage.ChildPageInfo == null) || (currentPage.ChildPageInfo.UsedPageTemplateInfo == null) || (currentPage.ChildPageInfo.UsedPageTemplateInfo.PageTemplateId == 0))
{
ti = PageTemplateInfoProvider.GetPageTemplateInfo(templateName);
}
}
else
{
// Resolve the path first
path = CMSContext.ResolveCurrentPath(path);

// Get specific page
usePage = PageInfoProvider.GetPageInfo(CMSContext.CurrentSiteName, path, CMSContext.PreferredCultureCode, null, false);
if (PortalManager.ViewMode != ViewModeEnum.LiveSite)
{
viewMode = ViewModeEnum.Preview;

// Set design mode for document's placeholder if is currently displayed
TreeNode tn = CMSContext.CurrentDocument;
if ((tn != null) && (CMSContext.ViewMode == ViewModeEnum.Design) && tn.NodeAliasPath.EqualsCSafe(path, true))
{
viewMode = ViewModeEnum.Design;
}

// Get current document content
if (usePage != null)
{
TreeNode node = DocumentHelper.GetDocument(usePage.DocumentID, null);
if (node != null)
{
usePage.LoadVersion(node);
}
}
}

// Get the appropriate page template
if (String.IsNullOrEmpty(templateName))
{
ti = usePage.UsedPageTemplateInfo;
}
else
{
ti = PageTemplateInfoProvider.GetPageTemplateInfo(templateName);
}
}

if ((usePage != null) && (ti != null))
{
// If same template as current page, avoid cycling
if (ti.PageTemplateId == currentPage.UsedPageTemplateInfo.PageTemplateId)
{
lblError.Text = GetString("WebPart.PagePlaceHolder.CurrentTemplateNotAllowed");
lblError.Visible = true;
}
else
{
usePage = usePage.Clone();

// Setup the page template
int templateId = ti.PageTemplateId;

usePage.SetPageTemplateId(templateId);
usePage.UsedPageTemplateInfo = ti;

// Load the current page info with the template and document
if (viewMode != ViewModeEnum.Unknown)
{
partPlaceholder.ViewMode = viewMode;
}

partPlaceholder.UsingDefaultPageTemplate = !string.IsNullOrEmpty(templateName);
partPlaceholder.UsingDefaultDocument = !string.IsNullOrEmpty(path);
partPlaceholder.PageLevel = PagePlaceholder.PageLevel;
partPlaceholder.LoadContent(usePage, true);
}
}