Managing Postings

There are many ways to manage a posting from PAPI. We will cover the brunt of them in this section. We will start with Submit, Approve, and Decline; then proceed to AcquireOwnership and ReleaseOwnership, CopyTo and MoveTo, and Delete; and end with ValidateChangeToken. Of course, users will need sufficient rights to interact with these methods.

Predictably, all the methods in this section will require that the Context be in Update mode (see the Getting into Update PublishingMode sidebar in Chapter 25). We will be using the function introduced in Listing 25-1 to get an authenticated CmsApplicationContext in Update PublishingMode. If we skip this step, we will receive a verbose .NET error page that basically says, You must be in Update mode to do this.

As always, after a posting has been deleted, attempting to call any of these methods will cause an exception. Also, attempting to call any of these methods on a Historical Revision will cause an exception.

In general, the OwnedBy property (discussed in Chapter 25) is implicitly changed to the current user so that other authors cannot concurrently update the posting or any of its ConnectedPostings. All changes only become permanent and ownership released (if appropriate) once the Context CommitAll method is called. Calling the Context Rollback All method before CommitAll will return the posting to its previously committed condition.

Before we start, to learn about the Submit, Approve, and Decline methods, you need a detailed understanding of a posting's state lifecycle.

NOTE: Chapter 6 contains an in-depth discussion about page status as it relates to the publishing workflow. Page status is a logical superset of the physical posting state.


First we'll discuss the two different names CMS uses for the logical page status and the physical posting state, and then how a posting moves through those posting states. Page status is a simplified logical superset of the actual physical posting state. Table 26-1 outlines the relationship between these two lists.

As you can see, some of the physical posting states have been consolidated and some (Deleted, Historical, and None) are not represented logically at all. Using the Submit, Approve, or Decline methods on a posting will have the same effect as if the authorized user within the same CMS Context had interactively used the Web Author console to accomplish the task. In fact, the Web Author console uses these methods to accomplish its work.

Table 26-1. Relationship between Page Status and Posting State

Page Status

Logical Description

Posting State

Physical Description

New

A new page has been created, but has not yet been saved for the first time.

New

The posting has not been stored permanently by the CMS server. It may be a new posting or a new unapproved version of an existing approved posting. A posting enters this state when it is first created or when a user modifies an existing posting that has only an Approved version.

Saved

The page has been saved, but has not yet been submitted for approval.

Saved

The posting has been permanently stored by the server, but has not been submitted or approved. A posting enters this state when it is first saved.

Waiting for Approval

The page has been submitted for approval, but has not yet been approved.

WaitingFor Editor Approval

The posting has been saved and submitted. It is waiting for editor approval.

WaitingFor Moderator Approval

The posting has either been approved by an editor or does not require editor approval. The posting version is now waiting for moderator approval.

Approved

The page has been approved.

Approved

The posting has been approved by both an editor and a moderator, or it did not require approval by one or both. The property StartDate is greater than the current date, so the posting is not yet visible on the site in Published mode.

Declined

The page has been declined (did not meet approval) and must be resubmitted after modification.

Editor-Declined

The posting has been saved and submitted, but an editor has declined it.

Moderator-Declined

The posting has been approved by an editor or did not require editor approval, but a moderator has declined it.

Expired

The approved page has expired (exceeded the expiration time specified in the publishing schedule for the page).

Expired

The posting has been approved by both an editor and a moderator, or it did not require approval by one or both. The property Expiry Date is less than the current date, so the posting is not visible on the site in Published mode.

Published

The page has been published on the live site.

Published

The posting has been approved by both an editor and a moderator, or it did not require approval by one or both. The current date is between the properties StartDate and ExpiryDate, so the posting is visible on the site in Published mode.

  

Deleted

The posting has been marked as deleted.

  

Historical

The posting is a historical revision.

  

None

The posting is in an incorrect state.

A posting can be promoted through the various physical posting states as illustrated by the UML transition diagram in Figure 26-2.

Figure 26-2. Typical posting state lifecycle

graphics/26fig02.jpg

