August 2015 - Posts

Today Microsoft released the IT Preview of SharePoint 2016.  We’re going to look at the install process today and point out any differences between previous versions of SharePoint.  You can find out more about SharePoint 2016 from the Office blog post.

Installation

I created a new virtual machine running on Windows 10 Hyper-V.  This virtual machine is running Windows Server 2016 Technical Preview 3.  On this server, I have promoted it to a domain controller using Active Directory Directory Services.  I have also installed SQL Server 2014 R2.

Installation of SharePoint 2016 IT Preview looks similar to previous SharePoint installations.  When you mount the ISO, you will see a familiar splash screen.

SP2016P1Splash

Installing the prerequisites

The prerequisite installer looks similar to previous versions.  Click Next to continue.

SP2016P1Prerequisites1

Accept the license terms.

SP2016PrerequisitesLicenseTerms2

Wait and home it finishes successfully.

SP2016P1PrerequisitesProgress3

Installation of the SharePoint 2016 IT Preview prerequisites is just as troublesome as previous versions.  I managed to generate a few errors and never did get it to agree the role was successfully installed.  I had to install the Visual Studio 2013 Redistributable myself.  There is a work-around for getting around the IIS role configuration step on the Known Issues in SharePoint Server 2016 Preview page.

SP2016P1PrerequisitesError4

SharePoint 2016 Installation

The installation is quick and easy.  It also looks similar to other versions.  Start by entering the product key.  Remember this was found on the SharePoint 2016 download page.

Sp2016P1InstallProductKey1

Next, accept some more license terms.

SP2016P1LicenseTerms2

Specify the install location for your search index.  You can just use the defaults for this preview installation.

SP2016P1InstallFileLocations3

Wait for the installation to complete.

SP2016P1InstallProgress4

When installation completes, you will be prompted to run the Configuration Wizard.

SP2016P1InstallCompleteRunWizard5

Running the Configuration Wizard

The Configuration Wizard also looks similar but has a few changes.  Click Next to proceed.

Sp2016P1ConfigStart1

Now, create a new farm.

SP2016P1ConfigNewFarm2

Then, specify your farm passphrase.

SP2016P1ConfigPassphrase

Specify your farm account, SQL Server name and database.

SP2016P1COnfigDatabase3

This new screen allows you use the new MinRole feature. MinRole simplifies the server architecture of SharePoint 2016.  In this case, we are going to use a Single Server Farm (which shouldn’t be as bad as previous versions).

Sp2016P1ConfigRole4

Specify the details for Central Administration.

SP2016P1ConfigCA5

Confirm your settings.

Sp2016P1ConfigConfirmation6

When it finishes, you are ready to try out Central Administration.

Sp2016P1ConfigComplete6

Now, we can start our configuration.

SP2016P1CAOptIn

That’s a quick look at the installation process of SharePoint 2016 IT Preview.  Be on the look out for my next posts covering changes in Central Administration and the UI.

Follow me on twitter: @coreyroth

I’ve had a personal interest in figuring out how to play videos from the Office 365 Video Portal in a Univeral Windows App (UWP) in Windows 10 since Microsoft Ignite.  In reality, the process isn’t that difficult, but there wasn’t a lot of details out there on how to put the pieces together until recently.  Today, I am going to walk you through how to retrieve the first video in a channel and play it using a MediaElement

Today, I combined elements I learned from Richard DiZerga’s Universal App blog post, Chakkradeep Chandran’s Ignite session, as well as Andrew Connell's MVC Sample.  Special thanks to all of them for having the pieces I needed to put all of this together.  Since this is a Universal app it should work across multiple devices in theory.

This app could easily be extended to create a nice interface to browse a channel and pick a video.  If you’re familiar with data binding in WPF though that shouldn’t be hard for you, so I won’t cover that today.  We’re simply going to look at the necessary API and REST calls to get the secure playback URL.  Once we have that URL, we can have the MediaElement start playing the video.

