Create a SharePoint Document Library with Microsoft Graph - sharepoint

I'm trying to create a new document library in a SharePoint Teams site using Microsoft Graph.
var docLibrary = $#"{{ ""name"": ""{listName}"", ""list"": {{ ""template"": ""documentLibrary"" }} }}";
var res = await GraphClient.QueryGraphAsyncPost($"/groups/{groupId}/sites/root/lists/", docLibrary, user);
var result = await res.Content.ReadAsStringAsync();
This is the code that I'm using, but it is returning a bad request. I can't seem to find in the documentation the correct way to create a Document Library.

You'll want to specify the displayName instead of the name. The value of name is generated by the server, and so the 400 is an error saying it cannot be written to. You should see an error response that contains the following message:
Cannot define a 'name' for a list as it is assigned by the server. Instead, provide 'displayName'
If you change your request to the following it should work:
var docLibrary = $#"{{ ""displayName"": ""{listName}"", ""list"": {{ ""template"": ""documentLibrary"" }} }}";
var res = await GraphClient.QueryGraphAsyncPost($"/groups/{groupId}/sites/root/lists", docLibrary, user);
var result = await res.Content.ReadAsStringAsync();

Related

Finding role and script deployment relations im Netsuite

Is it possible to easily see which roles have access to which script deployments?
I tried making a script deployments saved search as well as a role saved search but could not really find out how to extract this information.
Does anyone know?
I cannot see a way to complete this in the UI/via saved search. You can complete this via suitescript however by following this sort of layout. You can schedule the script to run periodically, or just run in the browser console to get the data you want. You can also add code to create an excel file to easily digest the information...
Layout in SS2.0
//gather all applicable role ids
var Roles = [];
//gather all applicable script deployment ids
var ScriptDep = [];
//for each script deployment id get the "Roles" from the "Audience" tab in the UI
for (var i=0; i<ScriptDep.length; i++){
var script = record.load({
type: 'scriptdeployment',
id: ScriptDep[i]
});
var scriptAudienceField = script.getField({
fieldId: 'audslctrole'
});
var scriptAudience = scriptAudienceField.getSelectOptions({
filter : '*',
operator : 'contains'
});
var RoleID = ; //role ID you care about, maybe loop through all roles with Roles[j]
var test = scriptAudience.includes(RoleID); //returns true or false this deployment is deployed to this role
}
Suite Answer 86327 gives the dollowing SS1.0 sample code
var search = nlapiLoadSearch('scriptdeployment', 147); //load search of all script deployments
var resultSet = search.runSearch();
resultSet.forEachResult(function(searchResult){ //for each script deployment returned by the search, get the id
var record = nlapiLoadRecord('scriptdeployment', searchResult.id); //load the script deployemnt
var arrayOfRoles = record.getFieldValues('audslctrole'); //get the values of the "Roles" from the "Audience" tab in the UI
if(arrayOfRoles == '18'){ //change based on the internal ID of the role
console.log(searchResult.id);
};
return true;
});

Unable To Use Docusign API to populate a text field(with Number validation) in my template

I have a template in Docusign with a Text field with the following settings:
Data Label : 'Demolition'
Validation : Numbers
I try to use the Docusign Nodejs client to populate this field like so :
let demolition = docusign.Text.constructFromObject({
tabLabel: "Demolition", value: args.demolition});
let builderTabs = docusign.Tabs.constructFromObject({
numberTabs: [demolition]
});
I use numberTabs because using textTabs does not work and the link below suggests using numberTabs.
Docusign auto populate to tabs with data validation not working
But that does not work either.
This is the error I receive from Docusign when I use 'numberTabs'
text: '{\r\n "errorCode": "UNSPECIFIED_ERROR",\r\n "message": "Object reference not set to an instance of an object."\r\n}',
I just tested the following code and it worked (make sure you update the tabLabel to the same label you have in your template):
var envDef = new docusign.EnvelopeDefinition();
envDef.emailSubject = 'Please sign this document sent from Node SDK';
envDef.templateId = templateId;
// create a template role with a valid templateId and roleName and assign signer info
var tRole = new docusign.TemplateRole();
tRole.roleName = roleName;
tRole.name = 'Sally Doe';
tRole.email = 'sally#email.com';
tRole.tabs = new docusign.Tabs();
tRole.tabs.numberTabs = [];
var nTab = new docusign.Text();
nTab.tabLabel = "myLabel";
nTab.value = "123";
tRole.tabs.numberTabs.push(nTab);
// create a list of template roles and add our newly created role
var templateRolesList = [];
templateRolesList.push(tRole);
// assign template role(s) to the envelope
envDef.templateRoles = templateRolesList;
The right way to set a value for a tab that is defined in a template is to use a role object as Ergin shows in his answer.
You were trying to create a new Number tab. I believe there is a problem with the Node.js SDK that currently prevents it from creating Number tabs. (Number is a reserved work in Javascript and this is causing a problem.)

SearchExecutor (JSOM) did not retrieve values from Sharepoint online user profile

