Friday, June 29, 2012

Upload Document to a doc set using Managed Client Object Model

Below function uploads any file to a docset using Client object modeling.


 public void UploadDocument(string siteurl, string listname, string docsetname, string filename)
        {
           
            using (ClientContext clientContext = new ClientContext(siteurl))
            {
                //Get Document List
                List documentsList = clientContext.Web.Lists.GetByTitle(HttpUtility.UrlDecode(listname));


                var fileCreationInformation = new FileCreationInformation();
                //Assign to content byte[] i.e. documentStream


                fileCreationInformation.Content = System.IO.File.ReadAllBytes( filename )); ;
                //Allow owerwrite of document


                fileCreationInformation.Overwrite = true;
                //Upload URL


                fileCreationInformation.Url = siteurl + "/" + listname + "/" + docsetname + "/" +  filename";
                Microsoft.SharePoint.Client.File uploadFile = documentsList.RootFolder.Files.Add(fileCreationInformation);


                uploadFile.ListItemAllFields.Update();
                clientContext.ExecuteQuery();


            }
        }

Call the above function as below

UploadDocument("https://testsite", "test Library", "My Doc Set", "C:\test.ppt");

if you look at the code above we are reading the bytes from the file(which is in the client machine) and uploading it using the Microsoft.SharePoint.Client.File class. 


Get doc set id by doc set name

If you want to upload any file programmatically to a doc set you need the id of that doc set. In my last post I showed how to create a new doc set using Managed Client Object model. Here I will post the code snippet how to get a doc set id.

We need to CAML Query to get the doc set id by its name. Below function returns the docset id when the docset name is passed


   public int GetDocSetID(string siteurl,string docsetname,string listname)
        {
            ClientContext context = new ClientContext(siteurl);
            context.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            Web site = context.Web;
            var list = context.Web.Lists.GetByTitle(HttpUtility.UrlDecode(listname));
            CamlQuery query = new CamlQuery();
            query.ViewXml = "@<Where><Eq><FieldRef Name='FileLeafRef' /><Value Type='File'>" + docsetname + "</Value></Eq></Where>";
            var items = list.GetItems(query);
            context.Load(list);
            context.Load(items);
            context.ExecuteQuery();
            return items[0].Id;


        }


Remember doc set is just a list item and there cant be more than one docset with the same name. So the CAML query always returns one item.

Add a Document Set using Managed Client Object Model

I love Client Object Modeling. SharePoint 2010 has made easy how to talk to the SharePoint objects from Client machines.

Adding a docset pro grammatically using Object modeling should be easy. I was trying to add a new doc set using Managed Client Object Model. Remember docset is nothing but a item in a list. And document libraries are again nothing but just a list with different look and feel. Below function creates a new docset with the defined content type.



public int AddDocSet(string siteUrl, string listName, string docSetContentTypeName, string newDocSetName)
        {
            ClientContext clientContext = new ClientContext(siteUrl);
            clientContext.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            Web web = clientContext.Web;
            List list = clientContext.Web.Lists.GetByTitle(listName);


            clientContext.Load(clientContext.Site);


            ContentTypeCollection listContentTypes = list.ContentTypes;
            clientContext.Load(listContentTypes, types => types.Include
                                              (type => type.Id, type => type.Name,
                                              type => type.Parent));


            var result = clientContext.LoadQuery(listContentTypes.Where(c => c.Name == docSetContentTypeName));


            clientContext.ExecuteQuery();


            ContentType targetDocumentSetContentType = result.FirstOrDefault();


            ListItemCreationInformation newItemInfo = new ListItemCreationInformation();
            newItemInfo.UnderlyingObjectType = FileSystemObjectType.Folder;
            newItemInfo.LeafName = newDocSetName;
            ListItem newListItem = list.AddItem(newItemInfo);


            newListItem["ContentTypeId"] = targetDocumentSetContentType.Id.ToString();
            newListItem["Title"] = newDocSetName;
            newListItem.Update();


            clientContext.Load(list);
            clientContext.ExecuteQuery();
            return newListItem.Id;


        }


Call this function by passing the appropriate site url, list name , docsetcontent type, and the doc set name.

Copy Slides to Presentation outside of Slide Library Context

Slide Library is a powerful document management feature of SharePoint 2010 but still very much underutilized. You can publish slides from you local machine to this library directly. Slides are stored as .pptx files. To do this. right click the ppt and click "Publish slides" and enter the slide library URL in the address box. This is fairly easy to do and very useful for someone who wants to publish only parts of their ppt file.