Getting started

First, you’ll need to have installed Windows 10 as well as the final version of Visual Studio 2015.  We’re also assuming you have an Office 365 tenant, the Video Portal turned on, and you have some videos uploaded.  If you have never created a Universal Windows App before you can find it under your favorite programming language –> Windows –> Universal –> Blank App (Universal Windows).

O365VideoVisualStudioNewUniveralProject

Playing a video from the Office 365 Video Portal involves several steps.  If you know some of the values already along the way (such as the Video Portal URL), you can skip some steps.  I am going to include all of them (which means this blog post is going to be long).  The steps we need to go through are:

  1. Authenticate with Azure Active Directory / Office 365
  2. Access the Discovery Service to get the RootSite ServiceResourceId
  3. Determine the Video Portal Hub Url (i.e.: https://mytenant.sharepoint.com/hub)
  4. Get the list of channels
  5. Get the videos inside a channel
  6. Get the video playback URL

As you can see, that’s a lot of service calls.  Caching is a good thing.

Connecting to Office 365

There are no shortage of ways to authenticate with Office 365 and Azure Active Directory.  Windows 10 introduces a new way called the Web Account Provider.  This will provide us our token that we can pass to the Discovery Service as well as give us tokens to other services such as SharePoint or Outlook.  It will prompt the user to enter his or her credentials if we don’t have a token yet as well.

To connect to Office 365 bring up the context menu on the project in Solution Explorer and choose Add –> Connected Service.  Select Office 365 APIs and then click Configure.

O365VideoConnectedServiceOffice365API

The nice thing about the Connected Service dialog in Visual Studio 2015 now is that it takes care of all of the manual Azure Active Directory application setup.  You don’t need to go manually copy a ClientId, secret, permissions, or anything.  This makes the new developer experience much better.

Now, you need to specify the domain of your tenant (i.e.: mytenant.onmicrosoft.com).

O365VideoConnectedServiceDomain

Clicking Next will prompt you for authentication.  Enter your Office 365 credentials and then you can proceed to the next step.

O365VideoLogin

Now, we need to tell Visual Studio to Create a new Azure AD application to access Office 365 API services.  This will register the new application in Azure AD and then we can request permissions.

O365VideoConnectedServiceNewApplication

On the next six steps of the Wizard, we set the permissions that the app requires.  For the purpose of playing a video, we don’t need access to Calendar, Contacts, Mail, or My Files.  For Sites, we need the following permissions:

  • Read and write items and lists in all site collections
  • Read and write items in all site collections
  • Read items in all site collections

O365VideoConnectedServiceSites

For Users and Groups, select the following permissions:

  • Sign you in and read your profile

O365VideoConnectedServiceUserGroups

Finally, hit Finish and Visual Studio will add the connected service to your project.

Designing the Page Layout

Now we’ll edit MainPage.xaml and add our controls to it.  I kept this simple by just adding a Button control and a MediaElement.  You can arrange them as you like.

O365VideoMainPageXaml

Authenticating with Web Account Manager

Before we get too far, I am going to create a folder for the Models.  I am going to skip a formal Controller class today since we’re not doing any real data binding.  Normally you would have multiple controllers to pull up a list of channels, videos, etc.  We’ll use a repository class, VideoRepository, that will connect to Office 365 and retrieve our data and our models we’ll use to deserialize the jSon that comes back from the REST API. 

The VideoRepository class will also handle authentication.  We’ll add the following using statements.

using System.Net.Http;

using System.Net.Http.Headers;

using Microsoft.Office365.Discovery;

using Microsoft.Office365.SharePoint.CoreServices;

using Windows.Security.Authentication.Web.Core;

using Windows.Security.Credentials;

using Newtonsoft.Json;

The first method we will create is GetAccessTokenForResource.  If you have looked at other Universal App Samples, this should look fairly similar.  The purpose of this method is to attempt to get a token silently (without prompting the user).  If it can’t, then it it will show the the Office 365 login and the user can login which will provide the token. 

public async Task<string> GetAccessTokenForResource(string resource)

{

    string token = null;

 

    //first try to get the token silently

    WebAccountProvider aadAccountProvider

        = await WebAuthenticationCoreManager.FindAccountProviderAsync("https://login.windows.net");

    WebTokenRequest webTokenRequest

        = new WebTokenRequest(aadAccountProvider, String.Empty, App.Current.Resources["ida:ClientID"].ToString(), WebTokenRequestPromptType.Default);

    webTokenRequest.Properties.Add("authority", "https://login.windows.net");

    webTokenRequest.Properties.Add("resource", resource);

    WebTokenRequestResult webTokenRequestResult

        = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(webTokenRequest);

    if (webTokenRequestResult.ResponseStatus == WebTokenRequestStatus.Success)

    {

        WebTokenResponse webTokenResponse = webTokenRequestResult.ResponseData[0];

        token = webTokenResponse.Token;

    }

    else if (webTokenRequestResult.ResponseStatus == WebTokenRequestStatus.UserInteractionRequired)

    {

        //get token through prompt

        webTokenRequest

            = new WebTokenRequest(aadAccountProvider, String.Empty, App.Current.Resources["ida:ClientID"].ToString(), WebTokenRequestPromptType.ForceAuthentication);

        webTokenRequest.Properties.Add("authority", "https://login.windows.net");

        webTokenRequest.Properties.Add("resource", resource);

        webTokenRequestResult

            = await WebAuthenticationCoreManager.RequestTokenAsync(webTokenRequest);

        if (webTokenRequestResult.ResponseStatus == WebTokenRequestStatus.Success)

        {

            WebTokenResponse webTokenResponse = webTokenRequestResult.ResponseData[0];

            token = webTokenResponse.Token;

        }

    }

 

    return token;

}

Let’s look at some of the highlights.  First we get our aadAccountProvider by calling WebAuthenticationCoreManager.FindAccountProviderAync().  This is the call into the Web Account Manager that I have been talking about.  You always pass it the https://login.windows.net (at least for this exercise).  We then need a WebTokenRequest.  This is where the ClientId of the application comes in.  Remember Visual Studio created this for us when it registered our app with Azure Active Directory.  The resource property is where we pass in the Uri to the service we want to access.  On our first call this will be the Uri of the discovery service.  On subsequent calls it will be the Uri we get for accessing things in SharePoint.

Next, the method tries to silently authenticate the user.  This method would return with a Success result if the user has authenticated inside this application before. 

WebTokenRequestResult webTokenRequestResult

    = await WebAuthenticationCoreManager.GetTokenSilentlyAsync(webTokenRequest);

If the user already has a token, then we are done.  Otherwise user interaction is required. The RequestTokenAsync call on the WebAuthenticationCoreManager is what actually prompts the user for credentials.  Ultimately, this method returns a token for the resource you asked for.  When we run the application and click the Play button, it will prompt us for credentials.

O365VideoCredentialPrompt

After you authenticate, you will get prompted to grant permissions to the app.  These will match the ones we specified earlier when adding the Connected Service.

O365VideoCredentialPrompt

Calling the Discovery Service

We’re going to call the Discovery Service to determine the ServiceEndpointUri for the RootSite capability. We’ll do this in a new method called GetSharePointServiceEndpointUri. We do this by accessing for an access token from our GetAccessTokenForResource passing the URL https://api.office.com/discovery

string accessToken

    = await GetAccessTokenForResource("https://api.office.com/discovery/");

DiscoveryClient discoveryClient = new DiscoveryClient(() =>

{

    return accessToken;

});

After we get a DiscoveryClient, we can call DiscoverCapabilityAsync.  This method also stores the access token used for accessing resources in the variable sharePointAccessToken.  It also stores the ServiceEndpointUri in the variable sharePointServiceEndpointUri.  We’ll use this URI for the subsequent REST calls.

CapabilityDiscoveryResult result = await discoveryClient.DiscoverCapabilityAsync("RootSite");

sharePointAccessToken = await GetAccessTokenForResource(result.ServiceResourceId);

sharePointServiceEndpointUri = result.ServiceEndpointUri.ToString();

 

return sharePointServiceEndpointUri;

Remember, the full source code is available in GitHub.

Get the Video Portal Hub URL

If you have worked with Office 365, you probably know that it’s pretty easy to guess what the URL to the Video Portal Hub will be (the hub is the root site collection of the Video Portal).  Since we want to do things right though, we’ll go through the Video Service’s Discover endpoint to determine the URL.  In fact, once we construct these next two methods, the rest will be very similar.

We’ll create a new method called GetVideoPortalHubUrl.  The first thing we’ll do is call GetSharePointServiceEndpointUri to authenticate and return us the endpoint for working with SharePoint.  We append VideoService.Discover to the Uri returned by our method.  How did we know this was the URL, it’s in the Video REST API reference (still in preview).

var requestUrl = String.Format("{0}/VideoService.Discover", await GetSharePointServiceEndpointUri());

We then, create a function that returns an HttpRequestMessage using the requestUrl.

Func<HttpRequestMessage> requestCreator = () =>

{

    HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl);

    request.Headers.Add("Accept", "application/json;odata=verbose");

    return request;

};

