简体   繁体   中英

How to get field name of item in sitecore when creating custom event handlers

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?

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? ie 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 (eg 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>

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
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM