Wednesday, 5 March 2014

View Tenant (ULS) Logs in SharePoint Online using CSOM

Update (14th Sep 2014): Even though the classes exist in the CSOM, the Microsoft Office 365 Engineering team has confirmed that this is something which is not possible right now. It is also something which is not currently on their road map. They have said that if there is high demand for this feature, they will look into implementing it. Please go to the Office 365 UserVoice site and vote this feature up if you are interested: http://officespdev.uservoice.com/forums/224641-general/suggestions/4578386-provide-a-way-to-view-uls-logs-on-sharepoint-onlin

----------------------------------------------------------X-------------------------------------------------

A while ago, I came across the Office365 UserVoice site. It was a good way to give feedback and let the SharePoint/Office365 team know which features could make the life of SharePoint Developers easy.

I decided to post on it a feature request, which I felt was desperately needed and would really help me as a SharePoint Developer: A way to view ULS Logs on SharePoint Online
http://officespdev.uservoice.com/forums/224641-general/suggestions/4578386-provide-a-way-to-view-uls-logs-on-sharepoint-onlin

It seems this was a shared opinion among many people and the request went on to become one of the top voted on the site:
http://officespdev.uservoice.com/forums/224641-general/filters/top

Fast Forward to today and I was really excited about the SharePoint Conference 2014! I saw a lot of code samples and articles being published as a result of the new features introduced by the SharePoint Team. While exploring the Office App Model Samples (http://officeams.codeplex.com/) I came across the following DLL: Microsoft.Online.SharePoint.Client.Tenant.dll

You can refer to my previous post about using this DLL to create Site Collections in SharePoint Online:
http://www.vrdmn.com/2014/03/create-site-collections-with-csom-in.html

I opened up the DLL in ILSpy and immediately noticed the TenantLog class:
http://msdn.microsoft.com/en-us/library/microsoft.online.sharepoint.tenantadministration.tenantlog_members(v=office.15).aspx

After playing around it a bit, I was able to retrieve Log messages from my Tenant. This seems to be a preview feature still in development and was not working on all the tenants on which I tested. In fact, it was working only on a newly created Tenant! That too only for the Developer Site.

Having a look at the MSDN docs for the SPO PowerShell cmdlet:
http://technet.microsoft.com/en-us/library/fp161369(v=office.15).aspx

"This function cannot retrieve all SharePoint Online errors. It retrieves a subset of errors that happen due to external systems.
For Beta 2, the only logs available are for Business Connectivity Services (BCS)."

I will keep this post updated with any new information which comes along.

You will need the following DLLs for this code to work:
Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Runtime.dll
Microsoft.Online.SharePoint.Client.Tenant.dll

The first two assemblies can be found in the ISAPI folder of your SharePoint 2013 Server Box. The Microsoft.Online.SharePoint.Client.Tenant.dll is a part of  the SharePoint Server 2013 Client Components SDK which can downloaded from here: http://www.microsoft.com/en-in/download/details.aspx?id=35585

So without much further ado, here is the code:
using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using System;
using System.Security;
namespace ViewSPOLog
{
class Program
{
static void Main(string[] args)
{
//Open the Tenant Administration Context with the Tenant Admin Url
using (var tenantContext = new ClientContext("https://yoursite-admin.sharepoint.com/"))
{
//Authenticate with a Tenant Administrator
var passWord = new SecureString();
foreach (char c in "password".ToCharArray()) passWord.AppendChar(c);
tenantContext.Credentials = new SharePointOnlineCredentials("admin@yoursite.onmicrosoft.com", passWord);
var tenant = new Tenant(tenantContext);
var tenantLog = new TenantLog(tenantContext);
var dateTimeUTCNow = DateTime.UtcNow;
//Get 50 Rows of Tenant Log Entries starting from 5 days ago till now.
var logEntries = tenantLog.GetEntries(dateTimeUTCNow.AddDays(-5), dateTimeUTCNow, 50);
//Get 50 Rows of Tenant Log Entries of the specified CorrelationId starting from 5 days ago till now
//var logEntries = tenantLog.GetEntriesByCorrelationId(dateTimeUTCNow.AddDays(-5), dateTimeUTCNow, 50, new Guid("ae2b1e34-12eb-4652-a0db-ce4ab916c74e"));
//Get 50 Rows of Tenant Log Entries of the specified Source starting from 5 days ago till now.
//var logEntries = tenantLog.GetEntriesBySource(dateTimeUTCNow.AddDays(-5), dateTimeUTCNow, 50, 1);
//Get 50 Rows of Tenant Log Entries of the specified User starting from 5 days ago till now.
//var logEntries = tenantLog.GetEntriesByUser(dateTimeUTCNow.AddDays(-5), dateTimeUTCNow, 50, "admin@yoursite.onmicrosoft.com");
tenantContext.Load(logEntries);
tenantContext.ExecuteQuery();
foreach (TenantLogEntry logEntry in logEntries)
{
Console.WriteLine(string.Format("Timestamp:{0} | Message:{1} | CorrelationId:{2} | Source:{3} | User:{4} | CategoryId:{5}",
logEntry.TimestampUtc, logEntry.Message, logEntry.CorrelationId , logEntry.Source , logEntry.User, logEntry.CategoryId));
}
Console.WriteLine("Press Any Key to Exit...");
Console.ReadKey();
}
}
}
}
view raw viewspologs.cs hosted with ❤ by GitHub
And here is the output I got after running the code:


I think the SharePoint team has done a really great job of listening to the community to add new features to SharePoint/Office365 and I am really happy!

Tuesday, 4 March 2014

Create Site Collections with CSOM in SharePoint Online

With the SharePoint Conference 2014, a lot of code samples and articles where recently released. I was most impressed by the Office App Model Samples found here: http://officeams.codeplex.com/

Within that, there is some really good code of which my favorite is Creating Site Collections in SharePoint Online with CSOM. Previously this was only possible via Powershell and the SharePoint Online (SPO) Commandlets. I have modified the code provided in the samples to make it a bit less complex and you can also use it outside of an app e.g. in console applications.

You will need the following DLLs for this code to work:
Microsoft.SharePoint.Client.dll
Microsoft.SharePoint.Client.Runtime.dll
Microsoft.Online.SharePoint.Client.Tenant.dll

The first two assemblies can be found in the ISAPI folder of your SharePoint 2013 Server Box. The Microsoft.Online.SharePoint.Client.Tenant.dll is a part of  the SharePoint Server 2013 Client Components SDK which can downloaded from here: http://www.microsoft.com/en-in/download/details.aspx?id=35585

So without much further ado, here is the code:

using Microsoft.Online.SharePoint.TenantAdministration;
using Microsoft.SharePoint.Client;
using System;
using System.Security;
namespace CreateSiteCollections
{
class Program
{
static void Main(string[] args)
{
//Open the Tenant Administration Context with the Tenant Admin Url
using (ClientContext tenantContext = new ClientContext("https://yoursite-admin.sharepoint.com/"))
{
//Authenticate with a Tenant Administrator
SecureString passWord = new SecureString();
foreach (char c in "password".ToCharArray()) passWord.AppendChar(c);
tenantContext.Credentials = new SharePointOnlineCredentials("admin@yoursite.onmicrosoft.com", passWord);
var tenant = new Tenant(tenantContext);
//Properties of the New SiteCollection
var siteCreationProperties = new SiteCreationProperties();
//New SiteCollection Url
siteCreationProperties.Url = "https://yoursite.sharepoint.com/sites/codesite";
//Title of the Root Site
siteCreationProperties.Title = "Site Created from Code";
//Login name of Owner
siteCreationProperties.Owner = "admin@yoursite.onmicrosoft.com";
//Template of the Root Site. Using Team Site for now.
siteCreationProperties.Template = "STS#0";
//Storage Limit in MB
siteCreationProperties.StorageMaximumLevel = 100;
//UserCode Resource Points Allowed
siteCreationProperties.UserCodeMaximumLevel = 50;
//Create the SiteCollection
SpoOperation spo = tenant.CreateSite(siteCreationProperties);
tenantContext.Load(tenant);
//We will need the IsComplete property to check if the provisioning of the Site Collection is complete.
tenantContext.Load(spo, i => i.IsComplete);
tenantContext.ExecuteQuery();
//Check if provisioning of the SiteCollection is complete.
while (!spo.IsComplete)
{
//Wait for 30 seconds and then try again
System.Threading.Thread.Sleep(30000);
spo.RefreshLoad();
tenantContext.ExecuteQuery();
}
Console.WriteLine("SiteCollection Created.");
}
}
}
}