Tag Archives: O365

How to use Microsoft Graph to get office groups listed in a native (Console) application

To get groups from using Microsoft Graph you have to do the following things:

  • Register an application using Azure AD and give required privileges to the application
  • Request a token for your application using the client ID and client secret key
  • Make the API call to using REST by specifying that your realm where to get the groups from

Register your application through Azure AD

Go to https://portal.azure.com/ or https://manage.windowsazure.com

Next from the Azure navigation go to your active directory. Next you should see different options in the top area of the your AAD, such as:

Users, Groups, Applications, Domain and so on.

Select the Applications section.

aad1

Next you should get a listing of applications configured in your AAD.

Next from the AAD UI select ADD to add a new application.

aad2

Select what type of an application it is. You can use both option. I used the configurations of an MVC application which allowed me to work just fine. What matters is the client ID, client secret key and the privileges. The redirect URL is not necessary for a Native Application, you can type in anything as long as it is a URL.

aad4aad5

 

After your application is created go to the configure section.

aad6

Here find the client ID and copy store it somewhere to be used later.

Then go to the keys section and add a new key(client secret)

aad7

Then scroll down and go the applications section and add the Microsoft Graph application and select the needed privileges. In this case, you would like at least to be able to read groups.

aad8aad9

That is it, next is some code.

Request a token for your application

This is the piece of code that will get the token from your application. The constants and parameters will be explained soon.

public static string GetTokenForApplication(String realm, String clientId, String clientSecret)
 {
 AuthenticationContext authenticationContext = new AuthenticationContext(Constants.UnifiedApiConnect.AzureADAuthority + realm, false);
 // Config for OAuth client credentials 
 ClientCredential clientCred = new ClientCredential(clientId, clientSecret);

 AuthenticationResult authenticationResult = authenticationContext.AcquireToken(Constants.UnifiedApiConnect.O365UnifiedAPIResource,
 clientCred);
 string token = authenticationResult.AccessToken;
 return token;
 }

Make the API Call to get the groups

This is the code that will get the token and request data from the Graph API


TokenHelper.Token = Program.GetTokenForApplication(realm, clientId, clientSecret);
 List<Group> groups = new List<Group>();
 string APIURL = Constants.UnifiedApiConnect.O365UnifiedAPIResource + "v1.0/" + realm + "/groups?$filter=groupTypes/any(c:c+eq+'Unified')";
 try
 {
 groups = GroupsHttpHelper.GetGroups(APIURL);
 foreach (var group in groups)
 {
 groupsSite.Add(new SiteDirectoryEntity() { Title = group.displayName, URL = String.Format(Program.O365OutlookMailGroupURL, realm, realmLCID, group.mail) });
 }
 }
 catch (Exception ex)
 {
 Logger.Error("Error in processing O365 groups through MS Graph: " + ex.Message + "\n" + ex.StackTrace);
 }

This is the code that will do the request to the Graph API, notice that the data is deserialized into objects.

 


public class GroupsHttpHelper
 {
 public static List<Group> GetGroups(string apiUrl)
 {
 if (String.IsNullOrEmpty(apiUrl)) { throw new ArgumentNullException("apiUrl"); }

 List<Group> groups = new List<Group>();

 string responseContent = GroupsHttpHelper.GetHttpResource(apiUrl);
 var responseObject = JsonConvert.DeserializeObject<GraphResponse<Group>>(responseContent);
 foreach (var item in responseObject.value)
 {
 groups.Add(item);
 }

 return groups;

 }

 public static string GetHttpResource(string url)
 {
 string responseContent = String.Empty;

 string token = TokenHelper.Token;

 var request = (HttpWebRequest)HttpWebRequest.Create(url);

 request.Method = "GET";
 request.Accept = "application/json";
 request.Headers.Add("Authorization", "Bearer " + token);

 var response = request.GetResponse();
 using (var reader = new StreamReader(response.GetResponseStream()))
 {
 responseContent = reader.ReadToEnd();
 }

 return responseContent;
 }
 }

