I have created a messaging system (basically a simple announcement list with a recipient and a IsRead flag).
This have been done by creating the classics web fields, content type, list schema and list instance. All of this is working as expected.
I want to set the Isread flag (a boolean field) as soon as the user navigates to the dispform page.
In order to reach this goal, I've created a simple webpart with no UI that set the IsRead field on the SPContext.ListItem item :
[ToolboxItemAttribute(false)]
public class MessageSetRead : WebPart
{
protected override void OnInit(EventArgs e)
{
try
{
var listItem = SPContext.Current.ListItem;
// TODO: ensure listitem is a message and exists
var isReadField = listItem.Fields.GetFieldByInternalName("IsRead");
var isRead = (bool)listItem[isReadField.Id];
var recipientField = listItem.Fields.GetFieldByInternalName("AssignedTo");
var recipientStr = (string) listItem[recipientField.Id];
var isCurrentUserRecipient = string.IsNullOrEmpty(recipientStr) ?
false:
new SPFieldUserValue(SPContext.Current.Web, recipientStr).LookupId == SPContext.Current.Web.CurrentUser.ID;
if (!isRead && isCurrentUserRecipient)
SPContextUtilities.RunWithElevatedPrivileges((elevatedSite, elevatedWeb) =>
{
using (elevatedWeb.CreateUnsafeUpdateAllowedContext())
{
var elevatedList = elevatedWeb.Lists[SPContext.Current.ListId];
var elevatedListItem = elevatedList.Items.GetItemById(SPContext.Current.ItemId);
elevatedListItem[isReadField.Id] = true;
elevatedListItem.SystemUpdate(false);
}
});
}
}
catch (Exception exc)
{
this.Controls.Clear();
var errorMessage = new Label();
errorMessage.Text = HttpUtility.HtmlEncode(exc.ToString());
errorMessage.Style[HtmlTextWriterStyle.WhiteSpace] = "no-wrap";
errorMessage.Style[HtmlTextWriterStyle.Color] = "red";
this.Controls.Add(errorMessage);
}
}
}
The webpart is put on the dispform.aspx file from the list schema.xml file :
<Form Type="DisplayForm"
Url="DispForm.aspx"
SetupPath="pages\form.aspx"
WebPartZoneID="Main">
<WebParts>
<AllUsersWebPart WebPartOrder="Integer"
WebPartZoneID="Main">
<![CDATA[
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="MyCustomer.Messaging.MessageSetRead.MessageSetRead, $SharePoint.Project.AssemblyFullName$" />
<importErrorMessage>$Resources:core,ImportErrorMessage;</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">MessageSetRead</property>
<property name="Description" type="string">My WebPart</property>
</properties>
</data>
</webPart>
</webParts>
]]>
</AllUsersWebPart>
</WebParts>
</Form>
Everything is working but with one gotcha.
When I navigate to the dispform, the IsRead flag is actually set to true, but the user see 'No' in the item. A simple refresh will show the 'Yes' value as expected.
I think this is due to the SPContext.ListItem population which occurs before my Page_Init.
What is the life cycle of the SPContext.ListItem object ?
How should I change my code to see the updated value of my field ?
Thanks
PS: using SP 2010 Enterprise