The another important feature of Slide Library is the "Copy Slides to Presentation". You can select the slides from the library and on click of the "Copy Slides to Presentation" button it will create a new presentation with the selected slides or it will add to a existing presentation based on your selection.  

This is a very cool feature that I wanted to use in my custom webparts and in some other pages. "Copy Slides to Presentation" button is a activex control embedded in the slides library. I was digging into how this is working. I was looking at the sharepoint js files and found that 1033/SLDLIB.js is the file that is called when you click the button. If you look at the file they get the pptx file URLs and form a array and pass it to the active control. I tried to replicate the same in my custom webpart and it worked amazingly!

1. First add the below reference to the js file 
  <script type="text/javascript" src="/_layouts/1033/SLDLIB.js"></script>
2. Place the Activex Control in the page as below.

<object id="ppactivex" 
classid="clsid:99098758-CB85-4a90-924F-F21898796281" style="visibility:hidden" OnError="SetActiveXStatus(false);">
</object>

3.Copy the below vbscript function to the page.

<script type="text/vbscript">
function CallInsertSlides(Selected)
    arrSelected = Split(Selected, ",", -1, 0)
    set objx = Document.ppactivex
    objx.InsertSlidesFromSlideLibrary arrSelected
End function
</script>

4. Now just call the CallInsertSlides function from you javascript code as below

CallInsertSlides("/Slides%20Management/sureshtest.pptx");

In the above function I have passed only one URL. You can form a array of URLs from the items selected and pass it to the function as below. 

.S4-itm-cbx is the class of the checkboxes in the page.

$(".s4-itm-cbx:checked").each(function () {
            var parentcell = $(this).parent();
            var hyperlinkparent = $(parentcell).next().next().children();
            selItems[cSelectedSlides++] = GetEscapedUrl(portalurl + $(hyperlinkparent).attr("href"));           
        });

CallInsertSlides(selItems);
When the function CallInsertSlides is called it will open a dialog box to copy the presentation.
Happy coding !!!!.


Update: Below is the entire sample aspx page I have created as there were requests to provide the sample.




<%@ Assembly Name="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c"%> <%@ Page Language="C#"

Inherits="Microsoft.SharePoint.WebPartPages.WikiEditPage"

MasterPageFile="~masterurl/default.master" meta:progid="SharePoint.WebPartPage.Document"

meta:webpartpageexpansion="full"       %>
<%@ Import Namespace="Microsoft.SharePoint.WebPartPages" %> <%@ Register

Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls"

Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c" %> <%@ Register Tagprefix="Utilities"

Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0,

Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Import

Namespace="Microsoft.SharePoint" %> <%@ Assembly Name="Microsoft.Web.CommandUI,

Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages"

Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral,

PublicKeyToken=71e9bce111e9429c" %>
<asp:Content ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
<SharePoint:ProjectProperty Property="Title" runat="server"/> -
<SharePoint:ListItemProperty runat="server"/>
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">
<span>
<SharePoint:DocumentFolderName runat="server" id="PageFolderName"

AppendSeparatorArrow = "true"/>
</span>
<span class="ms-WikiPageNameEditor-Display" id="wikiPageNameDisplay" runat="server">
<SharePoint:ListItemProperty runat="server"/>
</span>
<span class="ms-WikiPageNameEditor-Edit" style="display:none;" id="wikiPageNameEdit"

runat="server">
<asp:TextBox id="wikiPageNameEditTextBox" runat="server"/>
</span>
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderPageDescription" runat="server">
<SharePoint:UIVersionedContent runat="server" UIVersion="4">
<ContentTemplate>
<SharePoint:ProjectProperty Property="Description" runat="server"/>
</ContentTemplate>
</SharePoint:UIVersionedContent>
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderPageImage" runat="server">
<SharePoint:AlphaImage ID=onetidtpweb1 Src="/_layouts/images/wiki.png" Width=145

Height=54 Alt="" Runat="server"/></asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">


<script type="text/javascript"></script>

<meta name="CollaborationServer" content="SharePoint Team Web Site" />
<script type="text/javascript">
var navBarHelpOverrideKey = "WSSEndUser";
</script>
<SharePoint:RssLink runat="server"/>
<SharePoint:UIVersionedContent UIVersion="4" runat="server"><ContentTemplate>
<SharePoint:CssRegistration runat="server" Name="wiki.css" />
</ContentTemplate></SharePoint:UIVersionedContent>
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderMiniConsole" runat="server">
<SharePoint:FormComponent TemplateName="WikiMiniConsole" ControlMode="Display"

