Working with Channel Objects

Thus far we have seen the properties and methods of a Channel that use intrinsic data types. This section will explore CMS-specific objects and collections of objects that are available from a Channel. These are the principal objects graphically modeled in Figure 23-2, PAPI object model Channel.

NOTE: The PAPI object model is covered in detail in Chapter 23. The objects covered in this section will be covered in the same order as they are illustrated in Figure 23-2.


These objects require some special processing and consideration. As before, there are some common facts and concepts that will help us in this section.

After a Channel object has been deleted but before it is committed, all properties become read-only. However, even after a deleted Channel object is committed, it may still reside in an in-memory collection. All Channel child objects must be removed before a Channel object can be deleted. Even if they still reside in memory, Channel child objects cannot be read once the Channel object has been deleted and committed.

Historical revisions of a channel don't typically keep the value that was associated with the revision when it was the current version. Properties typically represent the value of the current revision regardless of the value when the historical revision was the current revision. Attempting to assign a value to these properties for a historical revision will result in an exception. This concept is extended to the child objects for historical revisions of a channel, including the collections (Channels, Postings, AllChildren, and CustomProperties) whose contents are based upon the revision date and time of the channel. Channel objects and Posting objects are only included in these collections if they have a corresponding revision date and are currently contained in the referencing Channel object. Otherwise, they are left out.

Parent (Inherited from ChannelItem)

The Parent property of a Channel object or Posting object returns the Channel object that contains it. The specific Channel object returned depends on the current PublishingMode, the user rights, and potentially the StartDate and ExpiryDate. If the referencing object is contained within the built-in RootChannel, then the RootChannel is returned. Since the RootChannel has no containing Channel, its Parent returns a null, so it is wise to check the IsRoot property (discussed earlier in this chapter) before accessing the Parent property.

