Tuesday, February 19, 2013

Calling Winform function from SharePoint page.

Consider a scenario like passing a value from SharePoint page(ex. document library URL) or something to a windows form application function and execute a code based on the value passed. Web page and windows form may seem like two completely non-linked entities. But there is a way to establish connection to and fro.
 
Below are the steps to call a windows form function from a SharePoint page. 

1. Create a Win formand add a webbrowser control. Give the SharePoint site URL as the webbrowser control URL property.

2. Inside the Win formadd the ComVisibleAttribute to the class level.

 [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class Save : System.Windows.Forms.Form
    {}

3. Add the ObjectForScripting property. This will act as a interface between the webpage and Win form

        [BrowsableAttribute(false)]
        public Object ObjectForScripting { get; set; }


4.  Add a function in Win form with a parameter just for test purpose. We will call this function from the SharePoint page.


        public void Test(String docurl)
        {
          MessageBox.Show(docurl);
        }

5. Now in the SharePoint page in the aspx page(if its an application page) call the Winform function by calling the below javascript code.

window.external.Test('url');

This will call the parent WinForm function and popup the message box.

6. To call this in .cs file code register with client script like below

this.Page.ClientScript.RegisterStartupScript(this.GetType(), "opendoc", "window.external.Test('" + locationpath + "/" + docname.Text);", true);


Tuesday, January 8, 2013

File not found exception in Office 2010 addin / ClientContext Code not executing

When we add any reference dlls(say in the example Microsoft.SharePoint.Client dll)  in Office 2010 addin and package it using Click once and install it in client machine it gives an


System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.SharePoint.Client, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c' or one of its dependencies. The system cannot find the file specified.

File name: 'Microsoft.SharePoint.Client, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c'

   at WordAddIn1.Form1.UploadDocument(Byte[] docbytes)

   at WordAddIn1.Form1.button1_Click(Object sender, EventArgs e)



Assembly manager loaded from:  C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscorwks.dll

Running under executable  C:\PROGRA~1\MICROS~2\Office14\WINWORD.EXE

Fix:


Add the reference dlls in the root of the project like below and publish again. This took me a day to figure out :(.

There were no good article to debug and fix this issue in msdn forums so thought this might be useful to someone

Upload a word document from Office 2010 plugin to SharePoint Doc library

When we create a Office 2010 addin  say for word and try to access SharePoint resources from it we know pretty much better option is 'Client Object model'.

1. Create a new Word 2010 addin and a button called 'Save'
2. Include a win form and add a button called "Upload doc"
3. Call this form on click of Save button.

4 Below code is to upload a current open word document in Office 2010 to a SharePoint site without saving locally on click of Upload Doc button.



 public void UploadDocument(byte[] docbytes)
        {

            ClientContext clientContext = new ClientContext("http://sharepointsiteurl/");

            List documentsList = clientContext.Web.Lists.GetByTitle("Events");

            var fileCreationInformation = new FileCreationInformation();

            fileCreationInformation.Content = docbytes;

            fileCreationInformation.Overwrite = true;

            fileCreationInformation.Url = "http://sharepointdoclibrarylocation/la.doc";
            Microsoft.SharePoint.Client.File uploadFile = documentsList.RootFolder.Files.Add(fileCreationInformation);
            uploadFile.ListItemAllFields.Update();
            clientContext.ExecuteQuery();
}

and on button click below code grabs the current document content as byte array and calls the above function to upload it to SharePoint

 private void button1_Click(object sender, EventArgs e)
        {

            Microsoft.Office.Interop.Word.Document doc = Globals.ThisAddIn.Application.ActiveDocument;

            doc.ActiveWindow.Selection.WholeStory();
            doc.ActiveWindow.Selection.Copy();

            IDataObject data = Clipboard.GetDataObject();

            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(data.GetData(DataFormats.Html).ToString());


            MessageBox.Show("Before Upload");
            try
            {
                UploadDocument(bytes);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());

            }
            MessageBox.Show("Uploaded to SharePoint Successfully");

        }

The difference from other solutions  is here we dont save the document anywhere locally instead directly grabbing the content as byte array and uploading it to SharePoint doc library which will improve the performance drastically.

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.

Wednesday, August 31, 2011

Error updating User Profile property on commit

Error: Updates are currently disallowed on GET requests. To allow updates on a GET, set the 'AllowUnsafeUpdates' property on SPWeb.


I saw many people has came across this is error when updating user profile property values, but I couldnt find a solid solution to this issue. So thought of posting a article on this one. The error may be misleading. Many think web.AllowUnsafeUpdates=true will solve the issue. But it wouldn't because this update will not have any impact on the User Profile Service application. 

Try the below code, it should solve the issue.





The difference here is SPContext.Current.Web.AllowUnsafeUpdates=true will update the current user profile to allow updates. Also make sure that there is no context given when Instantiating UserProfileManager object as it gets populated automatically when run on a personal site context. 

Tuesday, August 30, 2011

Hide Any Site template in Create Site section- SharePoint 2010

We may need to block creation of sites based on certain templates. For example my organisation does not like the employees to create blog site of their own in their personal mysite. 

There is a quick and dirty way to modify the webtemp.xml file to hide the template we dont want to show up. Its never a good approach to modify the default SharePoint config files. Also webtemp.xml file modification will affect farm level settings.

In SharePoint 2010 we can hide the templates of desired nature from the Create site page so no one can create site based on the particular template. This can by achieved by creating a new feature with a event handler code.

1. Create a new Empty SharePoint project.
2. Add a new feature element.Scope it to Web
3. Add a new event receiver to that feature element.
4. Paste  the below code(this code will hide the blog template at the site level)

public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
SPWeb web = properties.Feature.Parent as SPWeb;
SPWebTemplateCollection existingWebTemps = web.GetAvailableWebTemplates(1033); ;
Collection<SPWebTemplate> newWebTemps = new Collection<SPWebTemplate>();
for (int i = 0; i < existingWebTemps.Count; i++)
{
if (!existingWebTemps[i].Title.ToLower().Contains("blog"))
{
newWebTemps.Add(existingWebTemps[i]);
}
}
web.SetAvailableWebTemplates(newWebTemps, 1033);
web.Update();
}

