1
votes

I am trying to create a custom action that can be chosen by right-clicking on a file in a any folder of a particular SharePoint Library. This custom action would copy the file into the same folder with the user's login name appended to the end of the file name.

I currently have an event receiver that will perform the custom action when a file is being updated but that's not when I want it to happen. I was able to add a custom action to the right-click file menu using SharePoint Designer but SharePoint Designer only lets the custom action trigger special SharePoint 2010 compatible workflows or load a web page. I need to make it so the event handler (or possibly a workflow) fires when the user chooses the custom action after right-clicking on the file. I'm not sure what approach or what kind of project or app I need to create in Visual Studio 2017 to get this functionality.

2

2 Answers

0
votes

Your custom action should call javascript function or perform GET request to your SharePoint hosted WCF or ASMX WebService.

  • ASMX

Official MSDN Walktrought: Creating a Custom ASP.NET Web Service

For additional resources with more screenshots check this blog post: Walkthrough: Creating a Custom ASP.NET (ASMX) Web Service in SharePoint 2010

  • WCF

Official Technet Walkthrough: SharePoint 2013: Create a Custom WCF REST Service Hosted in SharePoint and Deployed in a WSP

Note: with GET request you will need web.AllowUnsafeUpdate = true

With javascript u need AJAX call ie jQuery.ajax()

/edit

To hook up web service and your custom action use SharePoint Desinger, delete or change your existing custom action, change type to Navigate to URL and in the textbox type:

javascript: (function() { console.log('Testing...' + {ItemId}); /* your web service call */ })();

Use {ItemId} alias to pass proper item id to your AJAX call.

On the other hand, on web service side use SPWorkflowManager class to start a workflow on item. Check the code belowe (link):

public void StartWorkflow(SPListItem listItem, SPSite spSite, string wfName)  {
    SPList parentList = listItem.ParentList;
    SPWorkflowAssociationCollection associationCollection = parentList.WorkflowAssociations;
    foreach (SPWorkflowAssociation association in associationCollection)  {
      if (association.Name == wfName){
       association.AutoStartChange = true;
       association.AutoStartCreate = false;
       association.AssociationData = string.Empty;
       spSite.WorkflowManager.StartWorkflow(listItem, association,  association.AssociationData);
       }
     }
}
0
votes

I found a way to do this using JavaScript, without SharePoint Designer. I put the following script in a Content Editor web part on the page where the listview webpart is and now I can right click on a file and get the option to "Get My Copy". If you have a Comments sub folder, the renamed copy will get put there.

<script type="text/javascript">

// adds the menu option to Get My Copy
function Custom_AddDocLibMenuItems(m, ctx)
{
    var strDisplayText = "Get My Copy";                  //Menu Item Text
    var strAction = "copyFile()"; 
    var strImagePath = "";                               //Menu item Image path
    CAMOpt(m, strDisplayText, strAction, strImagePath);  // Add our new menu item
    CAMSep(m);                                           // add a separator to the menu
    return false;                                        // false means standard menu items should also be rendered
}

// append current user account to filename and copy to subfolder named Comments 
function copyFile()
{
    // get web and current user from context
    var context = new SP.ClientContext.get_current();
    var web = context.get_web();
    this.currentUser = web.get_currentUser();
    context.load(currentUser);

    // load the folder
    var currentFolder = decodeURIComponent(ctx.rootFolder);
    var folderSrc = web.getFolderByServerRelativeUrl(currentFolder); 
    context.load(folderSrc,'Files');

    context.executeQueryAsync(
        function() {            
            // get the first (and hopefully only) file in the folder
            var files = folderSrc.get_files();
            var e = files.getEnumerator();
            e.moveNext()    
            var file = e.get_current();

            // get user account
            var curUserAcct = currentUser.get_loginName();
            curUserAcct = curUserAcct.substring(curUserAcct.indexOf("\\") + 1); 

            // get file without extension
            var file_with_ext = file.get_name();            
            var name_without_ext = file_with_ext.substr(0, file_with_ext.lastIndexOf("."));

            var destLibUrl = currentFolder + "/Comments/" + name_without_ext + " " + curUserAcct + ".docx";     
            file.copyTo(destLibUrl, true);

            context.executeQueryAsync(
                function() { alert("Success! File File successfully copied to: " + destLibUrl); }, 
                function(sender, args) { alert("error: " + args.get_message()) }
            );
        }, 
        function(sender, args){ alert("Something went wrong with getting current user or getting current folder '" + currentFolder + "'. " + args.get_message()); }
    );
}

</script>