1

I am creating an SPFx solution to create folders with nested folders. This solution is working fine. but I want to attach some metadata to my folder. For this reason I have created a new folder content type and added few site columns to it. But I am not getting how to update the content type value while creating the folder. I am using below code for folder creation

private createFolder(folderUrl: string): Promise<any> {
    let customFolderCTId = "0x012000F1CF7BFF04CE7344891D1F19E91A18ED";
    const spOpts: ISPHttpClientOptions = {
      body: JSON.stringify({
        'ContentTypeId':customFolderCTId
      })
    };
    return (
      this.state.context.spHttpClient.post(folderUrl,SPHttpClient.configurations.v1,spOpts).then((r: SPHttpClientResponse) => {
        return r.json()
      }) as Promise<any>
    );
  }

Above code is giving me error as {"error":{"code":"-1, Microsoft.SharePoint.Client.InvalidClientQueryException","message":"The parameter ContentTypeId does not exist in method Add."}}

What is the resolution for this?

  • Can you share the folderUrl that you are using in your code ? – Gautam Sheth Oct 29 '18 at 14:21
  • let _folderUrl = clientCtx.pageContext.web.absoluteUrl + "/_api/web/folders/add('${libraryName}/${clientName}')"; – Mihir Oct 29 '18 at 15:12
  • Updating folder content type is available through REST api? – Mihir Oct 29 '18 at 15:18
1

You need to modify your existing endpoint include the details of the created folder by including select and expand OData operator as below:

"/_api/web/folders/add('${libraryName}/${clientName}')?
$select=ListItemAllFields/*&$expand=ListItemAllFields"

Once you do this, you can get the ID of the created folder item. After that, its a simple update operation to the list item.

The code will be somewhat as below:

let _folderUrl = this.context.pageContext.web.absoluteUrl + 
"/_api/web/folders/add(`${libraryName}/${clientName}`)?
$select=ListItemAllFields/*&$expand=ListItemAllFields";

const body: string = JSON.stringify({});

this.context.spHttpClient.post(_folderUrl,
  SPHttpClient.configurations.v1,
  {
    body: body
  }).then((response): Promise<void> => {
    return response.json();
  })
  .then((item): void => {

    console.log(item);

    // get the created folder item Id
    var itemId = item["ListItemAllFields"]["ID"];

    var folderItemUrl = this.context.pageContext.web.absoluteUrl + 
    "/_api/web/lists/getByTitle(`${libraryName}`)/items('" + itemId +"')";


    // use the list item entity type full name

    const updateBody: string = JSON.stringify({
      "__metadata": {"type":"SP.Data.`${libraryName}`Item"},
      "ContentTypeId":"0x012000F1CF7BFF04CE7344891D1F19E91A18ED"
    });

    this.context.spHttpClient.post(folderItemUrl,SPHttpClient.configurations.v1,{
      headers: {
        'Accept': 'application/json;odata=verbose',
        'Content-type': 'application/json;odata=verbose',
        'odata-version': '',
        'IF-MATCH': '*',
        'X-HTTP-Method': 'MERGE'
      },
      body:updateBody
    }).then(d =>{
      console.log("success updating folder content type");
    });


  }, (error: any): void => {
    console.log(error);
  });
  • Thanks for the update. I will try this and let you know. – Mihir Oct 29 '18 at 17:33
  • @Mihir - any update on this ? I tried it at my end was able to make it work :) – Gautam Sheth Nov 3 '18 at 20:04
0

The accepted answer here was tremendously helpful, but there are a lot of areas for improvement: it makes assumptions about the folder path and the type value (the one that starts with "SP.Data"), it fails to escape the values it inserts into the URLs, and it has a broken chain.

I've improved on these areas and also cleaned up the code a bit to break it down into more consumable chunks.

Disclaimer: I don't have an easy way to test this code, so it may contain some small mistakes. Please feel free to propose an edit if you find any.

const jsonOdataVerbose = 'application/json;odata=verbose';

const escapeParam = (value) => encodeURIComponent(value.replace(/'/g, "''"));

const listByTitle = (webUrl, listName) =>
    `${webUrl}/_api/web/lists/getbytitle('${escapeParam(listName)}')`;

function createFolder(context, library, folderName) {
    const webUrl = context.pageContext.web.absoluteUrl;        
    const requestUrl =
        `${listByTitle(webUrl, library)}/rootfolder/folders/add('${escapeParam(folderName)}')` +
        `?$select=ListItemAllFields/*&$expand=ListItemAllFields`;

    return context.spHttpClient.post(
        requestUrl,
        SPHttpClient.configurations.v1,
        {
            headers: {
                Accept: jsonOdataVerbose,
            },
        },
    ).then(response => response.json());
}

function setContentType(context, library, id, type, contentType) {
    const webUrl = context.pageContext.web.absoluteUrl;
    const requestUrl = 
        `${listByTitle(webUrl, library)}/items('${id}')`;
    const payload = {
        __metadata: { type },
        ContentTypeId: contentType
    };

    return context.spHttpClient.post(
        requestUrl,
        SPHttpClient.configurations.v1,
        {
            body: JSON.stringify(payload),
            headers: {
                Accept: jsonOdataVerbose,
                'Content-Type': jsonOdataVerbose,
                'IF-MATCH': '*',
                'X-HTTP-Method': 'MERGE',
            },
        },
    );
}


// put it all together
createFolder(this.context, libraryName, clientName)
    .then(item => setContentType(
        this.context,
        libraryName,
        item['ListItemAllFields']['ID'],
        item['ListItemAllFields']['__metadata']['type'],
        '0x012000F1CF7BFF04CE7344891D1F19E91A18ED'
    ))
    .catch(error => console.error(error));

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.