Then, we create a new httpClient and pass it, our access token, the HttpClient, and the RequestMessage to a custom method we will build named SendRequestAsync.   This piece is based upon other’s code so I didn’t really tweak it since it works.  After our call to that method, we’ll deserialize the jSon that comes back.  I borrowed several of AC’s helper classes from his MVP example here.

Let’s take a look at SendRequestAsync.  We’ll start with a using blog to get our HttpRequestMessage

using (var request = requestCreator.Invoke())

We’ll then need to add the necessary headers.  First, we add an AuthenticationHeaderValue with the sharePointAccessToken we got earlier.  We also add another header, X-ClientService-ClientTag.  I don’t know if this is required but Chaks included it in his examples.  I updated the version to match the current version reported in the Connected Service wizard.

request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

request.Headers.Add("X-ClientService-ClientTag", "Office 365 API Tools 1.5");

Then we invoke the request using httpClient.

var response = await httpClient.SendAsync(request);

The method then returns the response assuming it’s successful.  The example that Chaks provided will actually make a second attempt to call the service if the user isn’t authorized.  You can optionally include that if you like.

Now going back to our GetVideoHubUrl method after we successfully got a response back.  We now need to parse the JSON that came back into a usable object.  This is where Newtonsoft.Json comes in.  We use the models that AC provided in the MVC project. In this case we serialize the responseString into an object of VideoServiceDiscovery.  Now, we can get the VideoPortalUrl for our subsequent REST calls.

