1

The scenario:

Content Organizer enabled, Drop Off Library has a bunch of custom content types as well as the default "Document" content type (library default is set to "Document").

Multiple users are allowed to upload docs, but are instructed to leave the default Document content type (with no rules attached), so that a "librarian" user can come through, edit the docs, change to the correct content type, fill out the metadata, and have the docs routed where they need to go.

Users discover that if they drag and drop multiple files, all the files remain checked out to the uploader, so the librarian can't see them and make the necessary changes. So, they ask me to set it up so files are automatically checked in.

Item Added event receiver, check in files, Bob's your uncle.

But now (and I tried to warn them of this), if someone tries to add a single file using the "new document" link or one of the Ribbon buttons, of course the usual SharePoint behavior kicks in and they are presented with the Edit form to fill out metadata, and even if they don't do anything, once they hit save, the event receiver has fired and checked in the file, and they are presented with an error message saying they can't make changes because the file is not checked out to them.

So.... is there any way I can tell from my event receiver code if the upload method was drag and drop, so that I can only auto-check-in docs that were dropped in, and leave the other ones so that the regular SharePoint Edit form will work correctly?

1

The easiest and by far only way to differentiate dropped vs uploaded is based on "Metadata" values.

  • Create a "Mandatory" field and check for the value in event receiver before proceeding your action. (i.e. Whether or not user drag & drop or perform a proper upload they need to fill this mandatory column to proceed further).
  • If possible think about disabling drag & drop option so that user has no other choice than a default upload, in this way we are enforcing them to fill the "Metadata" using below code in CEWP.

    ExecuteOrDelayUntilScriptLoaded(function() {
        g_uploadType = DragDropMode.NOTSUPPORTED;
        SPDragDropManager.DragDropMode = DragDropMode.NOTSUPPORTED;
    }, "DragDrop.js");
    

Note: Still user can open explore view to upload files. consider disabling that based on your need:

  • To disable for entire WebAppliction: Go to Central Admin->Choose your webapplication->Select User Permissions->look for 'Use Remote Interfaces' anddisable it.

  • CSS hack to hide this option only for the specific library: Go to the respective library default view and add a CEWP and this CSS to hide it #Ribbon.Library.Actions.OpenWithExplorer-Medium{display:none;}

  • Thanks for your response. Disabling drag-and-drop or Explorer view is not an option, because they definitely want to be able to bulk upload files. Creating an arbitrary mandatory field just for the purposes of being a flag to check to see if it was drag-and-drop won't really work, because the Item Added event receiver will fire before the user has the chance to fill out and save the form. – Dylan Cristy Jan 4 '18 at 22:52
  • ok, Metadata is our only key to find it. and just to clarify.. you don't have to create a new column to verify it can even be "Title" or any other column in that item. Also, wanted to check even the event receiver fires early we can cancel the commit with our custom condition properties.Status = SPEventReceiverStatus.CancelNoError; properties.Cancel = true; and create an "item updated" event receiver to verify and do the final check-in – little_big_thoughts Jan 4 '18 at 23:17
0

This is not exact answer but a hint(workaround) for your reference.

Take SharePoint 2013 as example, when user dragdrop a file to library, the UploadFinishFunc(either success or fail) will be triggered(we could get the function definition from dragdrop.debug.js). So you could extend/override this function to check in the file by JSOM.

Sample script to extend this function.

SP.File methods

<script type="text/javascript">
        ExecuteOrDelayUntilScriptLoaded(CustomizedragdropUpload, "dragdrop.js");
        function CustomizedragdropUpload() {
            var _UploadFinishFunc = UploadFinishFunc;
            UploadFinishFunc =
                function UploadFinishFunc(element, state) {
                    if (typeof g_currentControl.postUploadFunc == 'function' && state.status != UploadStatus.CANCELLED)
                        g_currentControl.postUploadFunc(state.files);
                    g_currentControl.status = ControlStatus.UPLOADED;
                    UpdateProgressBar(ProgressMessage.UPLOADED, state);
                    RefreshResult(state);
                    g_currentControl.status = ControlStatus.IDLE;
                    alert('to do:check in file ' + state.files[0].fileName);
                    var clientContext = SP.ClientContext.get_current();
                    var list = clientContext.get_web().get_lists().getById(_spPageContextInfo.pageListId);
                    var camlQuery = new SP.CamlQuery();
                    camlQuery.set_viewXml(
                                          "<View><Query>" +
                                              "<Where><Eq><FieldRef Name='FileLeafRef' /><Value Type='File'>" + state.files[0].fileName + "</Value></Eq></Where>" +
                                              "<OrderBy><FieldRef Name='Created' Ascending='False' /></OrderBy>" +
                                              "<RowLimit>1</RowLimit>" +
                                           "</Query></View>");
                    var collListItem = list.getItems(camlQuery);
                    clientContext.load(collListItem, 'Include(Id)');
                    clientContext.executeQueryAsync(
                    Function.createDelegate(this,
                    function () {
                        var listItemInfo = '';
                        var listItemEnumerator = collListItem.getEnumerator();
                        while (listItemEnumerator.moveNext()) {
                            var oListItem = listItemEnumerator.get_current();
                            var file = oListItem.get_file();

                            clientContext.load(file);
                            clientContext.executeQueryAsync(
                            Function.createDelegate(this,
                            function () {
                                alert(file.get_name());
                                //check in
                            }),
                            Function.createDelegate(this,
                            function (sender, args) {
                                //
                            }));
                        }
                        //check in
                    }),
                    Function.createDelegate(this,
                    function (sender, args) {
                        //
                    }));

                }
        }
    </script>
  • Interesting, I think I understand where you are going with this. You are saying, instead of using an event receiver to check in files (which can't tell if it was drag-drop or not), use some client side code that can hook in to functions that only run on drag-drop, therefore isolating the drag-drop behavior and doing the automatic check-in only in that case. That could definitely work, but can you please explain what happens in the case of multiple files being dropped at the same time? Will UploadFinishFunc be triggered once for every file, or is there something else that needs to be... – Dylan Cristy Jan 5 '18 at 14:22
  • ...done to determine if multiple files were drag-dropped at the same time? – Dylan Cristy Jan 5 '18 at 14:23

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.