public class Group
 {
 public string accessType { get; set; }

 public bool? allowExternalSenders { get; set; }

 public bool? autoSubscribeNewMembers { get; set; }
 public string description { get; set; }
 public string displayName { get; set; }
 public string[] groupTypes { get; set; }
 public string id { get; set; } // identifier

 public bool isSubscribedByMail { get; set; }
 public string mail { get; set; }

 public bool? mailEnabled { get; set; }
 public string mailNickname { get; set; }
 public string onPremisesLastSyncDateTime { get; set; } //timestamp
 public string onPremisesSecurityIdentifier { get; set; }

 public bool? onPremisesSyncEnabled { get; set; }
 public string[] proxyAddresses { get; set; }

 public bool? securityEnabled { get; set; }
 public int unseenCount { get; set; }
 public string visibility { get; set; }
 }

Namespaces needed in the code:

using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Newtonsoft.Json;

NuGet Packages needed:

Active Directory Authentication Library – Id: Microsoft.IdentityModel.Clients.ActiveDirectory
Json.NET – Id: Newtonsoft.Json

WebConfig Values and parameters in the code

 

<add key=”MSGraphGourps_Realm” value=”yourrealm.com” />

<add key=”ClientId” value=”your client ID in the Azure AD application” />
<add key=”ClientSecret” value=”your client secret key in the Azure AD application” />

The URL format for the authentication context request is something like this: https://login.microsoftonline.com/yourrealm.com

To acquire the token: https://graph.microsoft.com/

To get the groups the URL is: https://graph.microsoft.com/1.0/yourrealm.com/groups

If you are not sure where to get your realm from there are two ways:

  1. Get it from the URL in your browser bar when you are viewing an O365 outlook mail box or group: https://outlook.office.com/owa/?realm=yourrealm.com
  2. The other option is to use the Azure Management UI and again in the url your should find it: https://manage.windowsazure.com/yourrealm.com

 

Getting other information from Groups

One Drive:

https://graph.microsoft.com/v1.0/your realm name/groups/{your group guid}/drive/root

Owners:

https://graph.microsoft.com/v1.0/your realm name/groups/{your group guid}/owners

Group Logo:

 

How to set O365 PageLayout Associated Content Type field

Here is a code snippet to set your page layouts associated content type. This one was a bit weird when I first tried to set it.

 private static void SetPageLayoutMetadata(Web web, File uploadFile, string title, string publishingAssociatedContentType)
{
// Speficy that the page layout is a page layout and not a master page
var parentContentTypeId = ""0x01010007FF3E057FA8AB4AA42FCB67B453FFC100E214EEE741181F4E9F7ACC43278EE811""; //Page Layout
var gallery = web.GetCatalog(116);
web.Context.Load(gallery, g => g.ContentTypes);
web.Context.ExecuteQuery();

var contentTypeId = gallery.ContentTypes.FirstOrDefault(ct => ct.StringId.StartsWith(parentContentTypeId)).StringId;
var item = uploadFile.ListItemAllFields;
web.Context.Load(item);

item["ContentTypeId"] = contentTypeId;
item["Title"] = title;
item["PublishingAssociatedContentType"] = publishingAssociatedContentType;

item.Update();
web.Context.ExecuteQuery();
} 

Two important things:

  • parentContentTypeId: This is the ID that tells O365 that this page layout is actually page layout, this is a static id which is defined in the code
  • publishingAssociatedContentType: This is your actual content type to which you want to associate your page layout to: Example of the format:;#my content type name;#0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF3900242457EFB8B24247815D688C526CD44D00A3428808D7DE6A4RABF83921AFB25424;#
    • So the format should be in the following way:

public static String BuildPublishingAssociativeContentTypeId(ContentType contentType)
{
String contentTypeAssociativeID = null;
if(contentType != null)
{
contentTypeAssociativeID = String.Format(";#{0};#{1};#", contentType.Name, contentType.StringId);
}

return contentTypeAssociativeID;
}

O365 OfficeDev PnP CSOM tools installation

