Wednesday, June 4, 2014

Retrieve thumbnail from uploaded video in a Document Library

After a lot of months ignoring SharePointPills I decided to post a new blog entry with an interesting situation that happened in my current project.

The goal was to generate an image from a video used as a thumbnail or splash screen for an external web video player (FlowPlayer in this case, which works really good in almost every single browser). The video was meant to be allocated in a document library that, for external reasons, don't have the Video Content Type. This means that we were not able to access all the nice metadata that SharePoint 2013 generates for you when you upload a video, including a thumbnail for the video located in /[current_path]/[video_name]/Preview%20Images/[video_name].png. So my idea was to copy this video into the OOTB PublishingImages library, which contains the Video Content Type, and then get the thumbnail. Unfortunately using the File.CopyTo method I was able to get only a normal file uploaded into this library. No metadata at all. Even setting specifically the Video Content Type to the item.

After looking for a solution, crawling a thousand blogs and searching in MSDN I found something (a little bit hidden) that could work:  http://msdn.microsoft.com/en-us/library/microsoft.office.documentmanagement.videosets.videoset_members(v=office.15).aspx, and specially this, VideoSet.MigrateVideo: http://msdn.microsoft.com/en-us/library/microsoft.office.documentmanagement.videosets.videoset.migratevideo(v=office.15).aspx

It seems that MigrateVideo generates all the necessary metadata (including thumbnails) for your SPFile video. So I modified my code and the result was something like this:

var videoFile = web.GetFile(itemVideoId);
SPList publishingImagesList = web.GetList("/PublishingImages");

var fileExtension = new FileInfo(videoFile.Name).Extension;
videoFile.CopyTo("/PublishingImages/" + videoFile.Name, true);

var query = new SPQuery();
query.Query = string.Format("{0}", videoFile.Name);
var copiedFiles = publishingImagesList.GetItems(query);
var copiedFile = copiedFiles[0];

// Generate video metadata (thumbnail, etc)
var copiedVideo = VideoSet.MigrateVideo(copiedFile.File);
copiedVideo.SystemUpdate();

Now you can go to your PublishingImages library and see that your video has all the automatic metadata for Video Content Type, including the thumbnail, that you can easily get back using something similar to the code below:

SPFolder thumbnailVideoFolder = web.GetFolder("/PublishingImages/" + copiedVideo.Name + "/Preview Images/");
// Get single thumbnail generated
if (thumbnailVideoFolder.ItemCount > 0)
{
var thumbnailFile = thumbnailVideoFolder.Files[0];
}

As I said, there is not a lot of information about this on the Internet, so I hope this helps someone else.

Cheers!

Sunday, October 14, 2012

SharePoint Server 2013 Preview Setup guide

In this short post I am not going to explain how to set up a SP2013, but it is only to definitely recommend this great installation guide from CriticalPath: http://www.criticalpathtraining.com/_layouts/CriticalPath.Website/DownloadRedir.aspx?type=MemberDownload&id=96

I have just followed this step-by-step guide and apart of the basics (DC + DEV environments, accounts, and so on), it is really helpful to setup the new features, like the App Hosting or the Workflow Manager. Moreover, it includes several powershell scripts to make easier the creation of the AD accounts, disable loopback check and much more. It is also updated regularly.

Maybe it sounds like advertising, but I guess the good things need to have visibility. You need to be registered as member, yet that’s a minor snag. Thanks to Andrew Connell and Ted Pattison for this (and Adis Jugo for sharing).

Sunday, June 3, 2012

Hide Site Collection’s root link in breadcrumb top navigation

Although you can set up a Site Collection so the members of the internal Sites are not able to access the root of the Site Collection, they are still able to have this hateful “You don’t have permissions to this page” SharePoint error. Why grant the access to this page when you can just hide this link in the breadcrumb top navigation?

The goal of this entry is to hide the root navigation item (the root of the Site Collection), so the user is not able to click there, modifying the Site Collection’s master page in SharePoint Designer. I must admit that I don’t like this tool, and my recommendation would be create a new master page, deploy it, and then in the feature receiver set our custom master page as the default one. Anyway, as for the time being, I will use the SPDesigner’s approach.

