How do I populate the SharePointIds property on Drive and DriveItem objects? - microsoft-graph-api

Using the Graph API NuGet package, how do I populate the SharePointIds property.
Consider the following code snippet:
public async Task<Drive> RetrieveOneDriveForUserAsync(string userId)
{
return await _graphClient.Users[userId].Drive.Request().GetAsync();
}
The "SharepointIds" property is always NULL
EDIT:
NOTE: This is NOT for personal OneDrive items. This is for Group OneDrive items.
This is the documentation for the Drive object: https://learn.microsoft.com/en-us/graph/api/resources/drive?view=graph-rest-1.0
This is the documentation for the DriveItem object: https://learn.microsoft.com/en-us/graph/api/resources/driveitem?view=graph-rest-1.0
This is the documentation for the SharepointIds object: https://learn.microsoft.com/en-us/graph/api/resources/sharepointids?view=graph-rest-1.0

The SharePointIds object applies to an item stored in a SharePoint Site.
_graphClient.Users[userId].Drive.Items[itemId].Request().Select("sharepointids").GetAsync();
(Folders are an item, so you can get the Ids for Root.)
_graphClient.Users[userId].Drive.Root.Request().Select("sharepointids").GetAsync();

Related

Microsoft-Graph SDK for .NET is not returning odata.nextLink after upgrading from v1.19 to latest

When I make a request to Graph API I get in the response the "#odata.nextLink", if I use .NET SDK v1.19 I still get the value in the AdditionalData and there is also a NextPageRequest property which has an instance to make a request to the next page. But after upgrading to the latest version 4.53, using the same query I get the response with the NextPageRequest instance but not the "#odata.nextLink" in the AdditionalData.
I took a look at the release notes and there is nothing mentioning this change.
I could take the info from the NextPageRequest but I would like to understand what is actually happening here.
I found the official document to recommend using PageIterator for Paging, so I checked the source code for different version and I think this can answer your question in some terms. I mean this is recommended by Microsoft and the way it used to get next page value should explain something....
And this is what I found in SDK version
dynamic page = _currentPage;
// There are more pages ready to be paged.
if (page.NextPageRequest != null)
{
Nextlink = page.NextPageRequest.GetHttpRequestMessage().RequestUri.AbsoluteUri;
return true;
}
And this is what I see in V1.19
if (_currentPage.AdditionalData.TryGetValue("#odata.nextLink", out var value))
{
Nextlink = value as string;
return true;
}
I found the reason for this issue, commit: https://github.com/microsoftgraph/msgraph-sdk-dotnet/commit/834549348081869cc4b97d9ead6dbbf12a516264?diff=split class GraphServiceUsersCollectionResponse
[JsonPropertyName("#odata.nextLink")]
public string NextLink { get; set; }
The addition of the above property removed the odata.nextLink from the AdditionalData dictionary. This is an old commit, I'm not sure why this has not been reported as a breaking change.
I'm going to open a ticket directly to the project.

Using the search parameter on the /sites endpoint MSGraph .Net SDK

I've been trying to build a query to return all SPO sites in a tenant using MSGraph. I can do this in the Graph Explorer with the following query:
GET https://graph.microsoft.com/v1.0/sites?search=*
This MSdocs article seems to suggest that it's possible to use the search parameter but the C# example does not use search.
Has anyone been able to return all SPO sites in a tenant using the .Net SDK?
I'm using the following code to search for a site.
Add search as a query option in a request.
IGraphServiceClient client;
private async Task<Site> FindSiteAsync(string value)
{
var siteQueryOptions = new List<QueryOption>()
{
new QueryOption("search", value)
};
var sites = await client.Sites.Request(siteQueryOptions).GetAsync();
var site = sites.FirstOrDefault();
return site;
}

Working with Entity framework with Sitefinity and Portal Connector and Dynamic CRM