string responseString = await response.Content.ReadAsStringAsync();

var jsonResponse = JsonConvert.DeserializeObject<VideoServiceDiscovery>(responseString);

videoPortalUrl = jsonResponse.Data.VideoPortalUrl;

Get the video portal channels

Now that we have our Video Portal Hub URL, we can retrieve the list of channels.  The Video REST API Reference tells us we need to append /_api/VideoService/Channels to the Video Portal Hub URL which we just retrieved.  We’ll create a new method called GetVideoChannels which will look similar to GetVideoPortalHubUrl expect the requestUrl used and the JSON serialization.

var requestUrl = string.Format("{0}/_api/VideoService/Channels", videoPortalUrl);

Since we return multiple channels, we loop through the results and add new VideoChannel objects to the list. 

string responseString = await response.Content.ReadAsStringAsync();

var jsonResponse = JsonConvert.DeserializeObject<VideoChannelCollection>(responseString);

 

var channels = new List<VideoChannel>();

 

foreach (var videoChannel in jsonResponse.Data.Results)

{

    var channel = new VideoChannel

    {

        Id = videoChannel.Id,

        HtmlColor = videoChannel.TileHtmlColor,

        Title = videoChannel.Title,

        Description = videoChannel.Description,

        ServerRelativeUrl = videoChannel.ServerRelativeUrl

    };

    channels.Add(channel);

}