runat="server" id="WikiMiniConsole"/>
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderLeftActions" runat="server">
<SharePoint:RecentChangesMenu runat="server" id="RecentChanges"/>
</asp:Content>
<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">



<SharePoint:UIVersionedContent runat="server" UIVersion="3"

Id="PlaceHolderWebDescription">
<ContentTemplate>
<div class="ms-webpartpagedescription"><SharePoint:ProjectProperty

Property="Description" runat="server"/></div>
</ContentTemplate>
</SharePoint:UIVersionedContent>
<asp:UpdatePanel
  id="updatePanel"
  runat="server"
  UpdateMode="Conditional"
  ChildrenAsTriggers="false">
<ContentTemplate>
<SharePoint:VersionedPlaceHolder UIVersion="4" runat="server">
<SharePoint:SPRibbonButton
id="btnWikiEdit"


RibbonCommand="Ribbon.WikiPageTab.EditAndCheckout.SaveEdit.Menu.SaveEdit.Edit"
runat="server"
   Text="edit"/>
<SharePoint:SPRibbonButton
id="btnWikiSave"


RibbonCommand="Ribbon.WikiPageTab.EditAndCheckout.SaveEdit.Menu.SaveEdit.SaveAndStop"
runat="server"
   Text="edit"/>
<SharePoint:SPRibbonButton
id="btnWikiRevert"


RibbonCommand="Ribbon.WikiPageTab.EditAndCheckout.SaveEdit.Menu.SaveEdit.Revert"
   runat="server"
Text="Revert"/>
</SharePoint:VersionedPlaceHolder>
<SharePoint:EmbeddedFormField id="WikiField" FieldName="WikiField"

ControlMode="Display" runat="server"></SharePoint:EmbeddedFormField>
<WebPartPages:WebPartZone runat="server" ID="Bottom"

Title="loc:Bottom"><ZoneTemplate></ZoneTemplate></WebPartPages:WebPartZone>
</ContentTemplate>
<Triggers>
   <asp:PostBackTrigger ControlID="WikiField" />
   <asp:PostBackTrigger ControlID="btnWikiRevert" />
   <asp:PostBackTrigger ControlID="btnWikiSave" />
</Triggers>
 </asp:UpdatePanel>
 <script type="text/javascript" src="/_layouts/lazard/scripts/jquery-1.7.2.js"></script>
  <script type="text/javascript" src="/_layouts/lazard/1033/SLDLIB.js"></script>
<script type="text/javascript">

$(document).ready(function(){
        CallInsertSlides(serverurl+"/Slides%20Management/sureshtest.pptx");
});

   


</script>
<script type="text/vbscript">
function CallInsertSlides(Selected)
    arrSelected = Split(Selected, ",", -1, 0)
    set objx = Document.ppactivex
    objx.InsertSlidesFromSlideLibrary arrSelected
End function
</script>

<input type="button" value="Copy to presentation slides" onclick="javascript:CallPPT();">
<object id="ppactivex"
classid="clsid:99098758-CB85-4a90-924F-F21898796281" style="visibility:hidden"

OnError="SetActiveXStatus(false);">
</object>

</asp:Content>

Wednesday, April 4, 2012

Hide Site Action and Site Settings link

We know there is a straight way to add a Custom action under a Site Actions menu or in a Site settings page. You just need to develop a feature with a custom action and deploy it.

I got a requirement to hide a custom action under the Site Actions menu. I initially thought of doing it in using my familiar JQuery hack and hide dirty way. Then something I found that there is a straight way available in SharePoint. Just develop a feature with a element file and add the below code.

<HideCustomAction
  GroupId = "SiteAdministration"
  HideActionId = "DeleteWeb"
  Id = "HideDeleteWeb"
  Location = "Microsoft.SharePoint.SiteSettings">
</HideCustomAction>
Here in the above code:

GroupId: Self explanatory for a developer. You can find the group id herehttp://msdn.microsoft.com/en-us/library/bb802730.aspx
HideActionId: The id of the custom action that needs to be hidden. This can be found if you search in the features folder(in element file).
Id: Some Unique id(optional).
Location: From Where is should be hidden.
Hope this helps someone.