A Submit will stop for approval based on the following conditions (assuming CanSubmit is true for the submitting user):

  • If at least one editor rights group has been assigned (in Site Manager User Roles) to the containing channel. The posting is only promoted to WaitingForEditorApproval State, unless the submitting user has Editor rights themselves.

  • If at least one moderator rights group has been assigned (in Site Manager User Roles) to the containing channel. The posting is only promoted to WaitingForModeratorApproval State, unless the submitting user has Moderator rights themselves.

It is possible, although not depicted, to submit or approve a posting that is in a New state. The default Web Author console requires a posting to be saved first.

As depicted, a Submit or Approve can promote a posting to Approved, Published, or Expired status, depending upon where today falls in relation to the posting's StartDate and ExpiryDate.

A posting can actually be approved by a user with sufficient rights directly from Saved state, EditorDeclined state, and ModeratorDeclined state. Assuming CanApprove is true for the submitting user, the same rules apply as if it had been approved from WaitingForEditorApproval.

When a posting is copied, its state doesn't change, but the state of the copied posting is set to the Saved state. If a posting is moved from any state other than Published, it is promoted to the Saved state. As depicted, if it is moved by a user with moderator rights (including an administrator) it remains in Published state.

Attempts to set posting properties or call posting methods will fail after a posting is marked as submitted, approved, or declined but before CommitAll has been called. CommitAll should be called as quickly after marking a posting as possible.

So, let's see some code using these methods.

Submit

To successfully use the Submit method, the CanSubmit property must return true for the referencing Posting object. See the rules for Can Submit earlier in this chapter. Also, the PublishingMode must be set to Update. Once again, we will be using the function introduced in Listing 25-1 to get an authenticated CmsApplicationContext in Update PublishingMode.

The result of calling the Submit method (Figure 26-3) will depend on the current state of the posting, the current user's rights, and the configuration of user roles for the containing channel. Assuming all goes well, the posting state will change to WaitingForEditorApproval, WaitingFor ModeratorApproval, Approved, Published, or Expired.

Figure 26-3. Submitting a posting

graphics/26fig03.gif

The OwnedBy property is updated.

It doesn't make any sense to use Submit on a posting when its state is Approved, Published, Expired, Deleted, or Historical. Attempting to do so will fail or have no effect.

Approve

To successfully use the Approve method, the CanApprove property must return true for the referencing Posting object. See the rules for CanApprove earlier in this chapter. As before, the PublishingMode must be set to Update (see Listing 25-1).

The result of calling the Approve method (Figure 26-3) will depend on the current state of the posting, the current user's rights, and the configuration of user roles for the containing channel. Assuming all goes well, the posting state will change to WaitingForModeratorApproval, Approved, Published, or Expired.

The OwnedBy property is released if there are no outstanding changes in this posting or any ConnectedPosting(s).

It doesn't make any sense to use Approve on a posting when its state is Approved, Published, Expired, Deleted, or Historical. Attempting to do so will fail or have no effect.

Later in this chapter, we will look at the Approvers collection of users that can approve postings.

Decline

To successfully use the Decline method, the CanApprove property must return true for the referencing Posting object. See the rules for Can Approve earlier in this chapter. As before, the PublishingMode must be set to Update (see Listing 25-1).

The result of calling the Decline method (Figure 26-3) will depend on the current state of the posting. A posting in WaitingForEditor Approval state will be promoted to EditorDeclined state. A posting in WaitingForModeratorApproval state will be promoted to Moderator Declined state.

The OwnedBy property remains the same so that the user that submitted the posting can change it without an explicit AcquireOwnership (discussed next).

It doesn't make any sense to use Decline on a posting when its state is New, Saved, EditorDeclined, ModeratorDeclined, Approved, Published, Expired, Deleted, or Historical. Attempting to do so will fail or have no effect.

Remember, the following code sample requires Listing 25-1 from the Chapter 25 to work.