I'm working on a project that contains Dynamics CRM and Portal Connector which built upon Sitefinity.
There is a way to retrieve data inside Portal Connector from Dynamic CRM called Saved Query and this way generate a URL for you to retrieve data by HTTP request in front-end but I don't want to access it by the front end I want to access the Dynamics CRM by Backened, specifically by Entity framework, is it possible to connect to Dynamic CRM by Entity framework and retrieve the data by C# then send it to View?
My apologies for not coming across your post sooner.
A better way is to use the CRM connection provided by the Portal Connector. It essentially wraps the CRM SDK so calls you want make to the SDK can be made here and it uses the CRM connection configured in the site.
https://www.crmportalconnector.com/developer-network/documentation/developing-for-tpc/Dynamics-CRM-Connection-API
// Required usings
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using pavliks.PortalConnector.Crm.Connection;
// The Code
// Create an instance of the connection manager
CrmConnectionManager manager = new CrmConnectionManager();
// Use the Connection property of the manager to access the
// configured CRM connection and create a new account
Guid newId = manager.Connection.Create(new Entity("account")
{
Attributes = new AttributeCollection()
{
{"name", "My Account Name"}
}
});
// Create Query Expression
QueryExpression query = new QueryExpression("account")
{
ColumnSet = new ColumnSet(true),
};
// Use manager to query CRM
EntityCollection entities = manager.Connection.RetrieveMultiple(query);
All the required assemblies are already in the Sitefinity site bin folder as they come with the Portal Connector assemblies and are copied to that location with the Portal Connector during installation. If your code is in another project, either reference the assemblies in the Sitefinity project or add them from the Portal Connector deploy package to your project.
I know it's a bit late but I hope it helps you in your next portal project.
let me answer my question, in case anyone wants to do a similar thing in the future :
1- first thing connect to Dynamic CRM is not related to Portal Connector, so the area that you should search in is Dynamic CRM.
2- To connect to Dynamic CRM you should follow the below steps :
2.1- install this package "Microsoft.CrmSdk.XrmTooling.CoreAssembly"
2.2- find what is your connection string.
2.3 use below code
var service=new CrmServiceClient("AuthType=Office365;Url=https://ititisdf.crm4.dynamics.com;Password=1234" )/*put your connection string instead*/
3- Some example of you could create or retrieved data
service.Create(new Entity("account"){["name]="Test connection"}); // add record
// retrive data
//1- query expression
//var query= new QueryExpression().Criteria. <===== from here you can add filteration ... and so on
//2- fetch xml expression
//var query=new FetchExpression(#"fetch xml value"); // you need to use XrmToolBox to generate your fetchXml
//3- var query=new QueryByAttribute("account");
// query.AddAttributeValue("name","Test1");
var entities=service.RetrieveMultiple(query).Entities;
foreach(var entity in entities)
{
entity["name"];
}
var organization=new OrganizationServiceContext(service);
// below code is under a concept called late-bound
var result=(from account in organization.CreateQuery("account")
join contact in organization.CreateQuery("contact")
on account["primarcontactid"] equals contact["contactid"]
where account["gendercode"] == "test" AND account["industrycode"]=1
select new {
Name=account["name"],
ContactName=contact["fullname"]
}).ToList();
// to implement Early bound
1- go to XrmToolBox ==> About ==> Plugin Store ==> Early Bound Generator==>Early Bound Generator Page will opened choose Entity to skip and choose which entity to want to include and which want to exclude
===> choose the path of generated .cs class that will represent you Entity in your project ===> press on Create Entities ===> now copy the generated file .
Now you have something like Entity framework :
Just use Entity name as a normal class :
var account = new Account{Name="Ahmed"};
and instead of this :
organization.CreateQuery("account")
use
organization.CreateQuery<yourEntityName>()
Actually, I got all of this information from youtube serious related to Dynamic, and here is the link
note: this serious in the Arabic language for this reason I summarised the steps in this answer to make it helpful for all.

get count from oData enabled web api Get function

i have an oData enabled classic REST web api controller with a Get function like
[EnableQuery()]
public IQueryable<StoreCommand> Get()
{
return _storeCommandService.GetAllStoreCommands().AsQueryable();
}
i need to understand how i can make a call to get only the count of records using some url
i tried
http://localhost:9910/api/storeCommandsrest?$count
but i get
Message: "The query parameter '$count' is not supported."
please note that i am using MongoDb that is returning IQueryable of collection.
If you want to get only the count, try
http://localhost:9910/api/storeCommandsrest/$count

Custom DataService adapter saveChanges method to set entities to Unchanged

I've implemented a custom DataService adapter for BreezeJS - I wanted to use Breeze with a RESTful back end service (not OData or ASP.NET Web API).
So far - decent results after a learning curve.
I'm having an issue that when I call save changes - afterwards my entities on the client do not get marked as 'Unchanged'. They keep the same entityState.
I assume it has something to do with the success handler of the AJAX request to the backend service (looking at the source code to the WebAPI adapter):
success: function(data, textStatus, XHR) {
if (data.Error) {
// anticipatable errors on server - concurrency...
var err = createError(XHR);
err.message = data.Error;
deferred.reject(err);
} else {
// HACK: need to change the 'case' of properties in the saveResult
// but KeyMapping properties internally are still ucase. ugh...
var keyMappings = data.KeyMappings.map(function(km) {
var entityTypeName = MetadataStore.normalizeTypeName(km.EntityTypeName);
return { entityTypeName: entityTypeName, tempValue: km.TempValue, realValue: km.RealValue };
});
var saveResult = { entities: data.Entities, keyMappings: keyMappings, XHR: data.XHR };
deferred.resolve(saveResult);
}
},
It looks like the response includes an array of 'Entities'. What do these 'Entities' look like? It echoes what the client sent with an updated entityAspect.entityState value (server responses with 'Unchanged')?
Is that what should be passed into the deferred.resolve call?
I've got a working solution for this.
In a nutshell here's what is required for the object that is passed to the
deferred.resolve(saveResult);
Call in the success handler of the save change AJAX request.
Server response should include information about how to map from the client generated id to the server generated id (if the server generated one). This can be one keyMapping property returned in the response (like the Breeze API controller does) or what my service does is return a keyMapping property as a child property of a particular resource
The client code should create an array of objects that look like:
{ entityTypeName: "fully qualified entity type name",
tempValue: "client generated id",
realValue: "server generated id"
}
this array is the keyMappings property of the saveResult object
the entities property of the saveResult object is a flat list of all the entities that were modified from the server. Because of the design of my service API, it can return an entity, and child entities embedded in it, which I had to traverse and pull out into a flat list. Additionally these entity objects should be 'raw' and not include the entityAspect property or anything Breeze might interpret as a 'real' entity.
Also - something that can also be helpful is to look at the new sample from the Breeze folks - the MongoDB Breeze sample. They've implemented a custom dataServiceAdapter that hooks up their NodeJS/MongoDB backend. That provided some additional insight as well.
Good luck!

Resources