1

In SP 2013 I coded an event receiver that intercepts the ItemAdded event and it just renames the file.

It is a synchronous event (I added Synchronous in the Elements.xml).

This is the code:

    public override void ItemAdded(SPItemEventProperties properties)
     {
         SPSecurity.RunWithElevatedPrivileges(delegate()
         {
             try
             {
                 OutputDebugStringA("Inside ItemAdded");
                 string szHttpUrl = properties.WebUrl + "/" + properties.AfterUrl;
                 SPWeb openedWeb = properties.Web.Site.OpenWeb(properties.Web.ID);
                 SPFile spf = openedWeb.GetFile(szHttpUrl);
                 EventFiringEnabled = false;
                 string szUrl = properties.AfterUrl;
                 szUrl = szUrl + ".renamed";
                 string szNewFileName;
                 if (szUrl.LastIndexOf('\\') != -1) szNewFileName = szUrl.Substring(szUrl.LastIndexOf('\\') + 1);
                 else if (szUrl.LastIndexOf('/') != -1) szNewFileName = szUrl.Substring(szUrl.LastIndexOf('/') + 1);
                 else szNewFileName = szUrl;
                 if (properties.ListItem != null)
                 {
                     properties.ListItem["Title"] = szNewFileName;
                     properties.ListItem.Update();
                 }
                 spf.MoveTo(szUrl);
                 EventFiringEnabled = true;
                 base.ItemAdded(properties);
                 OutputDebugStringA("Renaming to " + szUrl);
             }
             catch (System.Exception exception)
             {
                 OutputDebugStringA("ItemAdded ERROR: " + exception.ToString());
             }

        });
     }

The problem is that when I upload a .txt file using Internet Explorer, just after the renaming is done, IE says that something went wrong and when I inspect the log files I see:

SPRequest.GetFileAndFolderProperties: UserPrincipalName=i:0).w|s-1-5-21-4050800873-4278272723-3073177257-500, AppPrincipalName= ,bstrUrl=-------- ,bstrStartUrl=Shared Documents/test2.txt ,ListDocsFlags=16400 ,bThrowException=True 0fa7689c-674b-5045-c3a2-b214a5d4cbed 01/09/2014 15:29:26.75 w3wp.exe (0x1544) 0x16F4 SharePoint Foundation General ai1wu Medium System.IO.FileNotFoundException: 0x80070002, StackTrace: at Microsoft.SharePoint.SPWeb.GetFileOrFolderProperties(String strUrl, ListDocsFlags listDocsFlags, Boolean throwException, SPBasePermissions& permMask) at Microsoft.SharePoint.SPFile.PropertiesCore(Boolean throwException) at Microsoft.SharePoint.SPFile.get_Length() at Microsoft.Office.RecordsManagement.PolicyFeatures.ApplicationPages.UploadPage.OnSubmit(Object o, EventArgs e) at Microsoft.Office.RecordsManagement.PolicyFeatures.ApplicationPages.UploadExPage.OnSubmit(Object o, EventArgs e) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest(Boolean includeSta... 0fa7689c-674b-5045-c3a2-b214a5d4cbed ...gesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) at System.Web.UI.Page.ProcessRequest() at System.Web.UI.Page.ProcessRequest(HttpContext context) at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error) at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb) at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContex... 0fa7689c-674b-5045-c3a2-b214a5d4cbed ...t, IntPtr moduleData, Int32 flags) at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags) at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus) at System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr pHandler, RequestNotificationStatus& notificationStatus) at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags) at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags) 0fa7689c-674b-5045-c3a2-b214a5d4cbed

So it is clear that the fact that I renamed the file is causing an issue in the SharePoint upload logic.

As a solution what I did was to not declare it as Synchronous, but if I do it then there is another error when SharePoint shows the Edit Properties dialog. In this case the upload is OK but when it is time to show that Edit Property dialog IE fails and says that the file has been already modified, or that "something went wrong".

If I use a synchronous event I get one problem. If I use the asynchronous event I get another problem.

It's very frustating and I am pretty sure that a so important API like Event Receivers should have support renaming files so I hope someone can tell me what I am doing wrong.

  • FYI, running code in and RunWithElevatedPrivileges delegate does nothing if you do not open up fresh SPSite and SPWeb objects :) – Robert Lindgren Jan 9 '14 at 18:52
1

Use ItemAdding to prepare file for uploading and ItemAdded to kick off bussiness logic. This means, in your case, I would put all the code in ItemAdding event.

In this way you can utilize properties.AfterProperties to rename file.

properties.AfterProperties["Title"] = szNewFileName;

Also, I'd recommended to access SPWeb as

SPWeb web = properties.Feature.Parent as SPWeb;

If I'm not mistaken, your approach will cause memory leak, and even if you do dispose it, you are creating brand new SPWeb object which may or may not be lightweight.

  • Thanks, but unfortunately properties.ListItem is NULL in ItemAdding... I need to rename the file depending on its content and to also modify its content. I am surprised this common task is so complex. – Paul Jan 10 '14 at 16:28
  • 1
    @Paul - like I said, you have to access properties.AfterProperties (or properties.BeforeProperties) instead properties.ListItem. However, I've never parsed the (.txt) file on any -"ing" receivers, so I'm not 100% sure it can be done (but I can't think of any reason why it couldn't be done) – StupidOne Jan 10 '14 at 19:04
  • The problem on doing stuffs on the ItemAdding is that I cannot access the file content... I mean, I cannot access the SPFile because if I use properties.Web.GetFile(szHttpUrl) and I for example do spFile.Length I get an error saying that the file does not yet exist. The goal here is to access the SPFile, to read the content, to modify the content, and to rename the file. – Paul Jan 10 '14 at 19:26
  • even more, the SPFile.Exist is FALSE in ItemAdding and if I enum the BeforeProperties it is empty and the AfterProperties only contains "vti_filesize" and "vti_parseversion" so I think doing things in ItemAdding is not doable. – Paul Jan 10 '14 at 19:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.