Replace the Button1_Click function of our Scratchpad template 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. Grab an Authenticated Context in Update PublishingMode     //   from Listing 25 1     CmsApplicationContext cmsContextApp =       GetAuthenticatedCmsApplicationContext(PublishingMode.Update);     //3. Position the Application Context to the Current Posting     Posting cmsCurrentPosting =       cmsContextApp.Searches.GetByGuid(cmsContextHttp.Posting.Guid)       as Posting;     //4. Populate the label with informational text     Label1.Text = "Submiting " +       cmsCurrentPosting.DisplayName.ToString() + " Posting";     //5. Add the Description value to the ListBox     ListBox1.Items.Add("Starting Description: " +         cmsCurrentPosting.Description.ToString()       );     //6. Add the Posting State values to the ListBox     ListBox1.Items.Add("Starting State: " +       cmsCurrentPosting.State.ToString()       + "/" + cmsCurrentPosting.StateApprovedVersion.ToString()       + "/" + cmsCurrentPosting.StateUnapprovedVersion.ToString()       );     //7. Check that the current user has sufficient rights     if(cmsCurrentPosting.CanSetProperties)     {       //8. Change the Description       cmsCurrentPosting.Description = "Scratchpad";       //9. Commit change       cmsContextApp.CommitAll();     }     else     {       //10. Provide nonerror feedback to the developer       Label1.Text = cmsContextApp.User.ToString() +         " has insufficient rights to Set Properties";     }     //11. Check that the current user has sufficient rights     //    CanApprove will be false unless a change has been made     //    that requires approval     if(cmsCurrentPosting.CanApprove)     {       //12. Add the Description value to the ListBox       ListBox1.Items.Add("Altered Description: " +         cmsCurrentPosting.Description.ToString()         );       //13. Add the Posting State values to the ListBox       ListBox1.Items.Add("Altered State: " +         cmsCurrentPosting.State.ToString()         + "/" + cmsCurrentPosting.StateApprovedVersion.ToString()         + "/" + cmsCurrentPosting.StateUnapprovedVersion.ToString()         );       //14. Submit the Altered unpublished Posting       cmsCurrentPosting.Submit();       //15. Commit change       cmsContextApp.CommitAll();       //16. Add the Description value to the ListBox       ListBox1.Items.Add("After Submit Commit Description: " +         cmsCurrentPosting.Description.ToString()         );       //17. Add the Posting State values to the ListBox       ListBox1.Items.Add("After Submit Commit State: " +         cmsCurrentPosting.State.ToString()         + "/" + cmsCurrentPosting.StateApprovedVersion.ToString()         + "/" + cmsCurrentPosting.StateUnapprovedVersion.ToString()         );     }     else     {       //18. Provide nonerror feedback to the developer       Label1.Text = cmsContextApp.User.ToString() +         " has insufficient rights to Approve";     }     //19. Dispose of the stand-alone Application Context     cmsContextApp.Dispose();   }   catch(Exception eError)   {     //20. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

NOTE: The Searches method of a CMS Context is covered in detail in Chapter 28.


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 26-3.

We increased the height of the ListBox on the template for this example so that Figure 26-3 would show all six entries. You may need to scroll down to see the last two.

In this example, the current posting's Description starts out as an empty string and ends up with a value of Scratchpad. Note the circled values in Figure 26-3. Before any changes were made, the current posting was in Published state; after the committed change, it was promoted to Saved state; after the Submit was committed, it was promoted to Published state again.

The reason the state didn't become WaitingForEditorApproval or WaitingForModeratorApproval is that we are using an administrator account to submit the change, and an administrator is allowed to approve, so our changes are automatically promoted to the next state in the posting lifecycle. We also don't have an editor user role or a moderator user role assigned to the Scratch channel; so even if we didn't use a CMS administrator, as long as the user that we did use could submit the posting, it would have bypassed both Waiting For Approval states. Since the Start Date for the posting was before now, and the ExpiryDate is set to Never (01/01/3000), the next state would be Published.

The coding for Approve and Decline would be very similar. We would use CanApprove (for both) rather than CanSubmit, and, of course, the posting acted on would need to be in a state that required approval.

AcquireOwnership, ReleaseOwnership

The AcquireOwnership method sets the OwnedBy property's Server AccountName property for a posting and its ConnectedPostings, if any, to the current user after a Context CommitAll is called. It can only be used if the current user has CanSetProperties rights. See the rules for CanSetProperties earlier in this chapter. As before, the PublishingMode must be set to Update (see Listing 25-1).