Here are the steps:

  • Open and modify the current master page using SharePoint Designer or editing it and then uploading to the master page gallery.
  • Locate the control SharePoint:ListSiteMapPath.
  • Add the property ParentLevelsDisplayed as follows ParentLevelsDisplayed="0”

The final control should look like:


runat="server"
SiteMapProviders="SPSiteMapProvider,SPContentMapProvider"
RenderCurrentNodeAsLink="false"
PathSeparator=""
CssClass="s4-breadcrumb"
NodeStyle-CssClass="s4-breadcrumbNode"
CurrentNodeStyle-CssClass="s4-breadcrumbCurrentNode"
RootNodeStyle-CssClass="s4-breadcrumbRootNode"
NodeImageOffsetX=0
NodeImageOffsetY=353
NodeImageWidth=16
NodeImageHeight=16
NodeImageUrl="/_layouts/images/spoverrides/fgimg.png"
HideInteriorRootNodes="true"
SkipLinkText=""
ParentLevelsDisplayed="0"/>

Monday, May 14, 2012

PlanB. event: explain – explore – experience System Center 2012

My company is arranging a System Managament event in Cologne and Stuttgart in a few weeks. Here you will have the chance to glimpse live demos, business cases and a deeper look into the architecture, functionality and design philosophie of System Center 2012. There will be Microsoft and PlanB experts to explain and answer all your questions.

This FREE workshop is in german during the whole day these dates:

  • 24.05.2012 – Stuttgart
  • 11.06.2012 – Cologne

From my point of view this is going to be a unique event about System Center in Germany, so if you are interesed and want to get more info or register, just drop a line or call anke.neumann@plan-b-gmbh.com (+49 7361-55 621-0).

image

Saturday, May 5, 2012

Add Blog and Discusssion Board tabs programmatically in Newsgator Social Sites 2010

