none
Change file name in Event Handler ItemAdding RRS feed

  • Question

  • Hi, I have a sharepoint document library and an event hadler associated with it. When I create a new item I need to catch the filename and rename it with a name that I want.  I have read some things about it, mas I haven't found the answer yet.

    I have tried to rename it in ItemAdding but it doesn't work. Here is some of my code:

     

    [ toolTipFieldInternalName = web.Lists[properties.ListId].Fields["Nome"].InternalName;
     SPFile spf = web.GetFile(properties.AfterUrl);

     spf.Name.Replace(subtitle, subnewtitle);]

     

    Any help with this would be nice and sorry the bad english Smile

    thanks

     

    ebgirl

    Wednesday, February 27, 2008 2:23 PM

Answers

  • Ok, no problem Smile

     

    The only way that I've found to rename a file in a sharepoint list is to use the method "MoveTo". The MoveTo changes the file's url. The filename is linked to the url and I believe that this must be the reason why it works.

     

    Here it's a bit of my code that I used in ItemAdded:

     

    To get the file:

     

     SPFile spf = properties.ListItem.File;
     string url = properties.AfterUrl;

     

    This url should be like:

     

    sharepointlist/filename (for example: books/mybook.doc)

     

    Then I've changed the string and maded a new url (for example: books/ ID_mybook.doc), and called it "newurl".

     

    After that I used the following code:

     

    string newurl = myNewUrlString;
    DisableEventFiring();
    spf.MoveTo(newurl);

    spf.Update();
    EnableEventFiring();

     

    The "MoveTo" is the last thing I do in ItemAdded because when I was trying to do it before running my other code I was getting problems on CheckOut(). So I do everything I need first and in the end I "rename" the file.

     

    ebgirl

     

     

     

     

     

    Friday, February 29, 2008 4:47 PM

