10
votes

I have a console app written in C#. I need to get some of the information from a SharePoint site. This instance of SharePoint is part of Office 365 (i.e. SharePoint Online).

My challenge is, I can't use the helper library. I have to use the REST-based APIs since I'm using .NET Core.

To begin, I registered my console app with Azure Active Directory. This console app is created in the same Azure Active Directory that my Office 365 environment is part of. I've also granted the "Read items in all site collections" delegated permission for the "Office 365 SharePoint Online" API to my console app.

In my situation, I have a console app sitting on a server. I've set up a test user with a username/password on my SharePoint tenant. I also have the Client ID for the console app I registered with Azure Active Directory and a Redirect URL.

At this time, I have some code that looks like this:

var accessToken = await GetToken(); // retrieves a token from Active Directory
using(var client = new HttpClient()) {
    client
        .DefaultRequestHeaders
        .Clear();

    client
        .DefaultRequestHeaders
        .Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    client
        .DefaultRequestHeaders
        .Accept
        .Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var apiUrl = "https://[mySite].sharepoint.com/_api/web";

    // how do I get the title of the site at the apiUrl variable?
}

I feel like I'm close since I'm getting an access token. I just can't seem to figure out how to get the title of the site. How do I get the title of a SharePoint Site from my C# code?

3
There are some decent answers below, could you supply us with the code you’re using to actually get the token? Depending on the kind of app registration you might need some other way on how to get the token. By the way Microsoft is using JWT tokens everywhere now, and they contain info about for what they are valid for. Just paste them at jwt.ioStephan

3 Answers

2
votes

The SharePoint REST API's web resource includes a Title property that represents the title for the Web site.

Calling:

GET http://<site url>/_api/web/title

Returns:

<d:Title xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" 
    xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" 
    xmlns:georss="http://www.georss.org/georss" 
    xmlns:gml="http://www.opengis.net/gml">Site Title Goes Here</d:Title>

or, assuming you've set the Accept header to application/json:

{
  "odata.metadata": 
  "https://microsoft.sharepoint.com/sites/msw/_api/$metadata#Edm.String",
  "value": "MSW"
}
1
votes

Just realised you're using SharePoint API instead of Graph API, it still might be useful for you though!

This is the JSON setup, you don't need it but it will make deserialization easier

public class SharePointSiteObject
{
    [JsonProperty("createdDateTime")]
    public string CreatedDate { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("id")]
    public string ID { get; set; }

    [JsonProperty("lastModifiedDateTime")]
    public string LastModified { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("webUrl")]
    public string WebUrl { get; set; }

    [JsonProperty("displayName")]
    public string DisplayName { get; set; }

    [JsonProperty("createdBy")]
    public user CreatedBy { get; set; }

    [JsonProperty("lastModifiedBy")]
    public user ModifiedBy { get; set; }
}

code to deserialize the returned JSON

public static SharePointSiteObject SharePointDeserialize(string jObject)
{
    SharePointSiteObject sharePointSite;

    sharePointSite = JsonConvert.DeserializeObject<SharePointSiteObject>(jObject);

    return sharePointSite;
}

Universal method to query the Graph API, feed it the endpoint and a token

public static async Task<string> Run(string url, string token)
{

    var httpClient = new HttpClient();
    HttpResponseMessage response;
    try {
        var request = new HttpRequestMessage(HttpMethod.Get, url);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
        response = await httpClient.SendAsync(request);
        var content = await response.Content.ReadAsStringAsync();
        return content;
    }
    catch (Exception ex) {
        return ex.ToString();
    }
}

use the below code where you want to call the graph API and display the SharePoint site name

string url = "https://graph.microsoft.com/v1.0/sites/" + sharePointID;
string token = await GetToken();
var request = await Run(url, token);
var result = SharePointDeserialize(request);
Console.WriteLine(result.DisplayName);

You should try out the MS Graph Explorer, it's super useful: https://developer.microsoft.com/en-us/graph/graph-explorer

1
votes

SharePoint endpoints follow the OData convention.

So, you can use $select query options to specify the data that you want for a given web or list or fields etc.

So, in your case, you can simply modify your endpoint as below:

var apiUrl = "https://[mySite].sharepoint.com/_api/web?$select=Title";

In case, you want to get additional properties like description, logo, Webtemplate etc. you can append it as:

var apiUrl = "https://[mySite].sharepoint.com/_api/web?$select=Title,Description,
SiteLogoUrl,WebTemplate";

Reference - List of properties in SPO - Web object

Also, ensure that you have Have full control of all site collections permissions checked in the Office 365 SharePoint Online permission as below:

enter image description here

Fuller version of the code that I am using:

1) Create AuthenticationResponse.cs class:

public class AuthenticationResponse
{
        public string token_type { get; set; }
        public string scope { get; set; }
        public int expires_in { get; set; }
        public int expires_on { get; set; }
        public int not_before { get; set; }
        public string resource { get; set; }
        public string access_token { get; set; }
        public string refresh_token { get; set; }
        public string id_token { get; set; }
}

2) Use that in your code as below:

string userName = "[email protected]";
string password = "password";

List<KeyValuePair<string, string>> vals = new List<KeyValuePair<string, string>>();

string tenantName = "tenantName.OnMicrosoft.com";
string authString = "https://login.microsoftonline.com/" + tenantName;
string resource = "https://graph.microsoft.com";

AuthenticationContext authenticationContext = new AuthenticationContext(authString, false);

string clientId = "<client-id>";
string key = "<client-secret>";

vals.Add(new KeyValuePair<string, string>("client_id", clientId));
vals.Add(new KeyValuePair<string, string>("resource", resource));
vals.Add(new KeyValuePair<string, string>("username", userName));
vals.Add(new KeyValuePair<string, string>("password", password));
vals.Add(new KeyValuePair<string, string>("grant_type", "password"));
vals.Add(new KeyValuePair<string, string>("client_secret", key));

string url = string.Format("https://login.windows.net/{0}/oauth2/token", tenantName);

using (HttpClient httpClient = new HttpClient())
{
    httpClient.DefaultRequestHeaders.Add("Cache-Control", "no-cache");
    HttpContent content = new FormUrlEncodedContent(vals);
    HttpResponseMessage hrm = httpClient.PostAsync(url, content).Result;

    AuthenticationResponse authenticationResponse = null;
    if (hrm.IsSuccessStatusCode)
    {
        Stream data = await hrm.Content.ReadAsStreamAsync();
        DataContractJsonSerializer serializer = new
        DataContractJsonSerializer(typeof(AuthenticationResponse));
        authenticationResponse = (AuthenticationResponse)serializer.ReadObject(data);

        var accessToken = authenticationResponse.access_token;

        httpClient
        .DefaultRequestHeaders
        .Clear();

        httpClient
            .DefaultRequestHeaders
            .Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

        httpClient
            .DefaultRequestHeaders
            .Accept
            .Add(new MediaTypeWithQualityHeaderValue("application/json"));

        var apiUrl = "https://[mySite].sharepoint.com/_api/web?$select=Title";      

    }
}