This post will assume you have Visual Studio installed with Microsoft Office 365 API tools for Visual Studio.

  • Create a new Visual Studio project, lets say a console application.
  • Press on your project the second mouse button and select “Manage NuGet Packages…”
  • In the new window search for online packages and type in pnp or officedevpnpcore or similar. Then install the OfficeDevPnp.Core.Online package.

OfficePnp1

  • Wait for the installation to complete. After this you are ready to use CSOM to operate on your desired O365 site.

OfficePnp2

As you can see from the image above the nuget package will install all of what you need. You do not have to worry about much. Easy, right :)?

Links to know:

https://github.com/OfficeDev/PnP

https://channel9.msdn.com/blogs/OfficeDevPnP/Getting-Started-with-PnP-Provisioning-Engine

https://github.com/OfficeDev/PnP-Partner-Pack

http://dev.office.com/patterns-and-practices-resources

http://dev.office.com/blogs/new-sharepoint-csom-version-released-for-Office-365

https://www.nuget.org/packages/Microsoft.SharePointOnline.CSOM

https://lionadi.wordpress.com/2015/06/22/office-365-o365-client-application-registration-authentication-and-authorization/

https://lionadi.wordpress.com/2015/07/02/o365-csom-client-side-object-model-examples/

https://lionadi.wordpress.com/2015/09/16/o365-csom-getting-user-profile-information-without-possible-errors/

https://lionadi.wordpress.com/tag/o365/

SharePoint 2013 display templates for content webparts do not work

This problem may occur when you have a custom display template which you are modifying at some stage and updating it into SharePoint. If for some reason your template stops working what you need to do is go to the display template and modify its properties.

There you will find several options where you want this template to be used, such as search, content webparts etc.

So go and check your display templates properties and make sure you have selected where the template is to be used.

Corrupted SharePoint Blog Post.aspx page and how to fix it

This is one possible solution which can also be applied to O365(possibly).

The solution is to re-activate two features related to Blogs site. These features should re-create the broken post.aspx page.

BlogContent $Resources:core,blogContentFeatureTitle; Web 0d1c50f7-0309-431c-adfb-b777d5473a65 $Resources:core,blogContentFeatureDesc;
BlogHomePage Blog Home Page Web e4639bb7-6e95-4e2f-b562-03b832dd4793 Creates the default.aspx page for the a Blog s

O365 – CSOM Check if a user does not exist in your tenant anymore

I had a situation where I needed to make sure if a user does not exist anymore in the O365 system. I had to use CSOM for this solution and no matter how I tried I could not get any indication that a user has been deleted from the system.

I tried the IsActive field and Deleted field of an user object but no luck. No matter what I did even if the user was deleted and the expiration date of 30 days expired the user was still active.

My solution was that I checked to see if CSOM could retrieve a user profile data. If no data could be retrieved then this is an indication that the user profile has been deleted, hence the user has been deleted from the system. That is it. I used a field like account name since I know it must exist for all users.

There may be a “proper” solution for this but I just could not find one no matter how hard I tried(or maybe I just looked in the wrong place 🙂 ). Anyway see my previous post on how to get user profile information on how to do this workaround:

https://lionadi.wordpress.com/2015/09/16/o365-csom-getting-user-profile-information-without-possible-errors/

O365 Add-In(App) Error: “Sorry, only tenant administrators can add or give access to this app.”

On the web there are many answers to this problem mine was simply related to the permission requests in the APP and the user account privileges in O365.

In my case I accidentally requested permission on tenant level while I needed only Site Collection level permission for my app. This lead to situations where my app was visible to be added by someone whom can manage apps in a site BUT did not have permissions to approve permission requests at Tenant level.

So lesson learned: Check your app and user permissions/privileges.

SharePoint/O365 JSOM – App(Add-In) – Updating list items and making your custom action behave like a popup window

I am a bit lazy today so I will not go into too much detail on the code below. It is rather self explanatory. The first piece of the code is getting selected list items and the second part is updating fields in a list item.


