Reputation: 281
In the handler I need to get a fields names(not field values!) that have been modified and add them to the log. I've tried item.DisplayName
, item.Name
, but it's a value of the field, not a name.
public void OnItemSavedHandled(object sender, EventArgs args)
{
Item temp = Event.ExtractParameter(args, 0) as Item;
Log.Info(string.Format(
"Item field {0} was modified at: {1}, by user:{2}",
temp.DisplayName,
DateTime.Now.ToString(), Sitecore.Context.User.Name),
this);
}
This code add to log a value, not a name of the field. How to get a name?
Upvotes: 3
Views: 4789
Reputation:
When you save an item minimun 4 fields I guess are save: item you modify,_Updated by,_Updated and Revision fields The solution is next one
public void OnItemSaved(object sender, EventArgs args)
{
SitecoreEventArgs eventArgs = args as SitecoreEventArgs;
Debug.Assert(eventArgs != null, "eventArgs != null");
//get the item who was changed
Item item = eventArgs.Parameters[0] as Item;
//get the fields that was modified
ItemChanges list = eventArgs.Parameters[1] as ItemChanges;
//parse the list of items and check if current field was modified
// I didn't find an solution without parsing list
foreach (Field field in list.Item.Fields)
if (list.IsFieldModified(field))
{
//get the field Name
string s = field.Name;
}
//now your code
}
Upvotes: 3
Reputation: 2395
If you're going to use the event handlers, you should consider using the OnItemSaving
event instead of the OnItemSaved
event. Before an item is saved, you can loop through it's fields to determine if a field value has changed using the Field.IsFieldModified
property of an individual field. Otherwise, if you use the OnItemSaved
handler, you'll have to retrieve the ItemChanges
object for the item that was saved, loop through fields in the ItemChanges
, and check the IsFieldModified
property there.
Here is code for the OnItemSaving event handler:
public void OnItemSaving(object sender, EventArgs args)
{
Item item = Event.ExtractParameter(args, 0) as Item;
if (item == null)
return;
item.Fields.ReadAll();
foreach (Field field in item.Fields)
{
if (!field.IsModified) //check if the field is modified
continue;
Log.Audit(string.Format("OnItemSaving - Item field {0} was modified at: {1}, by user: {2}", field.DisplayName, item.Statistics.Updated.ToString(CultureInfo.InvariantCulture), item.Statistics.UpdatedBy), this);
}
}
With all of that said, I wouldn't actually recommend using the OnItemSaved
or OnItemSaving
events for your purposes. The saved/saving events are raised by the API as a part of ANY save operation performed on the item - whether by Sitecore or by a Sitecore user. Therefore, you may notice that the events are being raised when you wouldn't normally expect them to be. For instance, during the publish process, a save operation is executed and therefore the saved/saving events are raised. There may be other instances when unintended save operations occur as well.
It sounds like you'd rather just capture user save events? i.e. when a content author clicks the 'Save' button for a specific item? If so, I would recommend tapping into the Sitecore.Pipelines.Save
pipeline. This pipeline is triggered only when a Sitecore UI save event occurs (e.g. Save button click, Ctrl+S hot key save, etc...)
To use the Sitecore.Pipelines.Save
pipeline, you will need to create a processor for the pipeline, then add it to the /sitecore/process/saveUI
processor in your web.config file (ideally, via a config include file). Here is code you could use for the pipeline processor:
public class LogFieldChanges
{
public void Process(SaveArgs args)
{
foreach (var saveItem in args.Items) //loop through item(s) being saved
{
var item = Sitecore.Context.ContentDatabase.GetItem(saveItem.ID, saveItem.Language, saveItem.Version); //get the actual item being saved
if (item == null)
continue;
foreach (var saveField in saveItem.Fields) //loop through the fields being saved
{
var field = item.Fields[saveField.ID]; //retrieve the Field from the actual item
var isModified = saveField.OriginalValue != saveField.Value; //determine if the field has been modified, we only want to log modified fields
if (field == null || !isModified)
continue;
Log.Audit(string.Format("SaveUI - Item field {0} was modified at: {1}, by user: {2}", field.DisplayName, item.Statistics.Updated.ToString(CultureInfo.InvariantCulture), item.Statistics.UpdatedBy), this);
}
}
}
}
In order for this code to work, it's important that your custom processor be inserted AFTER the Sitecore.Pipelines.Save.Save
processor. By placing it after that processor, you're able to use the SaveField.OriginalValue
and SaveField.Value
properties to determine if the field has been modified. Also, by placing your processor after the Sitecore.Pipelines.Save.Save
processor, you're able to use the Item.Statistics
properties to determine when and by whom the item was saved.
<sitecore>
<processors>
<saveUI>
.
.
<processor mode="on" type="Sitecore.Pipelines.Save.Save, Sitecore.Kernel" />
<!-- insert your processor after the Sitecore.Pipelines.Save.Save processor -->
<processor mode="on" type="Sitecore.Extensions.Pipelines.Save.LogFieldChanges, Sitecore.Extensions"/>
.
.
</saveUI>
</processors>
</sitecore>
Upvotes: 5