Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

Do you have any tips how can I create a new folder in a document library using listdata.svc (OData REST interface of SharePoint 2010) from JavaScript? SP creates a new file instead of a folder. I can create list items over OData without any problems, but this folder thing isn't documented at all. Thank you for your advices in advance.

I have an image gallery with folder creation enabled.

I tried to set the Path, ContentType (0x01010200B9CF3E8350E8024CB9921FDE096B5ACF), ContentTypeID fields of the new entity and added the slug request header, but it creates a file every time.

I can add list items in custom lists, but not a folder to document library.

share|improve this question
    
If you are able to get files uploaded, could you please respond to the question I posted on my answer? –  Robert Kaucher Jun 19 '13 at 16:25

5 Answers 5

This took forever to figure out, but of course it is simple once you got it.

Instead of pasting a bunch of code, here is the context and then the raw HTTP POST request that I ended up with.

The documentation is actually right here: http://msdn.microsoft.com/en-us/library/dd962796(v=office.12).aspx

Syntax for the slug header is as following:

/<LIST_PATH>/<FOLDERS>|<FOLDER_CONTENT_TYPE_ID>

So here is my SharePoint setup.

Document Library = "My Docs" (the Library Title)

  • Short Form: "MyDocs" (used by ListData.svc)

  • Path: "Docs" (used for slug and Path)

    The folder I want to create is "Folder 2" inside "Folder 1" (i.e. /Folder 1/Folder 2)

    URL:

    http://www.somewhere.com/_vti_bin/listdata.svc/MyDocs
    

    Method:

    POST
    

    header:

    slug: /Docs/Folder 1/Folder 2|0x01200093331D3790C54144AC10D65D164227C0
    

    body:

    {
      "ContentTypeID" : "0x01200093331D3790C54144AC10D65D164227C0",
      "ContentType" : "Folder",
      "Title" : "Folder 2",
      "Path" : "/Docs/Folder 1"
    }
    
  • share|improve this answer
        
    I wish I had more upvotes to give! Awesome work! –  Robert Kaucher Mar 20 at 1:05
    1  
    This should be the accepted answer--even though a while later it would be useful for later on; just saved me some SOAP headaches, thanks! –  Jeff Mar 26 at 19:00
        
    Good job! Indeed, this answer deserves to be accepted as answer! –  Vadim Gremyachev Aug 21 at 10:57

    Have you tried this approach:

    //Create Folder name MyFolder inside a doc library MyLib
    //Reference to Lists.asmx proxy
    ListsWebService.Lists listWebService = new ListsWebService.Lists();
    string xmlCommand;
    XmlDocument doc = new XmlDocument();
    xmlCommand = "<Method ID='1' Cmd='New'><Field Name='FSObjType'>1</Field><Field Name='BaseName'>MyFolder</Field> 
    <Field Name='ID'>New</Field>
    </Method>";
    XmlElement ele = doc.CreateElement("Batch");
    ele.SetAttribute("OnError", "Continue");
    ele.InnerXml = xmlCommand;
    listWebService.Credentials = System.Net.CredentialCache.DefaultCredentials;
    XmlNode node1 = listWebService.UpdateListItems("MyLib", ele);
    

    from here

    share|improve this answer
        
    Thank you Robert! Unfortunately this isn't the OData-capable listdata.svc, but the soap interface of SP. –  Robesz Jun 20 '13 at 6:57

    I have never been able to get this to work with the ListData.svc. I always get errors regarding slug headers or something else. For example sending a post to the Shared Documents URL with the following payload:

    {
       "ContentTypeID":"0x012000BBD736485259BF4582A1FE518D692108",
       "Name":"TestFolder2",
       "Title":"TestFolder2",
       "ContentType":"Folder"
    }
    

    Returns this error:

    {
       "error":{
          "code":"",
          "message":{
             "lang":"en-US",
             "value":"Invalid slug header for BLOBs. Slug headers must be server- or web-relative URL of the file. Server-relative URLs begins with a forward slash (\"/\")."
          }
       }
    }
    

    But since you are working in JavaScript you can do this easily using the Client Object Model:

    clientcontext = new SP.ClientContext.get_current();
    web = clientcontext.get_web();
    this.list = web.get_lists().getByTitle("LibraryName");
    var listItemCreationInfo = new SP.ListItemCreationInformation();
    listItemCreationInfo.set_underlyingObjectType(SP.FileSystemObjectType.folder);
    

    Code snip stolen from SharePointKings.

    If you can workout the slug headers and get this working, please post your findings. I gave up when trying to figure out how to add an attachment via ListData.svc.

    StackOverflow: http://stackoverflow.com/questions/17005819/how-to-use-the-html5-js-file-upload-api-to-upload-a-file-to-odata-service

    SP StackExchange: ListData.svc: How to upload attachment?

    Any project I do that uses ListData I always end up doing in a hybrid approach with JSOM. Some things are simpler using ListData others are easier using JSOM...

    share|improve this answer
        
    I used the same payload before, had the same slug header issue, but I added it to the request header. Which caused an other error message, but I added "slug" to the list of iis allowed headers and the content was created...but as a file, just like I told in the question. –  Robesz Jun 20 '13 at 7:01
        
    About your client object model snippet - I've never tried COM... I'm running my JavaScript file from mobile and external website from different domain. Is this available in this scenario or only for SharePoint-hosted pages? –  Robesz Jun 20 '13 at 7:11
        
    No, you would need to have access to SP.js and some other files as well as access to a hidden input called __REQUESTDIGEST used by the JSOM... I will be looking at this again this weekend, though, since you have provided me with some important details. –  Robert Kaucher Jun 21 '13 at 16:20
        
    Great, thanks! I left the office, but I check your solution on Monday, I'm very excited! –  Robesz Jun 21 '13 at 17:11
        
    I didn't succeed with JavaScript Object Model in a cross-domain setup, although I made a workaround that would be useful for others, too. We upload the files with metadata including the desired parent path and move the file from the temp directory to the folder passed as a metadata. Thanks for all your efforts, I really appreciate! –  Robesz Jun 27 '13 at 12:29

    I choosed to upload a document with metadata containing the parent folder and create the containing folder with a workflow. I have total control over the IIS of the SP 2010 foundation, so I was able to allow all the necessary request headers and domains to work in a cross-domain environment with basic auth (over https). I have a HTML5 client app with JayData library to consume the OData endpoint of SP (listdata.svc)

    <script src="scripts/jquery-1.9.1.min.js"></script>
    <script src="scripts/datajs-1.0.3.js"></script>
    <script src="scripts/jaydata.js"></script>
    
    
    var ctx = new MyPreGeneratedContext({
        name: 'oData',
        oDataServiceHost: 'https://mysharepoint.com/_vti_bin/listdata.svc',
        user: 'user',
        password: 'pass'
    });
    
    ctx.onReady(function () {
    
    var uploadFile = function (path, data, callback) {
        var request = {
            requestUri: ctx.storageProvider.providerConfiguration.oDataServiceHost + '/MyDestinationDocLibrary',
            method: 'POST',
            headers: {
                slug: path
            },
            body: data
        }
        ctx.storageProvider.appendBasicAuth(request, ctx.storageProvider.providerConfiguration.user, ctx.storageProvider.providerConfiguration.password);
    
        OData.request(request, function (resdata, response) {
    
            var entity = new ctx.MyDestinationDocLibrary.elementType(resdata, {
                converters: $data.oDataConverter.fromDb
            });
    
            callback(entity);
    
        },
        function () { alert(JSON.stringify(arguments)) });
    }
    
    uploadFile('/MyDestinationDocLibrary/testdoc.txt', 'filecontent', function (newFile) {
            console.log(newFolder.Owshiddenversion);
            ctx.MyDestinationDocLibrary.attach(newFile);
            newFile.ParentPath = 'Custom folder processed by the workflow";
            ctx.saveChanges({success: $data.debug, error: $data.debug});
        });
    
    });
    

    I guess this isn't the most elegant solution but this was the only one working in my scenario.

    share|improve this answer

    As Tommy pointed out in his answer and according to 3.1.4.3 Document:

    Inserting new documents to a document library involve sending a POST request containing the contents of the document to the EntitySet representing the document library. The protocol client MUST include the SLUG header (as specified in RFC5023 section 9.7) whose value is the name of the file that is being created in their POST requests.

    How to create Folder via REST in SharePoint 2010 using JavaScript

    function createFolder(webUrl,listName,folderName,folderPath, success, failure) {
    
        var folderPayload = {
          'ContentType': 'Folder',
          'Title' : folderName,
          'Path' : folderPath
        };
    
        $.ajax({
            url: webUrl + "/_vti_bin/listdata.svc/" + listName,
            type: "POST",
            contentType: "application/json;odata=verbose",
            data: JSON.stringify(folderPayload),
            headers: {
                "Accept": "application/json;odata=verbose",
                "Slug": folderPath + "/" + folderName + "|0x0120" 
            },
            success: function (data) {
                success(data.d);
            },
            error: function (data) {
                failure(data.responseJSON.error);
            }
        });
    }
    

    Examples:

    1 Create root folder named Orders in the Documents library

    createFolder('https://intranet.contoso.com','Documents','Orders', '/Shared Documents',function(folder){
        console.log('Folder ' + folder.Name + ' has been created succesfully'); 
      },
      function(error){
        console.log(JSON.stringify(error));
      }
    ); 
    

    2 Create sub folder named 2014 under the folder Orders in the Documents library

    createFolder('https://intranet.contoso.com','Documents','2014', '/Shared Documents/Orders',function(folder){
        console.log('Folder ' + folder.Name + ' has been created succesfully'); 
      },
      function(error){
        console.log(JSON.stringify(error));
      }
    ); 
    
    share|improve this answer

    Your Answer

     
    discard

    By posting your answer, you agree to the privacy policy and terms of service.

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