Replace the Button1_Click function of our Scratchpad template file with the following code:

 private void Button1_Click(object sender, System.EventArgs e) {   //1. Put current Channel into variable   Channel cmsChannel = CmsHttpContext.Current.Channel;   //2. Make sure that the current Channel isn't the root   if (!cmsChannel.IsRoot)   {     //3. Populate the label with the current Channel and its parent     Label1.Text =       "<br><b>Current: </b>" + cmsChannel.Name.ToString() +       "<br><b>Parent:  </b>" + cmsChannel.Parent.Name.ToString();   }   else   {     //4. Provide nonerror feedback to the developer     Label1.Text = "Current Channel is the RootChannel";   } } 

Build the solution and then refresh the Scratchpad posting in Internet Explorer, or browse to it and click the Button. The page should reload and look similar to Figure 25-9.

Figure 25-9. Show Channel Parent

graphics/25fig09.gif

This member can be useful, even essential, in the construction of dynamic navigation, including the infamous breadcrumbs.

NOTE: Although briefly mentioned later in this chapter, dynamic navigation and breadcrumbs are covered in depth in Chapter 14.


Channels

The Channels collection property of Channel objects depends on the current PublishingMode, the user rights, potentially the IsHiddenMode Published property, StartDate, and ExpiryDate of each Channel in the collection (all three properties are discussed earlier in the Read/Write Members section of this chapter), and potentially the AutoFilterHidden property of the Context.

The Channel objects in the collection will be ordered, by default, first by their SortOrdinal value (discussed earlier near the end of the Read/Write Members section of this chapter) and within that, alphabetically by Name. However, this sort order can be overridden. The ChannelCollection contains a large number of built-in sorts, which can be applied to the list. The ChannelCollection sort members are as follows:

  • SortByChangeDate (inherited from ChannelItemCollection)

  • SortByDisplayName (inherited from ChannelItemCollection)

  • SortByDisplayPath (inherited from ChannelItemCollection)

  • SortByExpiryDate (inherited from ChannelItemCollection)

  • SortByImportance (inherited from ChannelItemCollection)

  • SortByLastModifiedDate (inherited from HierarchyItemCollection)

  • SortByName (inherited from HierarchyItemCollection)

  • SortByOrdinal (inherited from ChannelItemCollection)

  • SortByOwner (inherited from HierarchyItemCollection)

  • SortByPath (inherited from HierarchyItemCollection)

  • SortByRevisionDate (inherited from HierarchyItemCollection)

  • SortByStartDate (inherited from ChannelItemCollection)

Each sort method can be applied successively to the Channels collection to create a multikey sort. This can be beneficial if duplicate values are expected in the collection and we want to iterate a consistent sequence of values (as is often the case in dynamically generating navigation for a site). For example, sorting the collection using SortByDisplay Name followed by SortByOwner would yield a list of Channels grouped by Channel Owner in Channel DisplayName sequence. To start the sort sequence over again, we would need to get another instance of the Channels property.

Be cautious about overusing this functionality because sorting is always a CPU-intensive activity, and repeatedly sorting a large list or a large number of small lists could become a resource drain. If most pages in your site require a specific sequence, consider manually ordering items using their SortOrdinal so that they will be sorted correctly when the collection is initially accessed. Remember, by default, new Channels added to the list will have a SortOrdinal of zero (0) and therefore sort to the bottom of the list.

This collection is not self-updating. If new Channel objects are added to the Web Property or existing Channel objects are deleted, the collection in memory will not be updated. It is good programming practice to get the property and use it swiftly. In busy sites, if some time has passed since the property was first acquired, it would typically be better to get the property again rather than use the one previously in memory.

The Channels collection has a Count property that can be used to determine whether the list contains any items. The items in the collection can be iterated using the common foreach statement or directly using the string Name for the item or its zero-based ordinal index.

There is also a Union method for the Channels collection. It can be combined with another collection to create a superset of all the objects in both collections.

Some of these concepts are demonstrated in the following code example. It uses the Scratch channel hierarchy created in the Creating and Deleting Objects in a Channel section earlier in this chapter.

Replace the Button1_Click function of our Scratchpad template file with the following code:

 private void Button1_Click(object sender, System.EventArgs e) {   try   {     //1. Grab the current CMS Context     CmsHttpContext cmsContext = CmsHttpContext.Current;     //2. Grab the Brady Channel     Channel cmsBradyChannel =       cmsContext.Searches.GetByPath("/Channels/Scratch/Brady")       as Channel;     //3. Populate the label with informational text     Label1.Text = "Working with " +       cmsBradyChannel.DisplayName.ToString() +       " Channel's Channels collection";     //4. Change sort from Name within SortOrdinal to DisplayName     cmsBradyChannel.Channels.SortByDisplayName();     //5. Apply secondary sort of Owner to the DisplayName sort     //   Duplicate values for Owner will retain the     //   DisplayName sequence     cmsBradyChannel.Channels.SortByOwner();     //6. Iterate the Channels in the Brady Channel     foreach (Channel cmsChannel in cmsBradyChannel.Channels)     {       //7. Add the DisplayName of each Channel into the ListBox       ListBox1.Items.Add("Using implicit reference: " +         cmsChannel.DisplayName.ToString()         );     }     //8. Check to be sure that there are items in the collection     if (cmsBradyChannel.Channels.Count > 0)     {       //9. Add the DisplayName of the first Channel into the       //   ListBox. This is a risky approach.       ListBox1.Items.Add("Using EXPLICIT reference: " +         cmsBradyChannel.Channels[0].DisplayName.ToString()         );       //10. Add the DisplayName of a the Mike Channel into the       //    ListBox. This is a very risky approach.       ListBox1.Items.Add("Using EXPLICIT reference: " +         cmsBradyChannel.Channels["Mike"].DisplayName.ToString()         );     }   }   catch(Exception eError)   {     //11. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

Build the solution and then refresh the Scratchpad posting in Internet Explorer, or browse to it and click the Button. The page should reload and look similar to Figure 25-10.

Figure 25-10. Working with a Channels collection

graphics/25fig10.gif

You'll have to scroll down to see the second explicit reference. If the explicit references to the item in the code under comments 9 and 10 do not find a Channel, an exception ("Object reference not set to an instance of an object") will occur. In general, we want to avoid using an explicit reference to an item in a collection anyway. Believe it or not, using one of the Searches (discussed in Chapter 28) like GetByGuid (ideally), GetByPath, or GetByUrl will likely actually outperform an explicit reference to an item. This is because explicit references require the entire collection to be inflated to access the single entry, whereas the search just hydrates the single instance.

This member collection can be useful, even essential, in the construction of dynamic navigation, including the infamous breadcrumbs.

Postings

The Postings collection property of a Posting object is similar to the Channels collection property. Its contents also depend on the current PublishingMode, the user's rights, potentially the IsHiddenMode Published property (discussed earlier in the Read/Write Members section of this chapter), StartDate, and ExpiryDate of the Postings in the collection, and potentially the AutoFilterHidden property of the Context.

The Posting objects in the collection will be ordered, by default, first by their SortOrdinal value (also discussed earlier near the end of the Read/Write Members section of this chapter) and within that, chronologically by LastModifiedDate.

The same sorting capabilities and cautions that apply to the Channels property apply to the Postings property. The tendency for the collection to get stale, the access methods, and the ability to form a union with other collections are the same too.

Since we have only one posting at this point, only a brief coding example will be shown. Postings are covered in depth in the next chapter.

Replace the Button1_Click function of our Scratchpad template file with the following code:

 private void Button1_Click(object sender, System.EventArgs e) {   try   {     //1. Put current Channel into variable     Channel cmsChannel = CmsHttpContext.Current.Channel;     //2. Populate the label with informational text     Label1.Text = "Working with " +       cmsChannel.DisplayName.ToString() +       " Channel's Postings collection";     //3. Change the sort to DisplayName     cmsChannel.Postings.SortByDisplayName();     //4. Iterate the Postings in the current Channel     foreach (Posting cmsPosting in cmsChannel.Postings)     {       //5. Add the DisplayName of each Posting into the ListBox       ListBox1.Items.Add(cmsPosting.DisplayName.ToString());     }   }   catch(Exception eError)   {     //6. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

As with the Channels collection property, explicit references to an item in the collection members are allowed, just not illustrated and not recommended.

Build the solution and then refresh the Scratchpad posting in Internet Explorer, or browse to it and click the Button. The page should reload and look similar to Figure 25-11.

Figure 25-11. Working with a Postings collection

graphics/25fig11.gif

This member collection can be useful, even essential, in the construction of dynamic navigation.

AllChildren

The AllChildren collection property of Channel and Posting objects (ChannelItem objects) is simply a union of the Channels collection property and the Postings collection property, both discussed just before this property in this section of this chapter. Its contents depend on the contents of those two collections for the given user in the given context.

The ChannelItem objects in the collection will be ordered, by default, first by their SortOrdinal value (discussed earlier near the end of the Read/Write Members section of this chapter) and within that, alphabetically by ChannelItem Name.

The same sorting capabilities and cautions that apply to the other two properties apply to the AllChildren property. The tendency for the collection to get stale, the access methods, and the ability to form a union with other collections are the same too.

Again, a brief coding example is shown to give a flavor of how this is similar to and how it is different from the other two collection properties.

Replace the Button1_Click function of our Scratchpad template file with the following code:

 private void Button1_Click(object sender, System.EventArgs e) {   try   {     //1. Put current Channel into variable     Channel cmsChannel = CmsHttpContext.Current.Channel;     //2. Populate the label with informational text     Label1.Text = "Working with " +       cmsChannel.DisplayName.ToString() +       " Channel's AllChildren collection";     //3. Change the sort to DisplayName     cmsChannel.AllChildren.SortByDisplayName();     //4. Iterate the Postings in the current Channel     foreach (ChannelItem cmsChannelItem in cmsChannel.AllChildren)     {       //5. Add the CMS type followed by the DisplayName for each       //   ChannelItem into the ListBox       ListBox1.Items.Add(         cmsChannelItem.GetType().ToString() + " " +         cmsChannelItem.DisplayName.ToString()         );     }   }   catch(Exception eError)   {     //6. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

The biggest difference is the casting of the children in the collection as the generic ChannelItem type in the code under comment 4. As with the other two collection properties, explicit references to an item in the collection members are allowed, just not illustrated and not recommended.

Build the solution and then refresh the Scratchpad posting in Internet Explorer, or browse to it and click the Button. The page should reload and look similar to Figure 25-12.

Figure 25-12. Working with an AllChildren collection

graphics/25fig12.gif

This member collection can be useful, even essential, in the construction of dynamic navigation, including the infamous breadcrumbs.

CustomProperties (Inherited from ChannelItem)

The CustomProperties collection of CustomProperty objects is predictably used as a catch-all for capturing Channel object characteristics that were not thought of by Microsoft but that we want to have for our Channel objects. These user-defined name/value pairs can be used for nearly anything that we can dream up. They include an optional domain list of allowed values (default values are only allowed on Posting objects). It's like having an intelligent, built-in dictionary object for each Channel object.

For instance, we could set up all channels to have a CustomProperty called IsBottomNavChannel with an allowed values list of true or false. As we iterate through the Channels collection to dynamically build our navigation, we could check the CustomProperty to see which channels we should include in the bottom navigation and which ones we should leave out.

However, CustomProperties for a channel must be created using Site Manager; the Web Author and PAPI can only be used to add allowed values and update the value of existing CustomProperty objects. This can be a big disadvantage. Some CMS pundits contend that creating a hidden posting in the channel with a collection of placeholders yields the same name/value pair (placeholder/content pair) concept. This is potentially a better solution since new placeholders can be created in code, and we have all the capabilities of a template and code-behind to exploit. Consistency across channels can also be maintained using a template, but this must be done manually by an administrator in Site Manager. For example, if we want to add a new CustomProperty to all of our channels, it must be manually added through Site Manager to each channel, one channel at a time. For a site with lots of channels, the task could be daunting and fraught with potential human error and inconsistency.

That said, CustomProperties are part of CMS and may require our attention. Table 25-3 lists the primary properties and their description for a CustomProperty object.

Table 25-3. CustomProperty Member Descriptions

Public CustomProperty Properties

Description

AllowedValues

Gets a collection of allowed values defined for a target CustomProperty object.

DefaultValue

Gets the default value of the target CustomProperty as a string, or as a null reference (Nothing, in Visual Basic) if the CustomProperty does not have a default value.

Name

Gets the name of this CustomProperty.

UsesDefaultValue

Indicates whether a CustomProperty is using the DefaultValue.

Value

Gets and sets a value for this CustomProperty object.

ResetToDefault

Resets the target instance of the CustomProperty class to derive its current value from its default value, if a default value exists.

Unlike the channel itself, each CustomProperty must have a unique Name within the CustomProperties collection for each channel. The Name is essentially the key and is used as the ascending, alphabetical sort order for the collection. Each CustomProperty must also have a value. Unlike postings (discussed in the next chapter), Channel CustomProperty objects do not have an associated template and therefore are not allowed to have default values (these are set up for postings in the template using VS.NET, and there isn't an equivalent capability in Site Manager for channels). So, the CustomProperty UsesDefaultValue property is always set to false, the DefaultValue property always returns null, and the ResetToDefault method has no effect.

To demonstrate this concept, assume that we want our channels to have the CustomProperty previously described, IsBottomNavChannel, with an allowed values list of true or false. Using the Scratch channel hierarchy created in the Creating and Deleting Objects in a Channel section earlier in this chapter, we use Site Manager (our only option) to create the CustomProperty for each channel in the hierarchy. Use the following steps to complete this setup task:

  1. Open Site Manager and authenticate as a CMS administrator.

  2. Expand each channel so that you can see the entire hierarchy.

  3. Start with the Scratch channel.

  4. Right-click the channel and choose Properties from the pop-up menu (Figure 25-13).

    Figure 25-13. Choose Properties from pop-up menu

    graphics/25fig13.jpg

  5. On the resulting Scratch Properties dialog, choose the Custom tab, on the far right.

  6. Click the New button, on the bottom left.

  7. On the resulting Add Custom Property dialog (Figure 25-14), enter the following values.

    Figure 25-14. Add Custom Property dialog

    graphics/25fig14.jpg

  8. Enter IsBottomNavChannel into the Property Name text box.

  9. Choose Selection from the Property Type drop-down (the section inside of the frame below will change from a single multirow text box for entering the Current Text Value to a set of controls that allow the creation of the allowed values list).

  10. Click the New button to add the first value to the list.

  11. On the resulting Add Value dialog, enter "true" into the Value text box and click the OK button.

  12. Click the New button again to add a second value of "false".

  13. While false is still highlighted, click the Set as Current button to assign the IsBottomNavChannel a value of "false" for the Scratch channel.

  14. This will enable the OK button; click the OK button to dismiss the Add Custom Property dialog.

  15. You will see the IsBottomNavChannel custom property we just added listed on the Custom tab of the Scratch Properties dialog (Figure 25-15).

    Figure 25-15. Scratch Properties dialog with custom property listed

    graphics/25fig15.gif

  16. Click OK to dismiss the Scratch Properties dialog.

From Site Manager select the Brady channel and repeat steps 4 through 16 in exactly the same way. One at a time, select each of the channels Alice, Carol, Cindy, Jan, Marsha, Mike, Bobby, Greg, and Peter and repeat steps 4 through 16 in exactly the same way except for Alice, Carol, and Mike. In step 13, when the Set as Current button is clicked, choose true rather than false. We want these three to be listed in our fictitious bottom navigation. Yes, it is tedious and potentially fraught with error.

When all of the channels have been given our new CustomProperty, you can exit Site Manager and open VS.NET to the Scratchpad template file. We are going to be traversing the channel hierarchy searching for channels with the IsBottomNavChannel custom property set to true (basically looking for Alice, Carol, and Mike from the work we just completed). The easiest way to traverse the hierarchy is recursively. So, just above the Button1_Click function that we have been replacing throughout this chapter, enter the following code:

 private void ShowChannelsWithCustomProperty(Channel cmsChannel,   string nameCustomPropertyToShow,   string valueCustomPropertyToShow) //***************************************************************** //Search all Channels from the cmsChannel passed to the function //for the nameCustomPropertyToShow CustomProperty Name //with the valueCustomPropertyToShow CustomProperty Value //If a child Channel has children, this function is called //recursively //***************************************************************** {   try   {     //1. Iterate the Channels collection     foreach (Channel cmsChildChannel in cmsChannel.Channels)     {       //2. Iterate the CustomProperties collection       foreach (CustomProperty cmsChannelProperty                  in cmsChildChannel.CustomProperties)       {         //3. Is it the CustomProperty we are looking for?         if (cmsChannelProperty.Name == nameCustomPropertyToShow)         {           //4. Does it have the correct value?           if (cmsChannelProperty.Value ==                 valueCustomPropertyToShow)           {             //5. Then show it in the ListBox             ListBox1.Items.Add(cmsChildChannel.Name.ToString());           }         }       }       //6. Check to see if a child Channel has children       if(cmsChildChannel.AllChildren.Count > 0)       {         //7. Call this function recursively to visit every Channel         ShowChannelsWithCustomProperty(cmsChildChannel,           nameCustomPropertyToShow, valueCustomPropertyToShow);       }     }   }   catch(Exception eError)   {     //8. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

As the comments indicate, this function will recursively traverse all the channels and child channels in a given root channel looking for a CustomProperty with a given Name set to a given Value. Now we just need to seed this function with the channel, CustomProperty name to search for, and the CustomProperty value to select.

Replace the Button1_Click function of our Scratchpad template file with the following code:

 private void Button1_Click(object sender, System.EventArgs e) {   try   {     //1. Grab the current CMS Context     CmsHttpContext cmsContext = CmsHttpContext.Current;     //2. Populate the label with the root Channel name     Label1.Text = cmsContext.Channel.Name.ToString() +       " Channel " +       "with IsBottomNavChannel CustomProperty set to true";     //3. Call function to show all Channels in the ListBox with     //   the IsBottomNavChannel CustomProperty set to true     //   CustomProperties can only hold strings so true is     //   in quotes     ShowChannelsWithCustomProperty(cmsContext.Channel,       "IsBottomNavChannel", "true");   }   catch(Exception eError)   {     //4. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

Build the solution and then refresh the Scratchpad posting in Internet Explorer, or browse to it and click the Button. The page should reload and look similar to Figure 25-16.

Figure 25-16. Channels with true IsBottomNavChannel

graphics/25fig16.gif

DefaultResourceGallery, DefaultTemplateGallery

The DefaultResourceGallery and DefaultTemplateGallery properties refer to the resources and templates that authors are encouraged to use when creating new postings in the referencing Channel object. If these properties are not set (no reference to a gallery exists) or the user doesn't have sufficient rights to the referenced gallery, CMS will return a null. Any use of gallery properties and methods will result in an exception if that object is null.

In Site Manager, these two properties can be found in the Default Galleries for Web Authoring section on the Web Authoring tab of the Channel Properties dialog for each channel. Although Site Manager facilitates the setting of these properties, they are not directly used by CMS for any purpose. They are, however, exposed for use within PAPI.

The following code example reuses the GetAuthenticatedCmsApplicationContext function from Listing 25-1. So we need to ensure the code from Listing 25-1 is entered above the Button1_Click function of our Scratchpad template file.

Replace the Button1_Click function of our Scratchpad template file with the following code:

 private void Button1_Click(object sender, System.EventArgs e) {   try   {     //1. Grab the current CMS Context     CmsHttpContext cmsContextHttp = CmsHttpContext.Current;     //2. If either gallery is not set, go into update mode     //   and set it     if (cmsContextHttp.Channel.DefaultResourceGallery == null |         cmsContextHttp.Channel.DefaultTemplateGallery == null)     {       //3. Grab an Authenticated Context in Update PublishingMode       //   using the GetAuthenticatedCmsApplicationContext function       //   from Listing 25 1       CmsApplicationContext cmsContextApp =         GetAuthenticatedCmsApplicationContext(           PublishingMode.Update);       //4. Position the Application Context to the current Channel       //   using its GUID (the most efficient Searches method)       //   Cast the result of the Searches object as a Channel       Channel cmsChannelApp =         cmsChannelApp.Searches.GetByGuid(           cmsContextHttp.Channel.Guid)         as Channel;       //5. If Current Channel DefaultResourceGallery is not set       if (cmsChannelApp.DefaultResourceGallery == null)       {         //6. Set it to the root         cmsCurrentApp.DefaultResourceGallery =           cmsContextHttp.RootResourceGallery;       }       //7. If Current Channel DefaultTemplateGallery is not set       if (cmsChannelApp.DefaultTemplateGallery == null)       {         //8. Set it to the root         cmsChannelApp.DefaultTemplateGallery =           cmsContextHttp.RootTemplateGallery;       }       //9. Commit all changes       cmsContextApp.CommitAll();       //10. Populate the label with the names of the default       //    galleries using the CmsApplicationContext Channel       Label1.Text = "From CmsApplicationContext" +         "<br><b>DefaultResourceGallery: </b>" +         cmsChannelApp.DefaultResourceGallery.Name.ToString() +         "<br><b>DefaultTemplateGallery: </b>" +         cmsChannelApp.DefaultTemplateGallery.Name.ToString();       //11. Dispose of the stand-alone Application Context       cmsContextApp.Dispose();     }     else     {       //12. Use Current Channel from Http Context       Channel cmsChannelHttp = cmsContextHttp.Channel as Channel;       //13. Populate the label with the names of the default       //    galleries using the CmsHttpContext Channel       Label1.Text = "From CmsHttpContext" +         "<br><b>DefaultResourceGallery: </b>" +         cmsChannelHttp.DefaultResourceGallery.Name.ToString() +         "<br><b>DefaultTemplateGallery: </b>" +         cmsChannelHttp.DefaultTemplateGallery.Name.ToString();     }   }   catch(Exception eError)   {     //14. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

Build the solution and then refresh the Scratchpad posting in Internet Explorer, or browse to it and click the Button. The page should reload and look similar to Figure 25-17.

Figure 25-17. Show channel default galleries

graphics/25fig17.gif

Of course, these properties can be set to any valid ResourceGallery object or TemplateGallery object, respectively, in CMS. Setting these to the root of the current channel is just a certainty for the sake of the example. Conversely, setting this property to null removes the reference to the default gallery.

This member can be useful to specify the default gallery as described. It could be valuable to use this value if you were creating a custom set of admin screens for the creation of a posting.

GetByRelativePath (Inherited from ChannelItem)

As previously described, the Channel object's Path property retrieves the fully qualified path using the Name property of the channels involved. The GetByRelativePath method provides a means to get a Channel object or Posting object relative to the current channel's Path. Of course, we can only retrieve objects that the user has appropriate rights to.

This concept and syntax is similar to the relative referencing used in HTML and DOS. The current object is represented with a period ("."), its parent is represented by two periods (".."), and each channel name is separated by a forward slash ("/"). Unlike the channel Path, the relative path string must not begin with a forward slash.

Using the hierarchy given at the beginning of this chapter, consider the following examples.

The Greg channel's path is /Channels/Scratch/Brady/Mike/Greg. With Greg as the current channel, we could use the GetByRelativePath method with the following relative path: "../../.." (Greg's parent's parent's parent). That would retrieve an object that we could cast as a Channel object, and we would have our Scratch channel.

Again, with Greg as the current channel, we could use the GetByRelativePath method with the following relative path: "../../Carol" (Greg's parent's parent's child channel Carol). That would retrieve an object that we could cast as a Channel object, and we would have the Carol channel.

Last, with the Carol channel as the current channel, we could use the GetByRelativePath method with the following relative path: "./Marsha" (Carol's child channel Marsha). That would retrieve an object that we could cast as a Channel, and we would have the Marsha channel.

Let's see these three examples in code.

Replace the Button1_Click function of our Scratchpad template file with the following code:

 private void Button1_Click(object sender, System.EventArgs e) {   try   {     //1. Grab the current CMS Context     CmsHttpContext cmsContext = CmsHttpContext.Current;     //2. Populate the label with static text     Label1.Text = "Get Channel Path using GetByRelativePath";     //3. Remove any previous entries from the ListBox     ListBox1.Items.Clear();     //4. Grab the Greg Channel from the Context     //   Cast the result of the Searches object as a Channel     Channel cmsGregChannel =       cmsContext.Searches.GetByPath(         "/Channels/Scratch/Brady/Mike/Greg")       as Channel;     //5. If our search for the Greg Channel was successful     if (cmsGregChannel != null)     {       //6. Add the Channel path to the ListBox       ListBox1.Items.Add         ("Greg Path: " + cmsGregChannel.Path.ToString());       //7. Grab the relative Scratch Channel using the Greg Channel       Channel cmsScratchChannel =         cmsGregChannel.GetByRelativePath("../../..")         as Channel;       //8. If our relative search for Scratch Channel       //   was successful       if (cmsScratchChannel != null)       {         //9. Add the Channel path to the ListBox         ListBox1.Items.Add           ("Scratch Path: " + cmsScratchChannel.Path.ToString());       }       else       {         //10. Provide nonerror feedback to the developer         ListBox1.Items.Add ("Scratch Channel not found");       }       //11. Grab the relative Carol Channel using the Greg Channel       Channel cmsCarolChannel =         cmsGregChannel.GetByRelativePath("../../Carol")         as Channel;       //12. If our relative search for Carol Channel       //    was successful       if (cmsCarolChannel != null)       {         //13. Add the Channel path to the ListBox         ListBox1.Items.Add           ("Carol Path: " + cmsCarolChannel.Path.ToString());         //14. Grab the relative Marsha Channel using the         //    Carol Channel         Channel cmsMarshaChannel =           cmsCarolChannel.GetByRelativePath("./Marsha")           as Channel;         //15. If our relative search for Marsha Channel         //    was successful         if (cmsMarshaChannel != null)         {           //16. Add the Channel path to the ListBox           ListBox1.Items.Add             ("Marsha Path: " + cmsMarshaChannel.Path.ToString());         }         else         {           //17. Provide nonerror feedback to the developer           ListBox1.Items.Add ("Marsha Channel not found");         }       }       else       {         //18. Provide nonerror feedback to the developer         ListBox1.Items.Add ("Carol Channel not found");       }     }     else     {       //19. Provide nonerror feedback to the developer       ListBox1.Items.Add ("Greg Channel not found");     }   }   catch(Exception eError)   {     //20. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

Build the solution and then refresh the Scratchpad posting in Internet Explorer, or browse to it and click the Button. The page should reload and look similar to Figure 25-18.

Figure 25-18. Show GetByRelativePath results

graphics/25fig18.gif

This member can be useful for searching for a Channel object or Posting object relative to the current channel or posting. However, searching for objects using their path is potentially fraught with error. If the reference is to an ambiguous item (duplicates are not prevented by CMS), one that does not exist, one that is in a different publishing mode, or one that the user doesn't have rights to, a null value is returned. Also, since the Path consists of the names of channels and postings and users can change those names, the Path can change, potentially rendering the code invalid. There can be performance issues as well.



Microsoft Content Management Server 2002. A Complete Guide
Microsoft Content Management Server 2002: A Complete Guide
ISBN: 0321194446
EAN: 2147483647
Year: 2003
Pages: 298

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net