If used, this property can optionally block other users from implicitly or explicitly taking ownership and can optionally check out the posting, potentially changing it to a Waiting for Moderator Approval state. A nonblocking reassignment of the OwnedBy property implicitly happens whenever writable properties or modifier methods are used on a posting. The posting's OwnedBy property is automatically set to the current user until the implicit modification is complete. If the OwnedBy property is set to the built-in Everybody value, no one currently owns it and anyone can acquire ownership.

However, there are times in a multiuser environment when we may want to block others from taking ownership of a posting while we are working with it. So, we can explicitly call AcquireOwnership with an optional first parameter indicating that we want to explicitly take exclusive ownership. Subsequent requests by anyone else to make changes to this posting will fail until we explicitly call ReleaseOwnership. It is possible for blocked users with sufficient rights to ignore the block and use ReleaseOwnership or AcquireOwnership exclusively on the posting so that they can manipulate it. However, this requires an overt action on their part.

Ownership is released when ReleaseOwnership is called, when another user acquires ownership (implicitly by modifying the posting or explicitly using AcquireOwnership), or when the posting goes into an Approved state.

Remember, the following code sample requires Listing 25-1 from Chapter 25 to work.

Replace the Button1_Click function of our Scratchpad template 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. Grab an Authenticated Context in Update PublishingMode     //   from Listing 25 1     CmsApplicationContext cmsContextApp =       GetAuthenticatedCmsApplicationContext(PublishingMode.Update);     //3. Position the Application Context to the Current Posting     Posting cmsCurrentPosting =       cmsContextApp.Searches.GetByGuid(cmsContextHttp.Posting.Guid)       as Posting;     //4. Check that the current user has sufficient rights     if(cmsCurrentPosting.CanSetProperties)     {       //5. Populate the label with informational text       Label1.Text = "Acquiring/Releasing Ownership of the " +         cmsCurrentPosting.DisplayName.ToString() + " Posting";       //6. Add the OwnedBy ServerAccountName value to the ListBox       ListBox1.Items.Add("Before Acquisition: " +         cmsCurrentPosting.OwnedBy.ServerAccountName.ToString());       //7. Explicitly acquire ownership       cmsCurrentPosting.AcquireOwnership();       //8. Commit change       cmsContextApp.CommitAll();       //9. Add the OwnedBy ServerAccountName value to the ListBox       ListBox1.Items.Add("After Committed Acquisition: " +         cmsCurrentPosting.OwnedBy.ServerAccountName.ToString());       //10. Explicitly release ownership       cmsCurrentPosting.ReleaseOwnership();       //11. Commit change       cmsContextApp.CommitAll();       //12. Add the OwnedBy ServerAccountName value to the ListBox       ListBox1.Items.Add("After Committed Release: " +         cmsCurrentPosting.OwnedBy.ServerAccountName.ToString());       //13. Add the OwnedBy IsEverybody value to the ListBox       ListBox1.Items.Add("Value of OwnedBy IsEverybody: " +         cmsCurrentPosting.OwnedBy.IsEverybody.ToString());     }     else     {       //14. Provide nonerror feedback to the developer       Label1.Text = cmsContextApp.User.ToString() +         " has insufficient rights to set properties";     }     //15. Dispose of the stand-alone Application Context     cmsContextApp.Dispose();   }   catch(Exception eError)   {     //16. Provide error feedback to the developer     Label1.Text = "<b>Error: </b>" + eError.Message.ToString();   } } 

For what its worth, the code under comment 13 demonstrates that the posting OwnedBy property (really any User property) has an IsEverybody property that returns true if the User is currently set to the built-in Everybody value.

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 26-4.

Figure 26-4. AcquireOwnership of posting

graphics/26fig04.gif

CopyTo, MoveTo

The CopyTo and MoveTo methods do exactly what you think that they would. CopyTo creates a new Posting object just like the referencing Posting object (ConnectedPostings just become regular Posting objects) in the destination channel. It requires that the current user have sufficient rights to create a new posting in the destination channel.

MoveTo changes the location of the referencing Posting object to the destination channel. The unapproved version of a posting is used, if any; otherwise, the approved version is used. It requires that CanMove be true on the Posting object to be moved and the current user have sufficient rights to create a new Posting object in the destination channel. See the rules for CanMove earlier in this chapter. As before, the PublishingMode must be set to Update (see Listing 25-1).

