Domanda

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?

È stato utile?

Soluzione

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

Altri suggerimenti

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));
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a sharepoint.stackexchange
scroll top