ForwardLinks, Variations & user rights

Recently Tom, a colleague of mine, experienced some odd behavior using the ForwardLinks property of an SPListItem. We wanted to extend the out-of-the-box publishing features with some extra functionality using the forward links property, but ended up parsing rich text fields ourselves because of the non-expected behavior.

First of all, the ForwardLinks property should "Get a collection of hyperlinks that are associated with the item; for example, the hyperlinks in a URL Field or rich text field". So when we create a publishing page that contains links to some documents, the ForwardLinks property should be updated to contain these links. In the following scenario's we found that this is not the case.

Scenario 1

  • You create a page in /enu (variation source), with a link Link1 in the Rich Text field
  • You publish the page in /enu
  • The timer service propagates the page to the variations, creating a draft in all the target variations
  • ForwardLinks of all target variations correctly report the link Link1.
  • You publish the page in the target variations
  • You add another link Link2 in /enu
  • When querying the ForwardLinks as the app-pool acc, this link does not show up (the red marked I. in the schema)
  • You publish the page in /enu and wait for the propagation service
  • ForwardLinks is properly updated in /enu
  • ForwardLinks is not updated in the variation targets when querying as a sitecoll admin
  • ForwardLinks is updated when querying as app-pool acc
  • You check out the page in the target variations
  • You edit the rich text field in the target variations
  • You check in the page in the target variations
  • You publish the page in the target variations
  • ForwardLinks is properly updated in the target variations

Scenario 2

This is actually a variation on scenario 1, only this time we don't modify the variation source, only the variation targets

  • You create a page in /enu (variation source), with a link Link1 in the Rich Text field
  • You publish the page in /enu
  • The timer service propagates the page to the variations, creating a draft in all the target variations
  • ForwardLinks of all target variations correctly report the link Link1.
  • You publish the page in a variation target
  • While logged in as the site-admin, you edit a variation target and you add a new link Link2.
  • You check this variation target in as a new minor version
  • In this case, ForwardLinks queried as the site-admin returns the proper links. However, querying it as an app-pool account results in the wrong links (also see the red marked III. in the schema)
  • While logged in as the site-admin, publish the variation target
  • ForwardLinks returns the correct links for both site-admin as app-pool acc

In this case, querying ForwardLinks as the app-pool account returns the exact opposite of what was originally said: it returns the value of the latest published version instead of the latest draft version.

Scenario 3

Almost identical to scenario 2.

  • Execute step 1-5 of scenario2.
  • This time, log in as a user who's a member of the Designers group (not a sitecoll-admin). Edit a variation target and add a link Link2 in the rich-text field.
  • While logged in as a Designer user, do a check-in of the page (minor version)
  • When querying ForwardLinks as the sitecoll-admin or as app-pool, you only get a reference to Link1. Only when querying the property as the Designer-account, you get a proper reference to Link1 and Link2
  • Log back in as the sitecoll-admin and publish the page in the variation target-site
  • ForwardLinks property properly lists Link1 and Link2 for every user.

Conclusion

Querying ForwardLinks as the application-pool account does not always return the values of the latest draft version.

Furthermore, it looks like the values are totally random. Is there some documentation that describes the logic behind this property: in which case will it return a draft-version's links, in which case will it resort to the published version?

Fyi, we tried the following solutions to get the draft version... but they didn't work, since everyone of them conflicted with at least 1 scenario:

  • Query the ForwardLinks as the same user who's specified in ModifiedBy. this conflicts with our findings in scenario1, mark II. (the red rectangle)

If we're in a variation source, query ForwardLinks as the current-user, otherwise use the app-pool acc. this conflicts with scenario2, mark III and scenario3, mark IV