At this point, you have enough data you can start doing some data binding.  As I mentioned earlier, I am skipping that since data binding in a Universal Windows App for Windows 10 is quite similar to what was there in Windows 8.1  For our example, I am simply going to pass the Channel Id into our next method to retrieve a list of videos.

Getting the list of videos in a channel

Now that we have a list of Channels, we can make another Video REST API call to get a list of videos in our new method GetVideos.  We build our requestUrl by appending /_api/VideoService/Channels(‘<channelid>’)/Videos.  Remember we got the Channel Id from our last API call.  Now this simply returns the metadata about the video.  After this, we still have one more call to get the Playback URL.

var requestUrl = string.Format("{0}/_api/VideoService/Channels('{1}')/Videos", videoPortalHubUrl, channelId);

The rest of the method is similar to GetVideoChannels

Get the video playback URL

For the purpose of our example, we’re also going to simply play the first Video in the Channel.  To get the Playback URL, we’ll need the Video Id as well as the Channel Id we retrieved earlier.  When it comes to streaming, we have a choice of either Smooth Streaming or HLS Streaming by specifying the streamingFormatType parameter on the Video REST API call.  HLS streaming requires one fewer API call so we are going to use that for the example today.  You may want to use Smooth Streaming for your application.  To use HLS Streaming, specify a value of 0.

var requestUrl = string.Format("{0}/_api/VideoService/Channels('{1}')/Videos('{2}')/GetPlaybackUrl('{3}')",

    new string[] { videoPortalHubUrl, channelId, videoId, streamingFormatType.ToString() });

The REST call will return a playback URL which we can then assign to the MediaElement

Playing the video

On the click handler of the Play button we added in the beginning, we make our calls into the VideoRepository class.  Once we get the Playback URL we binding it to the MediaElement and the video will start playing.  I also set a few parameters to turn on the transport controls and enable full screen mode.  You can set those as you like.

private async void button_Click(object sender, RoutedEventArgs e)

{

    VideoRepository videoRepository = new VideoRepository();

    string videoPortalUrl = await videoRepository.GetVideoPortalHubUrl();

    var videoChannels = await videoRepository.GetVideoChannels();

    string channelId = videoChannels[0].Id;

    var videos = await videoRepository.GetVideos(channelId);

    string videoId = videos[0].VideoId;

    var videoPlayback = await videoRepository.GetVideoPlayback(channelId, videoId, 0);

 

    mediaElement.Volume = 0;

    mediaElement.AreTransportControlsEnabled = true;

    mediaElement.IsFullWindow = true;

    mediaElement.Source = new Uri(videoPlayback.Value);

}

There you have it a (somewhat) quick and dirty way to play a video from the Office 365 Video Portal in Windows 10.  This should work on Windows 10 Mobile as well.  Here is what our app looks like when playing a video.

O365VideoAppPlayback

Source Code

As promised the source code is available on GitHub.  I may extend it in the future to include all of the data binding and improve the look.  Feel free to contribute to the repo as well.  If you make use of any of the code, you’ll want to add error handling of course.

Feel free to ask me any questions by leaving a comment.

Source code on GitHub

Follow me on twitter: @coreyroth

When we built dotnetmafia.com, we used one of the most common blog engines around Community Server by Telligent.  At the time Telligent had a great blogging platform that they provided free to technical bloggers.  They really did a service to the community.  Then one day, they decided to drop the free product and start charging for new versions even for community bloggers.  Now, people barely even remember the name Telligent and for good reason.  Cloud offerings like wordpress.com with their freemium model moved in and took over.

