Frage

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?

War es hilfreich?

Lösung

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);
  });

Andere Tipps

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));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit sharepoint.stackexchange
scroll top