5.Deploy the solution and activate the feature. You will no longer see the blog template visible to the user in the Create site page.

6. To revert back and to show all the templates use the below code at Feature deactivating event.

 web.AllowAllWebTemplates() ;

Saturday, August 6, 2011

Get User profile using Console App- Object reference error at Server context

Today I was trying to retrieve user profiles properties using a console application. Its a very simple application just pulls some metadata from the userprofilesmanager. Previously I have get and set profile properties in my SharePoint application many times. Thought it would be a piece of cake for me. Not though.

This is the code I have written in the program.cs. But to my surprise I was getting object reference error. I was thinking that url might be the wrong thing. But its not.


            SPSite site = new SPSite("http://suresh-pc:100/default.aspx");
            ServerContext context = ServerContext.GetContext(site);
            UserProfileManager upm = new UserProfileManager(context);
            UserProfile profile = upm.GetUserProfile("moss/suresh");

This error is a misleading one. You dont have permission to pull data from User Profile Service application basically.

Go to Central Admin- Manage Service applications- Click User Profile Service Application(click the row not the link).- In the ribbon select Manage Permmissions


Provide full permission for the user trying to access the User profile manager.

Build the application and run again.

Saturday, July 16, 2011

SharePoint 2010 Content Editor webpart

I am a very big fan of Content Editor Webpart in Moss 2007. I have done many site customization's using CEWP in SharePoint 2007. Place a new html file, hack DOM elements using JQuery and modify the html elements, javascript etcs., I almost love it. Even I have developed a complete site using few CEWP's in SharePoint 2007.

I was hoping SharePoint 2010 would offer much more functionality to CEWP. But to the sad part it has worsened it usability. When I first tried inserting a CEWP in my SharePoint 2010 site, I virtually struggled to use it. I was trying to figure our how to insert my custom html. There was no Source editor in WebPart editor panel.

Edit Html source has been moved to the Ribbon. You have to click the "HTML-EditHTMLSource" and place your html.


And the worst part is now you cannot place any javascript code in the source editor(edit html source).

To place a javascript code you need to create a text file or html file and put your code there. Save it to some document library and link the file as show below in the editor pane


I like it in one way. We can checkin the code in Source control and deploy the text file or html file to the layouts folder and we can link it in our webpart so that we can have a backup of the code.

Friday, July 15, 2011

Custom Workflow Activity for SharePoint Designer 2010