var context;
var web;
var user;
var spHostUrl;
var parentContext;
var listItems;
var listItem;
var listItemID;
var listID;
var parsedListItemIDs;

// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model
// Get the URLs for the add-in web the host web URL from the query string.
$(document).ready(function () {

 DisplaySelectedItems();
 
});

function DisplaySelectedItems() {

 // Get the query strings parameter to operate on the desired list and list items
 var params = document.URL.split("?")[1].split("&");

 for (var i = 0; i < params.length; i = i + 1) {
 params[i] = decodeURIComponent(params[i]);

 if (params[i].split("=")[0] == "SPListId") {
 listID = params[i].split("=")[1];
 }

 if (params[i].split("=")[0] == "SPHostUrl") {
 spHostUrl = params[i].split("=")[1];
 }
 if (params[i].split("=")[0] == "SPListItemId") {
 listItemID = params[i].split("=")[1];
 parsedListItemIDs = listItemID.split(",");

 }
 }

 // Open a client context
 context = new SP.ClientContext.get_current();
 // Create a parent context(to the target web where the list and list items are located, not in the app web)
 parentContext = new SP.AppContextSite(context, spHostUrl);
 web = parentContext.get_web();

 // Get the list
 var list = web.get_lists().getById(listID);

 var camlQuery = SP.CamlQuery.createAllItemsQuery();

 listItems = list.getItems(camlQuery);
 context.load(listItems);

 // Request O365 to perform the operations on list items
 context.executeQueryAsync(Function.createDelegate(this, onQuerySucceeded),
 Function.createDelegate(this, onQueryFailed));
}

function ProcessSelectedItemsFor()
{
 
 // Get the query strings parameter to operate on the desired list and list items
 var params = document.URL.split("?")[1].split("&");

 for (var i = 0; i < params.length; i = i + 1) {
 params[i] = decodeURIComponent(params[i]);

 if (params[i].split("=")[0] == "SPListId") {
 listID = params[i].split("=")[1];
 }

 if (params[i].split("=")[0] == "SPHostUrl") {
 spHostUrl = params[i].split("=")[1];
 }
 if (params[i].split("=")[0] == "SPListItemId") {
 listItemID = params[i].split("=")[1];
 parsedListItemIDs = listItemID.split(",");

 }
 }


 // Open a client context
 context = new SP.ClientContext.get_current();
 // Create a parent context(to the target web where the list and list items are located, not in the app web)
 parentContext = new SP.AppContextSite(context, spHostUrl);
 web = parentContext.get_web();

 // Get the list
 var list = web.get_lists().getById(listID);

 // Go through the list items and process them
 for (var i = 0; i < parsedListItemIDs.length; i++) {
 listItem = list.getItemById(parsedListItemIDs[i]);
 listItem.set_item('your list item field name', 'false');

 listItem.set_item('your list item field name', 'true');
 listItem.update();
 }


 // Request O365 to perform the operations on list items
 context.executeQueryAsync(Function.createDelegate(this, onQuerySucceededAlternate),
 Function.createDelegate(this, onQueryFailed));
}

function CloseChildDialog() {
 //SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, 'Closed with OK result');
 SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.cancel, 'Cancelled');
}


function onQuerySucceeded() {
 $("#selectedItems").empty();
 var listInfo = '';
 var listEnumerator = listItems.getEnumerator();

 listInfo += "Chosen filest:<br/><table><tr><th>ID</th><th>File name</th></tr>";

 while (listEnumerator.moveNext()) {
 var listItem = listEnumerator.get_current();
 for (var i = 0; i < parsedListItemIDs.length; i++) {
 if (listItem.get_item('ID') == parsedListItemIDs[i]) {
 listInfo += '<tr><td>' + listItem.get_item('ID') + '</td>'
 + '<td>' + listItem.get_item('FileLeafRef') + '</td>'
 + '</tr>\n';
 }
 }
 }
 $("#message").empty();



 listInfo += '</table>';

 $("#selectedItems").html(listInfo);
}