Moving to Azure

That said, my blog has been running on a Windows Server 2003 virtual machine with only 2 GB of ram since 2006 or so.  As old as my version of Community Server is now, it still works pretty well.  It did come out before the days of mobile devices so the master page I have could use some work.  It’s been serving up blog posts for years though without issue.

The virtual machine was hosted with my old employer, Isocentric Networks.  Isocentric is a small data center based in Tulsa, OK.  I learned all about racking, networking, and hosting while I worked there.  They have been nice enough to let me host my blog there all of these years.  I am truly thankful.

With Window Server 2003 no longer being supported as of last month though, it was time for the blog to move.  I created a new Windows Server 2012 R2 virtual machine in Azure and copied the database and everything over.  I was a little fearful that I might not be able to get Community Server to work in the new environment, but everything worked just fine.  I just created a .NET Framework 2.0 application pool and configured a new web site in IIS and everything worked fine.

Now, I have pointed the DNS entry for the site over to the Azure Virtual Machine and things seem to be running great.  If you see an issue, feel free to ping me on twitter @coreyroth.

Why DotNetMafia?

Over the years, many people have asked why DotNetMafia?  Well as with a lot of great things in life, the concept started while a few of us were sitting around at the bar for happy hour one day.  We were telling stories about how there were some recruiters in town that were less than professional.  Back then it wasn’t uncommon for a recruiter to lie to your face, make you lie on your resume, or just sent it to a client without even talking to you first.  We wanted to build a web site where we could rate recruiters and people could go talk about the good and bad things recruiters did.  So Kyle Kelin (a.k.a. theGodfather), came up with the concept and name.  Like all of the billion dollar ideas, we came up with back then, we only got about as far as purchasing the domain name. 

A lot of us were changing jobs back then (hence the recruiter thing).  I actually started the blog internally when we were all working at Dollar Thrifty Automotive Group.  .NET Framework 2.0 was in beta and I started it to teach the development team I led about the new features that were coming.  Back then it was simply called Corey’s .NET Tip of the Day.  It really wasn’t a blog though, it was really just an announcements list in SharePoint 2003.  I wasn’t really working with SharePoint much back then, but I thought it was a good tool at the time for what we were trying to accomplish.

When I left Dollar Thrifty at the end of 2005, I wanted to keep the content going so I moved it to a virtual machine I had at Isocentric Networks and hosted it at dotnettipoftheday.com.  I actually exported the contents of my announcements list into Excel and then imported into a SQL Server database.  I wrote my own custom blogging engine at the time and I used it for a while.

Now a year or so later, a few of the other ex-employees of Dollar Thrifty wanted a place to blog too.  Tony Kilhoffer set up a SharePoint 2003 server and I tried to use the blog platform there.  Unfortunately, we couldn’t ever get the content quite right so we gave up. 

Then we ended up with Community Server.  The nice thing about Community Server was it had the ability to import content from an RSS feed.  This made bringing in all of my old content quite easy.  If you look around the blog, you’ll notice we host for six different people: Cory Robinson, Kyle Kelin, James Ashley, Tony Kilhoffer, Kevin Williams, and myself.  None of them really blog much any more, but their content is still there.  We had all of the bloggers, but what were we to call this new site?  DotNetMafia.com.  A cheesy name that has worked well for us.

Why not move to a new blogging platform?  I definitely want to but it is a bit of a challenge.  Moving the content to another platform isn’t that difficult.  However, maintaining the existing URLs when moving to a new platform is difficult.  If I don’t maintain them, I’ll break the SEO of the site.  My top post every month is years old and talks about using PowerShell with SharePoint 2010.  The SEO is important so before I migrate anywhere, I need to have a solid solution to maintain those links.

with no comments
Filed under: