Estoy tratando de obtener la lista de elementos de una lista de sharepoint a través de Microsoft Graph. Este es el método que estoy usando para obtener el token de la aplicación:

    public async Task<string> GetAppToken(string tenantId, string clientId, string clientSecret)
    {
        var host = "https://login.microsoftonline.com";
        var tokenUri = $"/{tenantId}/oauth2/v2.0/token";
        var contentType = "application/x-www-form-urlencoded";

        var requestedResource = "https%3A%2F%2Fgraph.microsoft.com%2F.default";//&resource=https%3A%2F%2Fgraph.microsoft.com%2F.default
        var request = $"grant_type=client_credentials&client_id={clientId}&client_secret={clientSecret}&scope={requestedResource}";
        var resultContent = "fail";
        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(host);
            var content = new StringContent(request, Encoding.UTF8, contentType);

            var result = await client.PostAsync(tokenUri, content);
            resultContent = await result.Content.ReadAsStringAsync();

        }
        var json = JsonConvert.DeserializeObject<dynamic>(resultContent);
        return json.access_token;
    }

El token de acceso devuelto contiene estos roles:

"Mail.ReadWrite",
"Device.ReadWrite.All",
"User.ReadWrite.All",
"Domain.ReadWrite.All",
"Calendars.Read",
"Group.Read.All",
"Directory.ReadWrite.All",
"MailboxSettings.Read",
"Contacts.ReadWrite",
"Group.ReadWrite.All",
"Notes.Read.All",
"User.Invite.All",
"Files.ReadWrite.All",
"Directory.Read.All",
"User.Read.All",
"Files.Read.All",
"Mail.Read",
"Calendars.ReadWrite",
"Mail.Send",
"MailboxSettings.ReadWrite",
"Contacts.Read",
"IdentityRiskEvent.Read.All",
"Member.Read.Hidden",
"Reports.Read.All",
"Notes.ReadWrite.All"

Este es el código que estoy usando para hacer la solicitud:

token = await GetAppToken();
var client = new HttpClient();
var queryString = new NameValueCollection();
client.DefaultRequestHeaders.Authorization
    = new AuthenticationHeaderValue("Bearer", token);

var uri = $"https://graph.microsoft.com/beta";
var path = $"/sites/{siteId}/lists/{listId}/items";

var responseString = string.Empty;
try
{

    var response = await client.GetAsync($"{uri}{path}");
    if (response.Content != null)
    {
        responseString = await response.Content.ReadAsStringAsync();
        Console.WriteLine(responseString);
    }

}
catch (Exception ex)
{
    Console.Write(ex.ToString());
}

Esta url funciona para producir una respuesta:

> var path =
> "/sites/[sitecol-guid],[site-guid]/lists/[list-guid]/items";  

Pero la colección de valores está vacía a pesar de que hay elementos en la lista. Este es el resultado real de json:

{
    "@odata.context":"graph.microsoft.com/beta/$metadata#sites(‌​'host, site-id')/lists('list-id')/items",
    "value":[]
} 

También probé este formato para la solicitud de lista:

var path = "https://graph.microsoft.com/beta/sharepoint:/{list-path}"  

Esto produjo una respuesta json válida que detalla la información de la lista, pero cuando agregué el segmento / items, recibí este error:

"Recurso no encontrado para el segmento 'artículos'",

¿Qué me estoy perdiendo?

5
Irwin 3 may. 2017 a las 14:55

3 respuestas

La mejor respuesta

Esto es algo que me ha tomado un tiempo entender de los documentos.

En primer lugar, no haga nada programáticamente hasta que lo tenga funcionando en Microsoft Graph Explorer: es solo una gran pérdida de tiempo.

En segundo lugar, la versión beta no está lista para su sistema de producción, por lo que si bien funciona bien, no confíe en ella, en su lugar use la v1.0 de las API REST.

Si conoce la ID de su sitio y lista, todas las URL comenzarán con uno de los siguientes:

https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{listId}/
https://graph.microsoft.com/beta/sites/{siteId}/lists/{listId}/

Nota: En los ejemplos a continuación, doy la URL genérica, luego una del mundo real que funcionó para mí, para que pueda ver cómo se ve el formato.

Si no conoce el listId, digamos que estamos viendo listas en el sitio raíz, podemos obtenerlas usando esta URL en Microsoft Graph Explorer y haga clic en Ejecutar consulta :

https://graph.microsoft.com/v1.0/sites/{siteId}/lists
https://graph.microsoft.com/v1.0/sites/root/lists

Si desea obtener todas las columnas en su lista, pegue esta URL en el Microsoft Graph Explorer y haga clic en Ejecutar consulta

https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{listId}/columns
https://graph.microsoft.com/v1.0/sites/root/lists/ff34268a-d9ff-49c0-99a9-75c6b2eee62e/columns

Esto devuelve algo similar a:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('root')/lists('ff34268a-d9ff-49c0-99a9-75c6b2eee62e')/columns",
    "value": [
        {
            "columnGroup": "Custom Columns",
            "description": "",
            "displayName": "Title",
            "enforceUniqueValues": false,
            "hidden": false,
            "id": "fa564e0f-0c70-4ab9-b863-0177e6ddd247",
            "indexed": false,
            "name": "Title",
            "readOnly": false,
            "required": true,
            "text": {
                "allowMultipleLines": false,
                "appendChangesToExistingText": false,
                "linesForEditing": 0,
                "maxLength": 255
            }
        },
        ...
    ]
}   

Para obtener el valor de lo que está en su lista, use esto:

https://graph.microsoft.com/v1.0/sites/{siteId}/lists/{listId}/items?expand=fields
https://graph.microsoft.com/v1.0/sites/root/lists/ff34268a-d9ff-49c0-99a9-75c6b2eee62e/items?expand=fields

Tenga en cuenta la consulta expand=fields que realmente agrega los valores de los elementos en su lista

Esto devuelve algo similar a:

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('root')/lists('ff34268a-d9ff-49c0-99a9-75c6b2eee62e')/items",
    "value": [
        {
            "@odata.etag": "\"6a84a626-dae9-40eb-9c6d-899c6a05ffa8,3\"",
            "createdDateTime": "2017-01-03T11:11:42Z",
            "eTag": "\"6a84a626-dae9-40eb-9c6d-899c6a05ffa8,3\"",
            "id": "1",
            "lastModifiedDateTime": "2017-01-10T18:24:58Z",
            "webUrl": "https://myexample.sharepoint.com/Lists/Some%20Contacts/1_.000",
            "createdBy": {
                "user": {
                    ...
                }
            },
            "lastModifiedBy": {
                "user": {
                    ...
                }
            },
            "parentReference": {},
            "contentType": {
                "id": "0x010062202D579C40994CA18FDBA6760B9545"
            },
            "fields@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('root')/lists('ff34268a-d9ff-49c0-99a9-75c6b2eee62e')/items('1')/fields/$entity",
            "fields": {
                "@odata.etag": "\"6a84a626-dae9-40eb-9c6d-899c6a05ffa8,3\"",
                "Title": "Dr",
                "First_x0020_Name": "David",
                "Surname": "Simpson",
                "Location": "Nottingham",
                "First_x0020_Created": "2017-01-03T08:00:00Z",
                "Age@odata.type": "#Single",
                "Age": 25,
                "id": "1",
                "ContentType": "Item",
                "Modified": "2017-01-10T18:24:58Z",
                "Created": "2017-01-03T11:11:42Z",
                "AuthorLookupId": "11",
                "EditorLookupId": "11",
                "_UIVersionString": "1.0",
                "Attachments": false,
                "Edit": "",
                "LinkTitleNoMenu": "Dr",
                "LinkTitle": "Dr",
                "ItemChildCount": "0",
                "FolderChildCount": "0",
                "_ComplianceFlags": "",
                "_ComplianceTag": "",
                "_ComplianceTagWrittenTime": "",
                "_ComplianceTagUserId": ""
            }
        },
        ...
    ]
}   

Aunque estoy usando v1.0 del gráfico, la versión beta funciona igual.

En mi aplicación real, estoy usando offline_access Sites.ReadWrite.All como el alcance para el baile OAuth. El primero permite la actualización de tokens; este último para acceder a SharePoint Online en Microsoft Graph.

Su URL de autorización debería verse así:

https://login.microsoftonline.com/common/oauth2/v2.0/authorize
    ?client_id=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX
    &response_type=code
    &redirect_uri=https%3A%2F%example.ngrok.io%2Foauth2%2Fcallback
    &response_mode=query
    &scope=offline_access+openid+Sites.ReadWrite.All
    &prompt=consent

Un aparte: asegúrese de estar utilizando la API de Microsoft Graph (en https: // graph. microsoft.com/) en lugar de la API de Azure AD Graph (en https://graph.windows.net /). Si coloca el alcance incorrecto en su baile OAuth, sucederán cosas malas.

Una cosa buena acerca del uso de la API de Microsoft Graph es que no tiene que molestarse en agregar ningún permiso en el portal de Azure de antemano, porque solo puede agregar los permisos en el ámbito de OAuth y volver a realizar la autorización. Esto es mucho más fácil

4
dvdsmpsn 6 feb. 2019 a las 14:34

Como se menciona en los comentarios, se perdió un paso importante que era Grant Permissions, que básicamente es el consentimiento del administrador.

Este consentimiento es necesario para los permisos de aplicaciones que siempre requieren el consentimiento del administrador. Si la aplicación tiene permisos delegados, entonces antes del Grant permissions puede dar consentimiento de manera efectiva en nombre de todos los usuarios y, una vez hecho, suprimirá el mensaje para los usuarios>

Como se menciona en este blog (descargo de responsabilidad, mi propio blog) - Consuma la API Graph y cree grupos O365 / sitios de equipos modernos con CSOM C #, necesitamos Grant permissions una vez que hayamos otorgado y guardado los permisos necesarios para la aplicación.

Referencia: Configure el consentimiento del usuario

-1
Gautam Sheth 6 feb. 2019 a las 06:13

Asegúrese de otorgar su consentimiento de administrador. Aquí hay un ejemplo de ello.

https://login.microsoftonline.com/ {tenant ID} / adminconsent? client_id = {client id} & state = 12345 & redirect_uri = http: // localhost

-1
f1365 28 ago. 2018 a las 00:56