I'm trying to perform people search in SharePoint online user profile from Sharepoint hosted app but it returns no data.
I'm using the following code to do this:
clientContext = new SP.ClientContext.get_current();
// Building Keyword query for the search
var keywordQuery = new Microsoft.SharePoint.Client.Search.Query.KeywordQuery(clientContext);
keywordQuery.set_queryText("mohammed");
keywordQuery.set_sourceId("B09A7990-05EA-4AF9-81EF-EDFAB16C4E31");
keywordQuery.set_rowLimit(500);
keywordQuery.set_trimDuplicates(false);
var searchExecutor = new Microsoft.SharePoint.Client.Search.Query.SearchExecutor(clientContext);
results = searchExecutor.executeQuery(keywordQuery);
clientContext.executeQueryAsync(
function () {
alert(results.m_value);
},
function (err) {
alert("Error");
}
);
I'm trying to search user profile which contains "mohammed" text.
searchExecutor.executeQuery(keywordQuery) executes without any error but results.m_value returns 0. If I get value from results.m_value then I can move towards reading UserProfile properties using PeopleManager
Note: I've user as Mohammed Arief Kannubasha
Anyone please advice, thanks in advance
Try this
keywordQuery.set_queryText("mohammed*");

Paging in MS Graph API

Graph API Paging explains that the response would contain a field #odata.nextLink which would contain a skiptoken pointing to the next page of contents.
When I test the API, I'm getting a fully-qualified MS Graph URL which contains the skiptoken as a query param. E.g. Below is the value I got for the field #odata.nextLink in the response JSON.
https://graph.microsoft.com/v1.0/users?$top=25&$skiptoken=X%27445370740200001E3A757365723134406F33363561702E6F6E6D6963726F736F66742E636F6D29557365725F31363064343831382D343162382D343961372D383063642D653136636561303437343437001E3A7573657235407368616C696E692D746573742E31626F74322E696E666F29557365725F62666639356437612D333764632D343266652D386335632D373639616534303233396166B900000000000000000000%27
Is it safe to assume we'll always get the full URL and not just the skiptoken? Because if it's true, it helps avoid parsing the skiptoken and then concatenating it to the existing URL to form the full URL ourselves.
EDIT - Compared to MS Graph API, response obtained from Azure AD Graph API differs in that the JSON field #odata.nextLink contains only the skipToken and not the fully-qualified URL.
if you would like to have all users in single list, you can achieve that using the code that follows:
public static async Task<IEnumerable<User>> GetUsersAsync()
{
var graphClient = GetAuthenticatedClient();
List<User> allUsers = new List<User>();
var users = await graphClient.Users.Request().Top(998)
.Select("displayName,mail,givenName,surname,id")
.GetAsync();
while (users.Count > 0)
{
allUsers.AddRange(users);
if (users.NextPageRequest != null)
{
users = await users.NextPageRequest
.GetAsync();
}
else
{
break;
}
}
return allUsers;
}
I am using graph client library
Yes. In Microsoft Graph you can assume that you'll always get the fully qualified URL for the #odata.nextLink. You can simply use the next link to get the next page of results, and clients should treat the nextLink as opaque (which is described in both OData v4 and in the Microsoft REST API guidelines here: https://github.com/Microsoft/api-guidelines/blob/master/Guidelines.md#98-pagination.
This is different from AAD Graph API (which is not OData v4), which doesn't return the fully qualified next link, and means you need to do some more complicated manipulations to get the next page of results.
Hence Microsoft Graph should make this simpler for you.
Hope this helps,
The above code did not work for me without adding a call to 'CurrentPage' on the last line.
Sample taken from here.
var driveItems = new List<DriveItem>();
var driveItemsPage = await graphClient.Me.Drive.Root.Children.Request().GetAsync();
driveItems.AddRange(driveItemsPage.CurrentPage);
while (driveItemsPage.NextPageRequest != null)
{
driveItemsPage = await driveItemsPage.NextPageRequest.GetAsync();
driveItems.AddRange(driveItemsPage.CurrentPage);
}
I followed Tracy's answer and I was able to fetch all the messages at one go.
public List<Message> GetMessages()
{
var messages = new List<Message>();
var pages = Client.Users[_email]
.Messages
.Request(QueryOptions)
// Fetch the emails with attachments directly instead of downloading them later.
.Expand("attachments")
.GetAsync()
.Result;
messages.AddRange(pages.CurrentPage);
while (pages.NextPageRequest != null)
{
pages = pages.NextPageRequest.GetAsync().Result;
messages.AddRange(pages.CurrentPage);
}
return messages;
}

How can I check if a file is beeing edited (locked ?) using csom?

I am using sharepoint CSOM to download / upload file from a OneDriveBusiness account.
Before downloading the file I need to check if the file is currently in use.
File.CheckOutType is alway "None".
I though using File.LockedByUser property, using the following code, but I got a ServerObjectNullReferenceException when the file is not locked.
var listItem = clientDocs.GetItemById(item.Id);
clientContext.Load(listItem.File.LockedByUser);
clientContext.ExecuteQuery();
var locked = listItem.File.LockedByUser.UserId;
I was hoping to be able to do do something like :
if (file."locked")
{
throw exception...
}
enter code here
Any idea ?
Thanks !
File.LockedByUser property is a deferred property, it need to be requested explicitly as demonstrated below:
var list = ctx.Web.Lists.GetByTitle(listTitle);
var listItem = list.GetItemById(itemId);
ctx.Load(listItem, i => i.File.CheckOutType, i => i.File.CheckedOutByUser, i => i.File.LockedByUser);
ctx.ExecuteQuery();
if(listItem.File.CheckOutType != CheckOutType.None) //Is checked out?
{
var checkoutUserName = listItem.File.CheckedOutByUser.LoginName;
var lockedUserName = listItem.File.LockedByUser.LoginName;
}

Resources