In both cases the destination posting state is promoted to Saved. As you would expect, these destination posting properties are also changed to intuitive values: CreatedBy, CreatedDate, LastModifiedBy, Last ModifiedDate, OwnedBy, and Parent.

Posting copies are always made from the committed values in the database.

Remember, the following code sample requires Listing 25-1 from the Chapter 25 to work.

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

 private void Button1_Click(object sender, System.EventArgs e) {   try   {     //1. Make sure that the user entered something into the TextBox     //   We will use this entry as the name for the new Posting     if(TextBox1.Text.Length > 0)     {       //2. Grab the current CMS Context       CmsHttpContext cmsContextHttp = CmsHttpContext.Current;       //3. Grab an Authenticated Context in Update PublishingMode       //   from Listing 25 1       CmsApplicationContext cmsContextApp =         GetAuthenticatedCmsApplicationContext(           PublishingMode.Update);       //4. Position the Application Context to the Current Posting       Posting cmsCurrentPosting =         cmsContextApp.Searches.GetByGuid(           cmsContextHttp.Posting.Guid)         as Posting;       //5. Populate the label with informational text       Label1.Text = "Copying " +         cmsCurrentPosting.DisplayName.ToString() + " Posting";       //6. Check that the current user has sufficient rights       if(cmsCurrentPosting.CanSetProperties)       {         //7. Copy the current Posting to the current Channel         //   creating a new Posting         Posting cmsNewPosting =           cmsCurrentPosting.CopyTo(cmsContextHttp.Channel);         //8. Commit change         cmsContextApp.CommitAll();         //9. Change the name of the new Posting to the value in         //   the TextBox         cmsNewPosting.Name = TextBox1.Text.ToString();         //10. Submit the altered, unpublished Posting         //    Since we authorized as a CMS administrator, Submit         //    will approve the new Posting too         cmsNewPosting.Submit();         //11. Commit change         cmsContextApp.CommitAll();         //12. Add new Posting link to the label         Label1.Text += "<br><a href=" +           cmsNewPosting.UrlModePublished.ToString() +           ">Click link to New Posting</a>";         //13. Add the DisplayName value and URL to the ListBox         ListBox1.Items.Add("New Posting Display Name: " +           HttpUtility.HtmlEncode(             cmsNewPosting.DisplayName.ToString())           );         ListBox1.Items.Add("New Posting URL: " +           cmsNewPosting.UrlModePublished.ToString()           );       }       else       {         //14. Provide nonerror feedback to the developer         Label1.Text = cmsContextApp.User.ToString() +           " has insufficient rights to Set Properties";       }       //15. Dispose of the stand-alone Application Context       cmsContextApp.Dispose();     }     else     {       //16. Provide nonerror feedback to the developer       Label1.Text = "Enter name for new Posting into the TextBox";     }   }   catch(Exception eError)   {     //17. 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 26-5.

Figure 26-5. Copy posting to current channel with new name

graphics/26fig05.gif

After this code is run, there will physically be a new posting (in this case, called TestPosting) in the same channel as the current posting. We've included a link to the new posting. If you want, open Site Manager, or choose Global Refresh from the Site Manager View menu if it is already open. You can view (or even delete) this new posting from the channel in which it was created.

Next, we will delete this copied posting.

Delete (Inherited from HierarchyItem)

To successfully use the Delete method, the CanDelete property must return true for the referencing Posting object. See the rules for Can Delete earlier in this chapter. As before, the PublishingMode must be set to Update (see Listing 25-1).

Calling the Delete method merely marks an item for deletion. The item isn't actually deleted from the database until CommitAll on the Context is called. Even after a CommitAll, the item isn't actually deleted from any in-memory collection in which it existed before deletion. Interaction with a deleted item before CommitAll will return read-only values; interaction with a deleted item after CommitAll will cause an exception. Unlike in Site Manager, deletion of an item after a CommitAll cannot be undone. The item is not moved into a Deleted Items folder. It is possible to undo a delete before a CommitAll by calling a RollbackAll. Any attempt to delete an item that is being edited by another user will cause an exception.

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

 private void Button1_Click(object sender, System.EventArgs e) {   try   {     //1. Make sure that the user entered something into the TextBox     //   We use this entry as the path to the Posting to delete     if(TextBox1.Text.Length > 0)     {       //2. Grab an Authenticated Context in Update PublishingMode       //   from Listing 25 1       CmsApplicationContext cmsContextApp =         GetAuthenticatedCmsApplicationContext(           PublishingMode.Update);       //3. Grab the Posting to expunge       //   Cast the result of the Searches object as a Posting       Posting cmsPosting =         cmsContextApp.Searches.GetByPath(TextBox1.Text.ToString())         as Posting;       //4. Check if the user has sufficient rights to delete       if(cmsPosting.CanDelete)       {         //5. Populate the label with informational text         Label1.Text = "Deleting " +           cmsPosting.DisplayName.ToString() + " Posting";         //6. Delete Posting         cmsPosting.Delete();         //7. Provide visual feedback of Posting deletion         ListBox1.Items.Add( cmsPosting.Name +           " Posting was deleted from " +           cmsPosting.Parent.Name.ToString() + " Channel"           );         //8. Commit changes         cmsContextApp.CommitAll();       }       else       {         //9. Provide nonerror feedback to the developer         Label1.Text = "<b>User NOT allowed to delete Posting";       }       //10. Dispose of the stand-alone Application Context       cmsContextApp.Dispose();     }     else     {       //11. Provide nonerror feedback to the developer       Label1.Text = "Enter the path of the Posting to delete " +         "into the TextBox";     }   }   catch(Exception eError)   {     //12. 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 26-6.

Figure 26-6. Delete posting

graphics/26fig06.gif

Open Site Manager, or choose Global Refresh from the Site Manager View menu if it is already open. The posting should be expunged. Notice that you don't even find it in the Deleted Items hive.

ValidateChangeToken

The ValidateChangeToken method confirms that no other user has changed the posting since it was last retrieved. When a Posting object is hydrated by CMS, a ChangeToken property value is populated and kept with the posting. We can pass that token to CMS for this posting to see if anything has happened to the posting since we retrieved it.

However, this method only works in Update PublishingMode and requires that the authenticated user have rights to edit the posting as defined by CanSetProperties (discussed earlier in this chapter). It should be used on the working revision of a posting and then only if there is the possibility that other users may have changed the posting since it was read by the current process.

This method will typically be used just before calling CommitAll. Calling this method successfully will leave the posting locked by the current user until an explicit CommitAll or RollbackAll method is called or an implicit call is made based upon the RollbackOnSessionEnd property of the Context.

Replace the Button1_Click function of our Scratchpad template 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. Grab an Authenticated Context in Update PublishingMode     //   from Listing 25 1     CmsApplicationContext cmsContextApp =       GetAuthenticatedCmsApplicationContext(PublishingMode.Update);     //3. Position the Application Context to the Current Posting     Posting cmsCurrentPosting =       cmsContextApp.Searches.GetByGuid(cmsContextHttp.Posting.Guid)       as Posting;     //4. Check that the current user has sufficient rights     if(cmsCurrentPosting.CanSetProperties)     {       try       {         //5. Check to see if anything has changed since the Posting         //   was read         cmsCurrentPosting.ValidateChangeToken           (cmsCurrentPosting.ChangeToken);         //6. Populate the label with informational text. The code         //   will not get to this line if the previous line fails         Label1.Text = cmsCurrentPosting.DisplayName.ToString() +           " Posting not altered by anyone since it was last read";       }       catch(Exception eError)       {         //7. Provide error feedback to the developer         Label1.Text = "<b>Bad Token: </b>" +           eError.Message.ToString();       }     }     else     {       //8. Provide nonerror feedback to the developer       Label1.Text = cmsContextApp.User.ToString() +         " has insufficient rights to Set Properties";     }     //9. Dispose of the standalone Application Context     cmsContextApp.Dispose();   }   catch(Exception eError)   {     //10. 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 26-7.

Figure 26-7. ValidateChangeToken

graphics/26fig07.gif



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