Newsgator Social Sites 2010 is a great social add-on for SharePoint 2010 with a lot of features (IMHO maybe too many) and an extensive API to manage programmatically the Activity Stream, the creation of Communities, the Followers of a Community… they have a great support community (https://engage.newsgator.com) where, if you are a partner, you can register yourself to ask the real experts and access special documentation.

In my current project I needed to create a SiteDefintion with several default Newsgator tabs. It seems really easy to go to the Setup page and create a new Blog or Discussion Board using the UI, but to be honest it was really hard to find any kind of documentation about how to do it programmatically (in fact it was impossible).

image

My idea was to provide a SPWebEventReceiver event handler and add in the WebProvisioned event the tabs creation (they have special names, special webparts inside…). Within the following code and guessing what was Newsgator internally doing to add the tabs in the UI (like creating a new “blog” or creating a new “calendar” list), I was able to add them.

/// 
/// A site was provisioned.
///

public override void WebProvisioned(SPWebEventProperties properties)
{
base.WebProvisioned(properties);
SPWeb web = properties.Web;
if (web.WebTemplate.Equals("mySiteDefinition", StringComparison.InvariantCultureIgnoreCase))
{
// Blog
SPWeb blog = web.Webs.Add("news", "News", "News description", 1033, "BLOG#0", false, false);

var tabs = new List();
tabs.Add(new CommunityTab()
{
Id = 0,
CapabilityType = CapabilityType.Overview,
Name = "Home",
Enabled = true,
DisplayType = ServerUI.OverviewTab,
TabIndex = 0
});
tabs.Add(new CommunityTab()
{
Id = 1,
CapabilityType = CapabilityType.List,
Name = "Calendar",
Enabled = true,
DisplayType = "Calendar",
TabIndex = 1,
TemplateType = SPListTemplateType.Events
});
tabs.Add(new CommunityTab()
{
Id = 2,
CapabilityType = CapabilityType.DiscussionBoards,
Name = "Forums",
Enabled = true,
DisplayType = ServerUI.CommunityTabType_DiscussionBoards,
TabIndex = 2,
});
tabs.Add(new CommunityTab()
{
Id = 3,
CapabilityType = CapabilityType.Web,
Name = "News",
Enabled = true,
TabIndex = 3,
DisplayType = ServerUI.CommunityTabType_Blog,
SubWebId = blog.ID
});

SocialGroupPrivacyLevel privacyLevel = SocialGroupPrivacyLevel.Private;

CommunitySetup newsgatorSetup = new CommunitySetup();
newsgatorSetup.SaveSetupConfiguration(web.Site, web, tabs, web.Title, true, privacyLevel, false);

web.Features.Add(CommunityGlobals.WebCommunityFeature, true); // Convert to community before add blog
web.Features.Add(CommunityGlobals.WebScopedSkinningFeature, true); // Skin for NG communities

web.Dispose();
}
}

Anyway, with this code I had 2 serious problems:



  • the blog linked to the “News” tab didn’t have the top Newsgator navigation menu… it seemed like it was an isolated blog, and that was not what I wanted (maybe I needed a NG feature?)
  • the discussions board didn’t show up… and the “boards.aspx” page that it’s deployed using the UI was simply not there… (maybe again I needed a NG feature?)

Because of that lack of documentation, I was “forced” to glimpse the DLLs using ILSpy (great application when you are in trouble) and I realized I needed to change the code a little bit:



  • activate the NewsGator.Communities_NewsGator.Community.Context feature in the blog to enable the top navigation menu.
  • activate the NewsGator.Communities.BoardsPage feature in my site, which deploys the boards.aspx page.
  • add the LinkUrl property in the Discussions Boards page to “boards.aspx

At the end, my successful code looked like:

/// 
/// A site was provisioned.
///

public override void WebProvisioned(SPWebEventProperties properties)
{
base.WebProvisioned(properties);
SPWeb web = properties.Web;
if (web.WebTemplate.Equals("mySiteDefinition", StringComparison.InvariantCultureIgnoreCase))
{
// Blog
SPWeb blog = web.Webs.Add("news", "News", "News description", 1033, "BLOG#0", false, false);

var tabs = new List();
tabs.Add(new CommunityTab()
{
Id = 0,
CapabilityType = CapabilityType.Overview,
Name = "Home",
Enabled = true,
DisplayType = ServerUI.OverviewTab,
TabIndex = 0
});
tabs.Add(new CommunityTab()
{
Id = 1,
CapabilityType = CapabilityType.List,
Name = "Calendar",
Enabled = true,
DisplayType = "Calendar",
TabIndex = 1,
TemplateType = SPListTemplateType.Events
});
tabs.Add(new CommunityTab()
{
Id = 2,
CapabilityType = CapabilityType.DiscussionBoards,
Name = "Forums",
Enabled = true,
DisplayType = ServerUI.CommunityTabType_DiscussionBoards,
TabIndex = 2,
LinkUrl = "boards.aspx"
});
tabs.Add(new CommunityTab()
{
Id = 3,
CapabilityType = CapabilityType.Web,
Name = "News",
Enabled = true,
TabIndex = 3,
DisplayType = ServerUI.CommunityTabType_Blog,
SubWebId = blog.ID
});

SocialGroupPrivacyLevel privacyLevel = SocialGroupPrivacyLevel.Private;

CommunitySetup newsgatorSetup = new CommunitySetup();
newsgatorSetup.SaveSetupConfiguration(web.Site, web, tabs, web.Title, true, privacyLevel, false);

blog.Features.Add(new Guid("b084760c-452e-419d-8639-babb5c0a4283"), true); // NewsGator.Communities_NewsGator.Community.Context feature

web.Features.Add(CommunityGlobals.WebCommunityFeature, true); // Convert to community before add blog
web.Features.Add(CommunityGlobals.WebScopedSkinningFeature, true); // Skin for NG communities
web.Features.Add(new Guid("62ab07ce-3f9f-441a-80ce-b14beae97dd4"), true); // NewsGator.Communities.BoardsPage feature

blog.Dispose();
web.Dispose();
}
}

And it added the wished tabs, working properly.


image


Hope this helps someone!

Friday, January 13, 2012

Attributes of a socially optimized business

Lately I have worked in several projects where I had to develop some kind of social plugins for SharePoint, or integrate any of the available products to “socialize” SharePoint, or identify the real needs of the client and the better solution for them. It seems that more and more companies realize that a good relationship between their co-workers means better performance and better results.

Anyway, I still find a lot of managers (especially in Germany) that are not able to see the benefits of this approach. They are stuck in the e-mail age. They think that this is just a waste of time and of course, a waste of money –as these solutions are not especially cheap-.

For those people, I found this nice infographic signed by Dachis Group. There are a lot of new/old ideas… I especially like the massive shift from “me” to “we” sentence and the impact on the global workforce.