function onQuerySucceededAlternate() {
 $("#results").empty();
 

 $("#results").html("Success");
 $("#divActionArea").hide();
}

function onQueryFailed(sender, args) {
 $("#results").empty();
 $("#results").text('Request failed. ' + args.get_message() +
 '\n' + args.get_stackTrace());
}


 Making an app custom action in O365 to behave like a popup

to make your custom action to “pop up” into a window you need to add the following details in your custom action definition file(the bolded text):

<?xml version=”1.0″ encoding=”utf-8″?>
<Elements xmlns=”http://schemas.microsoft.com/sharepoint/”&gt;
<CustomAction Id=”afa59853-4390-4b16-876a-6be2338f4186.”
RegistrationType=”List”
RegistrationId=”101″
Location=”CommandUI.Ribbon”
Sequence=”10001″
Title=”Invoke &apos;&apos; action”
HostWebDialog=”true”
HostWebDialogHeight=”400″
HostWebDialogWidth=”300″>
<CommandUIExtension>
<!–
Update the UI definitions below with the controls and the command actions
that you want to enable for the custom action.
–>
<CommandUIDefinitions>
<CommandUIDefinition Location=”Ribbon.Documents.Manage.Controls._children”>
<Button Id=”Ribbon.Documents.Manage.Button”
Alt=”Request ”
Sequence=”100″
Command=”Invoke_ButtonRequest”
LabelText=”Request ”
TemplateAlias=”o1″
Image32by32=”_layouts/15/images/placeholder32x32.png”
Image16by16=”_layouts/15/images/placeholder16x16.png” />
</CommandUIDefinition>
</CommandUIDefinitions>
<CommandUIHandlers>
<CommandUIHandler Command=”Invoke_ButtonRequest”
CommandAction=”~appWebUrl/Pages/Default.aspx?{StandardTokens}&amp;DisplayType=iframe&amp;SPListItemId={SelectedItemId}&amp;SPListId={SelectedListId}”/>
</CommandUIHandlers>
</CommandUIExtension >
</CustomAction>
</Elements>

You also need to add the following bolded line of definition in your ASPX file:

<asp:Content ContentPlaceHolderID=”PlaceHolderMain” runat=”server”>

<WebPartPages:AllowFraming runat=”server” />

</asp:Content>

More info, I recommend reading the link below on “clickjacking” related to AllowFraming definition:

http://blogs.msdn.com/b/officeapps/archive/2012/12/12/iframing-sharepoint-hosted-pages-in-apps.aspx 

https://msdn.microsoft.com/ENUS/library/microsoft.sharepoint.webpartpages.allowframing.aspx

http://blogs.msdn.com/b/officeapps/archive/2012/12/12/iframing-sharepoint-hosted-pages-in-apps.aspx

O365 CSOM – Client Side Object Model examples

Here are some examples on how to use CSOM with O365:

This is Microsofts’ link on the matter for more examples:

https://msdn.microsoft.com/en-us/library/ff798388.aspx

 

Remove SiteCollection


 var tenantAdminUri = new Uri(tenantAdminUrl);
 string realm = TokenHelper.GetRealmFromTargetUrl(tenantAdminUri);
 var token = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, tenantAdminUri.Authority, realm).AccessToken;
 using (var tenantContext = TokenHelper.GetClientContextWithAccessToken(tenantAdminUri.ToString(), token))
 {
 // Set the time out as high as possible
 tenantContext.RequestTimeout = int.MaxValue;

 var tenant = new Tenant(tenantContext);

 //start the SPO operation to create the site
 SpoOperation op = tenant.RemoveSite(webUrl);
 tenantContext.Load(op, i => i.IsComplete);
 tenantContext.RequestTimeout = int.MaxValue;
 tenantContext.ExecuteQuery();

 while (!op.IsComplete)
 {
 Console.WriteLine("Waiting 30 seconds site to be provisioned");
 //wait 30seconds and try again
 System.Threading.Thread.Sleep(30000);
 op.RefreshLoad();
 tenantContext.ExecuteQuery();
 }
 }

 Updating a list item