Back in Moss 2007 we had the feature of creating a new custom activity for SharePoint designer. I never tried that. Yesterday I had to present a POC to a customer on Custom activity for SharePoint designer 2010. The requirement is pretty simple.

User will be presented with a simple list. On creating of a new item, a approval workflow will be triggered. On approval, a new subsite has to be created. So I thought creating a custom activity in designer and using that to create a designer workflow would to do the trick.

I will describe with steps to create a custom activity for a SharePoint designer 2010 below. Since creating a approval workflow is simple I m not going to cover it :-)

1. Open Visual Studio
2. Select the “File->New->Project”
3. For template, select “Workflow->Workflow Activity Library” ( If you don't see this template, then target your environment to .Net 3.5.)
4. For Name, type “CustomActivities”
7. Rename Activity1.cs to CustomAction.cs
8. Right click the project, select “Add Reference”
9. Add the following references:
o C:\program files\common files\microsoft shared\web server
extensions\14\isapi\Microsoft.SharePoint.dll

I dont want to jump into full code directly. Lets go Step by Step.

Create a new function which creates new site




To make your custom code we need to override the Execute method of System.Workflow.Activities.
Call our CreateSite() function within the Execute method.



We have created a simple activity which is good enough to create a new SharePoint site. But if you notice I have hardcoded the siteTitle and siteURLRequested. Not good practice ah..

Lets create a new set of properties to get and set values for our title and url parameters. Before that to make the properties to be picked by the SharePoint designer we need to create Dependency properties as below.


   public static DependencyProperty TaskTitleProperty = DependencyProperty.Register("TaskTitle", typeof(string), typeof(CustomAction));

        [Category("Cross-Site Actions"), Browsable(true)]
        [DesignerSerializationVisibility
          (DesignerSerializationVisibility.Visible)]
        public string TaskTitle
        {
            get
            {
                return ((string)
                    (base.GetValue(CustomAction.TaskTitleProperty)));
            }
            set
            {
                base.SetValue(CustomAction.TaskTitleProperty, value);
            }
        }

Note that we need to prefix the DependencyProperty with the word "Property" else VS2010 is going to shout at you.

Now use the dependency property created in our CreateSite method. Overall code looks like below.


So create another dependency property for siteUrlRequested as well which i m not doing here. Sign the assembly and build it. Place the assembly in GAC using gacutil.exe(never  install manually).

We are done with the coding part. Now lets register our newly created activity with the SharePoint designer.

If you navigate to 14 hive folder under 1033/Workflows/ you will find MOSS.ACTIONS and WSS.ACTIONS.

As a good housekeeping we will create a new ACTIONS file. Say CustomAction.ACTIONS.

Place the below xml in it to register our custom activity.


<WorkflowInfo>
  <Actions Sequential="then" Parallel="and">
     <Action Name="Create Site"
    ClassName="CustomActivities.CustomActions"
    Assembly="CustomActivities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a3170baa21b0a3e9"
    AppliesTo="all" Category="Custom Site Actions">
        <RuleDesigner 
           Sentence="Create a Site titled %1">
           <FieldBind Field="TaskTitle" DesignerType="TextArea" 
              Id="1"/>
        </RuleDesigner>
         <Parameters>
            <Parameter Name="TaskTitle" Type="System.String, mscorlib" 
              Direction="In" />
         </Parameters>
     </Action>
  </Actions>
</WorkflowInfo>

Save the file and close.  We have a very last step that to register our dll as a Authorized type with my webapplication. Navigate to web.config in the file system and make the below entry.

<authorizedType Assembly="CustomActivities, Version=1.0.0.0, 
   Culture=neutral, PublicKeyToken=a3170baa21b0a3e9"     
   Namespace="CustomActivities" TypeName="*" Authorized="True" />
Save the web.config. There you go..
Perform and IISReset and load the designer. You will see a new activity added under "Custom Site Actions"

Saturday, June 11, 2011

What does IISReset really do

IISReset- perhaps the first lesson every SharePoint developer and administrators learn.
But when we start to do extreme programming(really lol), we eventually forget to do this.. cool lemme come to the meat of the subject..

Last week I have to support from development side for a uat deployment of our new solution. Every thing worked well in my environment as always. My development environment is a standalone farm. testing, uat and prod are medium farms..

We deployed the code. loaded the site..Some code error..ahhh.. i could see clearly from the error that the new code is not referred by the page. We did redeployment as I insisted  confidently that Web hosting team didn't do the deployment as I specified in the install notes. Whenever something go wrong then its other mistake. lol...

So we deployed the solution..again same error. Now Web hosting team hit me back stating its my error.

on multiple refresh of the page, i saw the site loading correctly on few instances. ahhhh i caught the culprit. "DLL caching". I asked to do IISReset on all the WFE's. It worked.

So whats the issue.

Whenever we deploy a new code which has a dll we probably need to do a IISReset.
You know why, SharePoint when hosted in IIS caches the dll from GAC and renders the page from it. So we have to tell the GAC to take the new dll from GAC after new deployment of our code.

Do we need to do IISReset on all new deployment. Answer is no.

1. When we do partial trusted solution SharePoint automatically picks up the new dll from the bin. We dont need an IISReset.
2. When we deploy features, we dont need it unless and until it doesn't has any code.

Most of the prod servers doesn't allow us to do IISReset. Then how to tell my IIS to take the new dll from the GAC.

Use the below script to refresh the application pool.


Option Explicit
'*** spsapppoolrecycle.vbs
'*** Script to recycle Sharepoint Portal Server application pool
'*** For use when deploying updated version of Webparts in the GAC
'*** Author: Michael Christensen, mac@landscentret.dk
'*** Provided AS IS with no warranties
'*** Heavily based on this posting by David Wang:
'*** http://tinyurl.com/4k26n
Const WEBSITEID = 1
Dim objApp
Dim AppPoolId
Dim objAppPool
Set objApp = GetObject("IIS://localhost/w3svc/" & WEBSITEID  & "/root")
AppPoolId = objApp.AppPoolId
WScript.Echo "AppPoolID: " & AppPoolId
Set objAppPool = GetObject( "IIS://localhost/w3svc/AppPools/" + AppPoolId )
objAppPool.Recycle()
WScript.Echo "AppPool recycled."

The script assumes that Sharepoint is installed on the virtual server with ID 1. This will usually be the case, otherwise the actual ID could probably be determined programmatically.

Probably next time when you deploy the new code,,think whether is necessary to do an IISRESET after deployment.

Saturday, May 14, 2011

Blank SharePoint Site in Windows 7

Another issue with SharePoint 2010 installation in Windows 7. When I create a new site collection through central administration and browse through the page, it shows a blank page. Even sometimes I receive the blank page when I open Central administration. Weird :-(

After doing many changes and I have even reinstalled the farm to get rid of this issue. No luck. After a long time I found the issue is with the authentication.

to make the sites to work do the following.
1. go to IIS : cmd-inetmgr.
2. Go to your site collection.
3. Click Authentication


4.Right click Basic authentication and enable it.
5. There you go..refresh the page..you will see you sites.. bravo..

cannot connect to configuration database

I have installed SharePoint 2010 in Windows 7. I had to do many configuration changes to make it work. Not excited though. It should work in the same way as it should have in Windows server. Whenever i turn off my system, start again and broswe to anysites or central admin I receive this error.
"cannot connect to configuration database"..

very annoying ah?..

The reason is everytime you turn off you system, the SQL Server(SharePoint) services also get stopped.

To make the sites to work normally go to Services.msc and make sure the following services are running. If not right click and start it.

1. SQL Server (MSSQLSERVER)
2. SQL Server (SHAREPOINT)


Thursday, April 14, 2011

Personal sites(MySite) configuration in SharePoint 2007


The first thing you should do is make sure you’ve created a Shared Service Provider (SSP). To check this do the following:
  1. Go to MOSS 2007 Central Administration
  2. Click on Shared Services Administration in left navigation
    1. If this list is not empty then click on an SSP
    2. If this list is empty then click New SSP and create a Shared Service Provider  
Once on the Shared Services Administration page for your SSP you should see at least 3 sections titled: User Profiles and My Sites, Audiences and Search. To get started you’ll need to import user profiles from the directory.To import user profiles:
  1. Under User Profiles and My Sites click on the link labeled “User profiles and properties”
  2. On the User Profiles and Properties page click on “Configure profile import”
  3. Provide a default access account, specify an account that has read access to your directory.Note: This account needs to also have Manage User Profiles rights, verify click on “Personalization services permissions” under User Profiles and My Sites on the SSP Admin page. To keep things simple until you have a grasp of the service you should use the SharePoint Admin account.
  4. Click OK
  5. On the User Profiles and Properties page click on “Start full import”
  6. Verify that import started and wait until import has completed before moving on to other personalization admin tasks (this may take a few hours)
  7. After import is complete to view the results click on “View user profiles” on the User Profiles and Properties page
The SSP administrative portion of My Site should have been configured when you created the SSP. So while waiting on profile import to complete you can explore the non administrative parts of My Site.To create a My Site:
  1. Click on My Site in the global actions bar which is in the top right corner of every SharePoint page
  2. Wait while your My Site is created
  3. After creation is complete check to make sure the name of the site created is titled with your name
    1. If not then open a new browser window with your credentials and click the My Site link again or copy the URL behind the My Site link into the browser window.Note: My Site is highly personalized so it works best when its created using your credentials and not those of an admin account or alternate account
  4. Follow the links in the Getting Started with My Site web part
Once profile import is complete we can go back to setting up personalization services in the SSP Admin page. Now that we have profiles we can do things with them like create audiences.To create audiences:
  1. Go to the Shared Services Administration page for your SSP.
  2. Click on “Audiences” under the section Audiences
  3. On the Manage Audiences page click on “Create audience”Note: Audiences should not be created until after you’ve completed a profile import.
  4. Walk through the steps to create a new audiences based on user profile data
  5. After you’re done creating audiences click on “Start compilation” from the Manage Audiences pageNote: Audiences must be compiled before they can be used.
  6. After compilation is complete to view the results click on “View audiences” from the Manage Audiences page
Now that we have created new audiences we should put them to use on SharePoint sites by targeting content. To target content on SharePoint sites:
  1. Go to SharePoint site
  2. Go to the document library on the site
  3. Go to Document Library Settings
  4. Click on “Audience targeting settings” under General Settings
  5. Enable audience targetingNote: You can do this for any list type not just documents.
  6. Go back to the document library
  7. Edit or upload a new document
  8. Click the Browse button in the Target Audiences field
  9. Select an audience you created or search and use an existing distribution listNote: Distribution lists and security groups will only display after you’ve completed a profile import.
  10. Click OK to update the document’s properties
To display targeted content on SharePoint sites:
  1. Go to the site home page and add the Content Query Web Part
  2. Modify the Content Query Web Part
  3. Under Query change List Type to Document Library
  4. Under Query -> Audience Targeting check “Apply audience filtering”
  5. Click OK
  6. Verify the items you targeted in the document library only show for people in those audiences.  
Now that you’ve had a chance to see how audience targeting works let’s move on to People Search. To setup people search:
  1. Go to Shared Services Administration for your SSP
  2. Under Search section click on “Search settings”
  3. On Configure Search Settings page find the default content access account
    1. If this is not set then provide a default content access account
  4. Verify default content access account has Use personal features rightsNote: To verify click on “Personalization services permissions” under User Profiles and My Sites on the SSP Admin page. To keep things simple until you have a grasp of the services you should use the SharePoint Admin account.
  5. On Configure Search Settings page click on “Content sources and crawl schedules”
  6. On the Manage Content Sources page hover over “Local Office SharePoint Server sites” and click the arrow to drop the ECB menu
  7. In the drop menu click Start Full Crawl
  8. Verify that crawl started and wait until crawl has completed before moving on to search for people
Finding people:
  1. Once crawl is complete to main portal site and click on Search in the top navigation area to go to the Search Center
  2. In Search Center click on tab labeled “People”
  3. Type in a term you added to your profile while exploring your My Site such as a project, skill or responsibility
  4. Hit Enter or click the Go button
  5. Verify that you and others who match that search term was returned as search results  
One area of personalization we haven’t touched on at all yet is publishing links to the Office client. Links to SharePoint lists, libraries, and sites can be published to Office 2007 clients as places to easily retrieve or save documents. To publish links to Office 2007 clients:
  1. Go to Shared Services Administration for your SSP
  2. Under User Profiles and My Sites click on “Published links to Office client applications”
  3. Click New to add a link
  4. Provide a URL, name and type for the link
    1. If you want to the link to only show for a specific set of people then specify and audience
  5. Click OK
To view links in the Office 2007 client:
  1. Open Word 2007
  2. Open the File Open or Save As dialog box
  3. Click on My SharePoint Sites on the leftNote: In order for the service to find the SSP you must set the My Site you created earlier as your default My Site.
  4. Verify link are presented