All replies

  • Please check if you get "ListId" and any other reference to the item thats being added.

    I guess its all null

     

    You will have to change the name then do it on  itemadded

     

     

    isha

    http://programmingsharepoint.blogspot.com/

    Wednesday, February 27, 2008 5:42 PM
  • I've tried to rename it on itemadded but it doesn´t work.

    I've tried with "moveTo" to move it to new url and it worked. In the document library field the new name looks alright.The problem is that when event handler runs the rest of the code it gives me the error "the file has not been found" in the properties.ListItem.File...

     

    ebgirl

    Wednesday, February 27, 2008 6:06 PM
  • ok in Item added try to get the field name (name of the documnet ) of the new document added

     

    like CurrentItem["Name"] if you get it , then you can simply reset it. by assigning this to another string

     

    Dont forget Update method!.

     

    Just comment all other and try to get simple things for the file.

     

     

    isha

     

    Wednesday, February 27, 2008 6:14 PM
  • I've tried that too. I´ve catch the file name and assigned it  a new string. A have made "ListItem.Update();"

    and it doesn't work. The name did not suffer any change.

    I thought it was a simple thing to do but it doesn't look like that.

    What am I missing?

    thanks for your help.

     

    ebgirl

    Wednesday, February 27, 2008 6:31 PM
  • You need to use the AfterProperties to affect the end result.

     

    try this:

     

    properties.AfterProperties["Name"] = "My new file name";

     

    of something of that ilk.

     

    -Gavin

    Thursday, February 28, 2008 1:08 AM
  • Thanks but unfortunally that does'nt work. It gives me an error that properties cannot be changed.

    I haven't figure it out yet... Sad

    Thursday, February 28, 2008 12:29 PM
  • That's a pain....

     

    it could be due to the fact that the item name and the file name are linked when you're adding the file?

     

    It may be that you need to refactor the timing of the event to use ItemAdded. This way the ListItem is not null and you can work directly against that..

     

    I'm interested to hear how you get along.

    Friday, February 29, 2008 12:43 AM
  • Hi ebgirl,

     

    This should do the trick!?

     

     

     

    Code Snippet

    public override void ItemAdded(SPItemEventProperties properties)
            {
                SPFile thisFile = properties.ListItem.File;

     

     //do your checking here

     

    //rename the file name if necessary

    properties.ListItem.Name = "NEW NAME";


                properties.ListItem.Update();
                base.ItemAdded(properties);
            }

     

     

     

     

    Regards,

    James

    Friday, February 29, 2008 7:07 AM
  • I've tried that too, but it gives me an error saying that property name is "read-only".

    I'm using the method "moveTo" because it's working and I've change the rest of the code in "ItemAdded" to work over the file at the new url. I thought that everything was ok mas then I tried to edit the item in sharepoint's document library and when I tried to change something the itemUpdated doesn't work as it should. I'm still working on it.

     

    ebgirl

     

    Friday, February 29, 2008 11:00 AM
  • Finally it's working! After using the method "moveTo" the problem was in ItemUpdating because afterproperties wasn´t catching the right values. Then I've passed the code in ItemUpdating into ItemUpdated and maded a few adjustments and now it's working just fine.Smile

     

    Thanks for your support!

     

    ebgirl

    Friday, February 29, 2008 2:06 PM
  • Please paste some code sample here so it can help others, Thanks

     

    Friday, February 29, 2008 2:54 PM
  • Ok, no problem Smile

     

    The only way that I've found to rename a file in a sharepoint list is to use the method "MoveTo". The MoveTo changes the file's url. The filename is linked to the url and I believe that this must be the reason why it works.

     

    Here it's a bit of my code that I used in ItemAdded:

     

    To get the file:

     

     SPFile spf = properties.ListItem.File;
     string url = properties.AfterUrl;

     

    This url should be like:

     

    sharepointlist/filename (for example: books/mybook.doc)

     

    Then I've changed the string and maded a new url (for example: books/ ID_mybook.doc), and called it "newurl".

     

    After that I used the following code:

     

    string newurl = myNewUrlString;
    DisableEventFiring();
    spf.MoveTo(newurl);

    spf.Update();
    EnableEventFiring();

     

    The "MoveTo" is the last thing I do in ItemAdded because when I was trying to do it before running my other code I was getting problems on CheckOut(). So I do everything I need first and in the end I "rename" the file.

     

    ebgirl

     

     

     

     

     

    Friday, February 29, 2008 4:47 PM
  • I got the following error event I put the SPFile.MoveTo at the bottom of ItemAdded Event.  Turned out that I only get this error if I turned on Document Version History.  When the .xls file put into document library by SSRS subscriber, ItemUpdated is called shortly after program enters into ItemAdded. ItemUpdated won't be called if No Versioning is selected.

    And I checked by this.GetHashCode() in VS Immediate Window, it looks like different instances of SPItemEventReceiver are instantiated to run ItemAdded and ItemUpdated, so I don't think I can define a Lock object at SPItemEventReceiver to synchronize ItemAdded and ItemUpdated.

    I am think about something like static Dictionary<Guid, ReaderWriterLock> lks inside SPItemEventReceiver, Guid stands for the List Item UniqueId, however, ConcurrentDictionary<TKey,TValue> (https://msdn.microsoft.com/en-us/library/dd287191(v=vs.100).aspx) is for .net 4.0 and above. I am in a SharePoint 2010 project, I don't know whether its safe to use .net 4.0 and how.

    file rpt5/测试销售日报__31.xls has been modified by SHAREPOINT\system on 28 12月 2015 14:01:10 +0800.   在 Microsoft.SharePoint.SPGlobal.HandleComException(COMException comEx)     在 Microsoft.SharePoint.Library.SPRequest.AddOrUpdateItem(String bstrUrl, String bstrListName, Boolean bAdd, Boolean bSystemUpdate, Boolean bPreserveItemVersion, Boolean bPreserveItemUIVersion, Boolean bUpdateNoVersion, Int32& plID, String& pbstrGuid, Guid pbstrNewDocId, Boolean bHasNewDocId, String bstrVersion, Object& pvarAttachmentNames, Object& pvarAttachmentContents, Object& pvarProperties, Boolean bCheckOut, Boolean bCheckin, Boolean bMigration, Boolean bPublish, String bstrFileName, ISP2DSafeArrayWriter pListDataValidationCallback, ISP2DSafeArrayWriter pRestrictInsertCallback, ISP2DSafeArrayWriter pUniqueFieldCallback)


    • Edited by GuYuming Monday, December 28, 2015 7:25 AM
    Monday, December 28, 2015 7:24 AM
  • My co-worker suggest me that whether I had disabled event firing.

    I had EventFiringEnabled = false , but its after base.ItemAdded(properties)

    So, I move it before base.ItemAdded(properties). looks like it solved the problem. However, in regression test, the problem appear again. From the call stack information, I suspect ItemUpdating is still called. I try to find ULS log entry for ItemUpdating, but what Category shall I filter with? Which logging area and category shall I turn in in Central Admin?

    Thursday, December 31, 2015 7:42 AM
  • I added my custom spmonitorscope in ItemAdded and ItemUpdating event receiver:

    it seems that different threads in the same process involves in race condition although  EventFiringEnabled = false is set at the first line in event receiver:


    • Edited by GuYuming Thursday, December 31, 2015 9:32 AM
    Thursday, December 31, 2015 9:30 AM
  • it looks like what described in http://andrewwburns.com/2011/01/05/how-disableeventfiring-eventfiringenabled-works/ :

     This LocalDataStoreSlot is in the SPEventManager class, and being static, it’ll be shared across the entire thread, for that current domain.

    This is interesting, as it leads to an interesting scenario – if you were creating additional threads from your Event Receiver’s thread, then event firing will not be disabled on those.

    As a workaround, I build my own thread safe collections following http://blogs.msdn.com/b/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx .

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading;
    
    namespace EmailTimerJob
    {
        public class ThreadSafeListOfReadWriteLock
        {
            private class SPListItemLock
            {
                public SPListItemLock(Guid guid)
                {
                    listItemUniqueId = guid;
                    rwLock = new ReaderWriterLock();
                }
                public Guid listItemUniqueId;
                public ReaderWriterLock rwLock;
            }
            private List<SPListItemLock> lockList = new List<SPListItemLock>();
            private ReaderWriterLock listLock = new ReaderWriterLock();
            public int lktimeout = 1000 * 60; //60 seconds
    
            public ReaderWriterLock AddLockForListItem(Guid id)
            {
                using (URPReaderWriterLockHelper lk=new URPReaderWriterLockHelper(ref listLock,ref lktimeout,URPReaderWriterLock.Write,string.Concat("AddLockForListItem(",id.ToString(),")")))
                {
                    SPListItemLock itemlk = new SPListItemLock(id);
                    lockList.Add(itemlk);
                    return itemlk.rwLock;
                }
            }
    
            public ReaderWriterLock GetLockForListItem(Guid id)
            {
                using (URPReaderWriterLockHelper lk=new URPReaderWriterLockHelper(ref listLock,ref lktimeout,URPReaderWriterLock.Read,string.Concat("GetLockForListItem(",id.ToString(),")")))
                {
                    SPListItemLock itemlock=lockList.FirstOrDefault(_=>_.listItemUniqueId.Equals(id));
                    if (itemlock!=default(SPListItemLock))
                    {
                        return itemlock.rwLock;
                    }
                    else
                    {
                        return AddLockForListItem(id);
                    }
                }
            }
        }
    }
    For the URPReaderWriterLockHelper:https://social.msdn.microsoft.com/Forums/office/en-US/46395303-9bf9-4a15-85b5-16e193abdfe2/large-object-memory-cache-refreshing?forum=sharepointdevelopment#46395303-9bf9-4a15-85b5-16e193abdfe2


    • Edited by GuYuming Saturday, January 2, 2016 1:53 PM
    Saturday, January 2, 2016 1:49 PM
  • this might be not exactly the same issue, but must related.

    http://blogs.msdn.com/b/unsharepoint/archive/2010/11/10/sharepoint-event-receivers-making-asynchronous-event-synchronous-to-avoid-save-conflict-error.aspx

    http://blogs.msdn.com/b/manuj/archive/2009/09/22/itemadded-event-on-document-library-the-file-has-been-modified-by-on-error.aspx

    Update: I finally give up my custom ThreadSafeListOfReadWriteLock and use ItemUpdated and ItemAdded event receiver. But change this two event receivers both to Synchronious 

    • Edited by GuYuming Friday, January 8, 2016 9:14 AM
    Monday, January 4, 2016 3:42 AM