</pre>
List list = ctx.Web.Lists.GetByTitle(ConfigurationManager.AppSettings["SiteCollectionRequests_List"]);
ListItem listItem = list.GetItemById(id);
ctx.Load(listItem);
ctx.ExecuteQuery();

statusMessage += "Your message";
listItem["StatusMessage"] = statusMessage;
listItem.Update();
list.Update();
ctx.Web.Update();
ctx.ExecuteQuery();
<pre>

Adding a new item to a list


List list = ctx.Web.Lists.GetByTitle(ConfigurationManager.AppSettings["SiteCollectionRequests_LogList"]);

 ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();
 ListItem newItem = list.AddItem(itemCreateInfo);
 newItem["Title"] = title;
 newItem["url"] = workspaceURL;

 XmlSerializer xs = new XmlSerializer(typeof(WorkspacePrivileges));
 StringWriter sww = new StringWriter();
 XmlWriter writer = XmlWriter.Create(sww);
 xs.Serialize(writer, workspacePrivileges);
 String aaa = sww.ToString();

 newItem["my text field"] = sww.ToString();
 newItem.Update();
 ctx.ExecuteQuery();

Change Workspace Privileges To Read Only


Uri siteUrl = new Uri(workspaceURL);
 string realm = TokenHelper.GetRealmFromTargetUrl(siteUrl);
 var token = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, siteUrl.Authority, realm).AccessToken;
 using (var ctxWorkspace = TokenHelper.GetClientContextWithAccessToken(siteUrl.ToString(), token))
 {
 Web currentWeb = ctxWorkspace.Web;
 ctxWorkspace.Load(currentWeb);

 UserCollection webUsers = currentWeb.SiteUsers;
 ctxWorkspace.Load(webUsers);
 ctxWorkspace.ExecuteQuery();
 List<String> usersToAddReadOnlyRights = new List<string>();

 foreach(User user in webUsers)
 {
 if (user.LoginName.ToLowerInvariant().Contains("membership"))
 {
 if (!user.IsSiteAdmin)
 {
 webUsers.RemoveById(user.Id);
 usersToAddReadOnlyRights.Add(user.LoginName);
 }
 }
 }
 currentWeb.Update();
 ctxWorkspace.ExecuteQuery();

 Group visitorGroup = ctxWorkspace.Web.SiteGroups.GetByName(ctxWorkspace.Web.Title + ConfigurationManager.AppSettings["WorkspaceVisitors"]);
 ctxWorkspace.Load(currentWeb);
 ctxWorkspace.Load(visitorGroup);
 ctxWorkspace.Load(webUsers);
 ctxWorkspace.ExecuteQuery();
 foreach (String user in usersToAddReadOnlyRights)
 {
 String[] userLoginNameArray = user.Split('|');
 if(userLoginNameArray != null && userLoginNameArray.Length > 1)
 {
 UserCreationInformation userInfo = new UserCreationInformation();
 userInfo.LoginName = userLoginNameArray[2];
 currentWeb.AddUserToGroup(visitorGroup, userLoginNameArray[2]);

 }
 }
 currentWeb.Update();
 ctxWorkspace.ExecuteQuery();

Remove Workspace users privileges And deny Search Indexing on lists


Uri siteUrl = new Uri(workspaceURL);
 string realm = TokenHelper.GetRealmFromTargetUrl(siteUrl);
 var token = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, siteUrl.Authority, realm).AccessToken;
 using (var ctxWorkspace = TokenHelper.GetClientContextWithAccessToken(siteUrl.ToString(), token))
 {

 Web currentWeb = ctxWorkspace.Web;
 ctxWorkspace.Load(currentWeb);
 ListCollection lists = ctxWorkspace.Web.Lists;
 ctxWorkspace.Load(lists);
 UserCollection webUsers = currentWeb.SiteUsers;
 ctxWorkspace.Load(webUsers);
 ctxWorkspace.ExecuteQuery();

 foreach (List list in lists)
 {
 list.NoCrawl = true;
 list.Update();
 }

 foreach (User user in webUsers)
 {
 if (user.LoginName.ToLowerInvariant().Contains("membership"))
 {
 if (!user.IsSiteAdmin)
 {
 webUsers.RemoveById(user.Id);
 }
 }
 }
 currentWeb.Update();
 ctxWorkspace.ExecuteQuery();

Office 365( O365 ) – Client application registration, authentication and authorization

OK,

I am currently working on a client side application (console app) that needs to connect to a O365 site and do some stuff with CSOM.

In this post I will write some basic things you need to do in order to achieve a connection to an O365 site. In my case I am working with a console app but this can be a powershell app also.

At first I recommend you look at this piece of code which you need to use to achieve the communication and authentication with O365:

https://github.com/OfficeDev/SharePoint-Power-Hour-Code-Samples/blob/master/SP.SiteCreatorWeb/TokenHelper.cs

https://github.com/OfficeDev/SharePoint-Power-Hour-Code-Samples

A basic C# code to connecto O365 and do get a list and its items would look like this:


Uri siteUri = new Uri(ConfigurationManager.AppSettings["SiteCollectionRequests_SiteUrl"]);

 //Get the realm for the URL
 string realm = TokenHelper.GetRealmFromTargetUrl(siteUri);

 //Get the access token for the URL.
 //Requires this app to be registered with the tenant
 string accessToken = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, siteUri.Authority, realm).AccessToken;

 //Get client context with access token
 using (var ctx = TokenHelper.GetClientContextWithAccessToken(siteUri.ToString(), accessToken))
 {

 // Set the time out as high as possible
 ctx.RequestTimeout = int.MaxValue;

 List list = ctx.Web.Lists.GetByTitle(ConfigurationManager.AppSettings["SiteCollectionRequests_List"]);
 CamlQuery camlQuery = new CamlQuery();
 camlQuery.ViewXml = "your CAML query here";
 ListItemCollection listItems = list.GetItems(camlQuery);
 ctx.Load(listItems);
 ctx.ExecuteQuery();

 var itemsCount = listItems.Count;

So before you can use your code you need to do two things in your target site:

  1. Register you client side app. This basically means that in your app config you need to set a clientID and a client secret. Without these values no proper authentication and authorization can done.
    1. Register you app in O365 by using the following URL and replacing the hostname and adding your target site: http://<SharePointWebsite>/_layouts/15/AppRegNew.aspx
  2. After you register the app you need to need to specify in a target site what kind of privileges the app has. In the code sample above you would need to specify at least read rights.
    1. To provide privileges the following url: http://<SharePointWebsite>/_layouts/15/AppInv.aspx
    2. Notice that for this step you need to provide a XML describing the privileges request. The simples way for me was to start up Visual Studio, create an app and define the rights request through the GUI and copy & pasting the XML from the AppMenifest.xml. It would look something like this:
      1. <AppPermissionRequests AllowAppOnlyPolicy=”true”>
        <AppPermissionRequest Scope=”http://sharepoint/content/sitecollection/web/list&#8221; Right=”FullControl” />
        </AppPermissionRequests>

Also the last thing which you need to check is to have a proper configurations in the app.config(if you are using an console app):


<appSettings>
 <add key="ClientId" value="client id obtained after registration" />
 <add key="ClientSecret" value="client secrect after registration" />
 <add key="SiteCollectionRequests_SiteUrl" value="yoursiteurl"/>
 <add key="SiteCollectionRequests_List" value="listname" />

 </appSettings>

Also notice that the ClientId and the ClientSecret have to be provided in the app.config for the TokenHelper.cs class to work. The class will search for these settings values automatically.

Additional help here: http://blog.vgrem.com/2015/01/27/consuming-the-sharepoint-online-rest-api-from-powershell-part-2/

https://msdn.microsoft.com/en-US/library/fp142383.aspx

https://msdn.microsoft.com/library/fp179892(office.15).aspx

https://msdn.microsoft.com/en-us/library/office/fp179912.aspx#BasicOps_SPListItemTasks