Search code examples
sharepointtextsharepoint-2007

Detect a change in a rich text field's value in SPItemEventReceiver?


I currently have an Event Receiver that is attached to a custom list. My current requirement is to implement column level security for a Rich Text field (Multiple lines of text with enhanced rich text).

According to this post[webarchive], I can get the field's before and after values like so:

object oBefore = properties.ListItem[f.InternalName];
object oAfter = properties.AfterProperties[f.InternalName];

The problem is that I'm running to issues comparing these two values, which lead to false positives (code is detecting a change when there wasn't one).

Exhibit A: Using ToString on both objects

oBefore.ToString()

<div class=ExternalClass271E860C95FF42C6902BE21043F01572>
<p class=MsoNormal style="margin:0in 0in 0pt">Text. 
</div>

oAfter.ToString()

<DIV class=ExternalClass271E860C95FF42C6902BE21043F01572>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">Text. 
</DIV>

Problems?

  • HTML tags are capitalized
  • Random spaces (see the additional space after margin:)

Using GetFieldValueForEdit or GetFieldValueAsHTML seem to result in the same values.

"OK," you say, so lets just compare the plain text values.

Exhibit B: Using GetFieldValueAsText

Fortunately, this method strips all of the HTML tags out of the value and only plain text is displayed. However, using this method led me to discover additional issues with whitespace characters:

In the before value:

  1. Sometimes there are additional newline characters.
  2. Sometimes spaces are displayed as non-breaking spaces (ASCII char code 160)

Question:

How can I detect if the user changed a rich text field in an event receiver?

  1. [Ideal] Detect any change to HTML or text or white space
  2. [Acceptable] Detect changes to text or white space
  3. [Not so good] Detect changes to text characters only (strip all non-alphanumeric characters)

Solution

  • I'm currently testing a combination approach: GetFieldValueAsText and then stripping out all characters except alphanumeric/punctuation:

    static string GetRichTextValue(string value)
    {
        if (null == value)
        {
             return string.Empty;
        }
        StringBuilder sb = new StringBuilder(value.Length);
        foreach (char c in value)
        {
             if (char.IsLetterOrDigit(c) || char.IsPunctuation(c))
             {
                  sb.Append(c);
             }
        }
        return sb.ToString();
    }
    

    This only detects changes to the text of a rich text field but seems to work consistently.