Tuesday, 7 January 2014

Hide Edit Page Link From Site Actions Menu

If you have a requirement to hide a link from site actions menu, for example, the edit page link, you can use SharePoint designer instead of creating a custom code.

Here are the steps on how to hide edit page link from site actions menu of a SharePoint site:

1. Open the site using SharePoint Designer.
2. Go to _catalogs >> masterpage.
3. Check out and edit default.master page.
4. Find the below code from the page:

<SharePoint:MenuItemTemplate runat="server" id="MenuItem_EditPage"
Text="<%$Resources:wss,siteactions_editpage%>"
            Description="<%$Resources:wss,siteactions_editpagedescription%>"
            ImageUrl="/_layouts/images/ActionsEditPage.gif"
            MenuGroupId="100"
            Sequence="200"
            ClientOnClickNavigateUrl="javascript:MSOLayout_ChangeLayoutMode(false);" />


and then add the following lines on it:

PermissionsString="ManageSubwebs"
PermissionMode="Any"


The code should now look like:

<SharePoint:MenuItemTemplate runat="server" id="MenuItem_EditPage"
            Text="<%$Resources:wss,siteactions_editpage%>"
            Description="<%$Resources:wss,siteactions_editpagedescription%>"
            ImageUrl="/_layouts/images/ActionsEditPage.gif"
            MenuGroupId="100"
            Sequence="200"

            ClientOnClickNavigateUrl="javascript:MSOLayout_ChangeLayoutMode(false);"
            PermissionsString="ManageSubwebs"
            PermissionMode="Any" />


5.  Save and check in default.master page.


 

Attach OnChange Event to a SharePoint Lookup Field Using JQuery

The below script will attach onchange event to a SharePoint lookup field (with items < 20 or items >= 20).

var ddlBranch;

// check if no. of items < 20 items
 if($("select[title='Branch']").html() != null)
 {
        ddlBranch = $("select[title='Branch']")[0];
 }
 // check if no. of items >= 20
 else if ($("input[title='Branch']").html() != null)
 {
        ddlBranch = $("input[title='Branch']");

        //  override the default HandleOptDblClick function in core.js
        //  added CallCustomFunction function

        HandleOptDblClick = function()
        {         
                var opt=event.srcElement;
                var ctrl=document.getElementById(opt.ctrl);
                SetCtrlFromOpt(ctrl, opt);
                SetCtrlMatch(ctrl, opt);
                opt.style.display="none";
   
                // this checking is needed if you have other lookup fields in the form.
                // this ensure that your custom function will be called only onchange of your specific lookup field
                if($(ctrl).attr('title') == 'Branch')
                         CallCustomFunction();
       
        }   
 }

 // attach onchange event to ddlBranch
 $(ddlBranch).change(function() {
        CallCustomFunction();
 }); 



//  override the default FilterChoice function in core.js
//  changed strHandler into "onclick" instead of "ondblclick"
//  this will allow the user to just click once to select item instead of double click
function FilterChoice(opt, ctrl, strVal, filterVal)
{
        var i;
        var cOpt=0;
        var bSelected=false;
        var strHtml="";
        var strId=opt.id;
        var strName=opt.name;
        var strMatch="";
        var strMatchVal="";
        var strOpts=ctrl.choices;
        var rgopt=strOpts.split("|");
        var x=AbsLeft(ctrl);
        var y=AbsTop(ctrl)+ctrl.offsetHeight;
        var strHidden=ctrl.optHid;
        var iMac=rgopt.length - 1;
        var iMatch=-1;
        var unlimitedLength=false;
        var strSelectedLower="";
        if (opt !=null && opt.selectedIndex >=0)
        {
                bSelected=true;
                strSelectedLower=opt.options[opt.selectedIndex].innerText;
        }
        for (i=0; i < rgopt.length; i=i+2)
        {
                var strOpt=rgopt[i];
                while (i < iMac - 1 && rgopt[i+1].length==0)
                {
                        strOpt=strOpt+"|";
                        i++;
                        if (i < iMac - 1)
                        {
                                strOpt=strOpt+rgopt[i+1];
                        }
                        i++;
                }
                var strValue=rgopt[i+1];
                var strLowerOpt=strOpt.toLocaleLowerCase();
                var strLowerVal=strVal.toLocaleLowerCase();
                if (filterVal.length !=0)
                        bSelected=true;
                if (strLowerOpt.indexOf(strLowerVal)==0)
                {
                        var strLowerFilterVal=filterVal.toLocaleLowerCase();
                        if ((strLowerFilterVal.length !=0) && (strLowerOpt.indexOf(strLowerFilterVal)==0) && (strMatch.length==0))
                                bSelected=false;
                        if (strLowerOpt.length > 20)
                        {
                                unlimitedLength=true;
                        }
                        if (!bSelected || strLowerOpt==strSelectedLower)
                        {
                                strHtml+="<option selected value=\""+strValue+"\">"+STSHtmlEncode(strOpt)+"</option>";
                                bSelected=true;
                                strMatch=strOpt;
                                strMatchVal=strValue;
                                iMatch=i;
                        } 
                        else
                        {
                                strHtml+="<option value=\""+strValue+"\">"+STSHtmlEncode(strOpt)+"</option>";
                        }
                        cOpt++;
                }
        }
       
var strHandler=" onclick=\"HandleOptDblClick()\" onkeydown=\"HandleOptKeyDown()\"";
        var strOptHtml="";
        if (unlimitedLength)
        {
                strOptHtml="<select tabIndex=\"-1\" ctrl=\""+ctrl.id+"\" name=\""+strName+"\" id=\""+strId+"\""+strHandler;
        }
        else
        {
                strOptHtml="<select class=\"ms-lookuptypeindropdown\" tabIndex=\"-1\" ctrl=\""+ctrl.id+"\" name=\""+strName+"\" id=\""+strId+"\""+strHandler;
        }
        if (cOpt==0)
        {
                strOptHtml+=" style=\"display:none;position:absolute;z-index:2;left:"+x+   "px;top:"+y+   "px\" onfocusout=\"OptLoseFocus(this)\"></select>";
        }
        else
        {
                strOptHtml+=" style=\"position:absolute;z-index:2;left:"+x+   "px;top:"+y+   "px\""+   " size=\""+(cOpt <=8 ? cOpt : 8)+"\""+   (cOpt==1 ? "multiple=\"true\"" : "")+   " onfocusout=\"OptLoseFocus(this)\">"+   strHtml+   "</select>";
        }
        opt.outerHTML=strOptHtml;
        var hid=document.getElementById(strHidden);
        if (iMatch !=0 || rgopt[1] !="0" )
                hid.value=strMatchVal;
        else
                hid.value="0";
        if (iMatch !=0 || rgopt[1] !="0" )
                return strMatch;
        else return "";
}



    

Tuesday, 26 November 2013

Common STSADM Commands

Stsadm is a command-line tool that provides access to the complete set of Office SharePoint Server 2007 operations. It can be used from the command line or with batch files or scripts. Stsadm must be run on the server itself and you must be a member of the local Administrators group on the server in order to use it. Stsadm is located at the following path on the drive where SharePoint Products and Technologies is installed: %COMMONPROGRAMFILES%\microsoft shared\web server extensions\12\bin.


How to use:

In command prompt, go to this directory:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN

and then use either of the following commands:


Backup and Restore Site

>> to backup a site collection
                stsadm -o backup -url <site collection url> -filename <name of the backup file>

      example:  to backup sitecollection1 and save the backup file to drive C:

                stsadm -o backup -url "http://www.vpc.com/sites/sitecollection1" -filename "C:\sitecollection1.bak"


>> to restore a site collection
                stsadm -o restore -url <site collection url> -filename <name of the backup file>

      example: to restore sitecollection1 into a new site collection:

                stsadm -o restore -url "http://www.abc.com/sites/newsitecollection" -filename "C:\sitecollection1.bak"



Import and Export Subsite

>> to export a subsite
                stsadm -o export -url <subsite url> -filename <name of the backup file>

     example:
                stsadm -o export -url "http://www.vpc.com/log" -filename "C:\vpclog.bak"


>> to import a subsite
                stsadm -o import -url <subsite url> -filename <name of the backup file>

      example:
                stsadm -o import -url "http://www.abc.com/log" -filename "C:\vpclog.bak"
             


SetSiteLock

>> to lock the site collection as read-only:
                stsadm -o setsitelock -url <site collection url> -lock readonly

      example:
                stsadm -o setsitelock -url http://www.vpc.com -lock readonly


>> to unlock the site collection:
                stsadm -o setsitelock -url <site collection url> -lock none

      example:
                stsadm -o setsitelock -url http://www.vpc.com -lock none



Install / Uninstall & Activate / Deactivate Feature

>> to deactivate feature
                stsadm -o deactivatefeature -filename path of the Feature.xml file relative to the 12\TEMPLATE\FEATURES folder> -url <site url> -force

      example:
                stsadm -o deactivatefeature -filename "DomainRequestTaskWFCT\Feature.xml" -url http://www.abc.com -force


>> to uninstall feature
                stsadm -o uninstallfeature -filename <path of the Feature.xml file relative to the 12\TEMPLATE\FEATURES folder > -force

      example:
                stsadm -o uninstallfeature -filename "DomainRequestTaskWFCT\Feature.xml" -force


>> to install feature
                stsadm -o installfeature -filename <path of the Feature.xml file relative to the 12\TEMPLATE\FEATURES folder > -force

      example:
                stsadm -o installfeature -filename "DomainRequestTaskWFCT\Feature.xml" -force


>> to activate feature
                stsadm -o activatefeature -filename path of the Feature.xml file relative to the 12\TEMPLATE\FEATURES folder> -url <site url> -force

      example:
                stsadm -o activatefeature -filename "DomainRequestTaskWFCT\Feature.xml" -url http://www.abc.com -force






Friday, 22 November 2013

Display List Header of a List View Web Part

When you add a custom list view web part on a page, the list header is not displaying by default unlike the other web parts namely Categories, Other Blogs and Links.








In order to add a list view web part on a page with list header (for example, you want to use your custom list as a left navigation menu, similar to Categories web part in SharePoint blog site), replace the <ListViewXml> with the item below and then change the View Name value equal to the listview webpart id (__WebPartId).

<ListViewXml xmlns="http://schemas.microsoft.com/WebPart/v2/ListView">&lt;View Name="{D5DE4857-09A5-49CC-8EB3-5D26EDC40238}" Type="HTML" Hidden="TRUE" DisplayName="" Url="/blog/default.aspx" Level="1" BaseViewID="4" ContentTypeID="0x"&gt;&lt;Toolbar Type="None"/&gt;&lt;ViewHeader&gt;&lt;HTML&gt;&lt;![CDATA[ &lt;div class="ms-WPBody"&gt; &lt;div class="ms-navheader"&gt;]]&gt;&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[&lt;a ]]&gt;&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[ id="defviewurl]]&gt;&lt;/HTML&gt;&lt;Counter Type="View"/&gt;&lt;HTML&gt;&lt;![CDATA["&gt;]]&gt;&lt;/HTML&gt;&lt;ListProperty Select="Title" HTMLEncode="TRUE"/&gt;&lt;HTML&gt;&lt;![CDATA[&lt;/a&gt;]]&gt;&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[&lt;/div&gt; &lt;table cellpadding="0" cellspacing="0" border="0" class=""&gt;]]&gt;&lt;/HTML&gt;&lt;/ViewHeader&gt;&lt;ViewEmpty&gt;&lt;HTML&gt;&lt;![CDATA[ &lt;div class="ms-WPBody"&gt; &lt;div class="ms-navheader"&gt;]]&gt;&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[&lt;a ]]&gt;&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[ id="defviewurl]]&gt;&lt;/HTML&gt;&lt;Counter Type="View"/&gt;&lt;HTML&gt;&lt;![CDATA["&gt;]]&gt;&lt;/HTML&gt;&lt;ListProperty Select="Title" HTMLEncode="TRUE"/&gt;&lt;HTML&gt;&lt;![CDATA[&lt;/a&gt;]]&gt;&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[&lt;/div&gt; &lt;table cellpadding="0" cellspacing="0" border="0" class="ms-navSubMenu2"&gt;]]&gt;&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[&lt;tr&gt;&lt;td&gt;&lt;div class="ms-BlogEmptyListText"&gt;]]&gt;&lt;/HTML&gt;&lt;HTML&gt;There are no items in this list.&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;]]&gt;&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[&lt;/table&gt;&lt;/div&gt;]]&gt;&lt;/HTML&gt;&lt;/ViewEmpty&gt;&lt;ViewBody&gt;&lt;HTML&gt;&lt;![CDATA[&lt;tr class="ms-CategoryTitleRow"&gt;&lt;td class="ms-CategoryTitleCell" id="lnkurl]]&gt;&lt;/HTML&gt;&lt;Column Name="ID" URLEncode="TRUE"/&gt;&lt;HTML&gt;&lt;![CDATA["&gt;]]&gt;&lt;/HTML&gt;&lt;Field Name="URL"/&gt;&lt;HTML&gt;&lt;![CDATA[&lt;/td&gt;&lt;/tr&gt;]]&gt;&lt;/HTML&gt;&lt;/ViewBody&gt;&lt;ViewFooter&gt;&lt;HTML&gt;&lt;![CDATA[&lt;/table&gt;&lt;/div&gt;]]&gt;&lt;/HTML&gt;&lt;/ViewFooter&gt;&lt;RowLimitExceeded&gt;&lt;HTML&gt;&lt;![CDATA[&lt;div class="ms-BlogMoreLinks"&gt;&lt;a href="]]&gt;&lt;/HTML&gt;&lt;ListProperty Select="DefaultViewUrl"/&gt;&lt;HTML&gt;&lt;![CDATA[" ID=onetidMoreFavs&gt;
                                        ]]&gt;&lt;/HTML&gt;&lt;HTML&gt;(More Links...)&lt;/HTML&gt;&lt;HTML&gt;&lt;![CDATA[
                                        &lt;/a&gt;&lt;/div&gt;]]&gt;&lt;/HTML&gt;&lt;/RowLimitExceeded&gt;&lt;Query&gt;&lt;OrderBy&gt;&lt;FieldRef Name="Order" Ascending="TRUE"/&gt;&lt;/OrderBy&gt;&lt;/Query&gt;&lt;ViewFields&gt;&lt;FieldRef Name="URL"/&gt;&lt;/ViewFields&gt;&lt;RowLimit&gt;30&lt;/RowLimit&gt;&lt;/View&gt;</ListViewXml>




After doing the modifications, it will now show the list header of the custom list as shown below:







How to Update People Picker Field Programmatically

People picker field is a SharePoint column that allows you to select users, distribution lists, and security groups within the SharePoint Foundation user interface. If you have a user's requirement that needs to update the people picker field programmatically, you can try the following solution.

In your ascx page, add a hidden SharePoint people picker field (where visible property is equal to false) by using the following syntax:

<spuc:PeopleEditor AllowEmpty="false" ValidatorEnabled="true" id="userPicker" runat="server" ShowCreateButtonInActiveDirectoryAccountCreationMode="true" SelectionSet="User" MultiSelect="false" Visible=false />

But in order to use this field in a page, you need to add a directive at the top of the page:

<%@ Register TagPrefix="spuc" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

In code behind, add the following:

PickerEntity entity = new PickerEntity();
entity.Key = vr.RName //display name;
entity.DisplayText = vr.RName //display name;
entity = userPicker.ValidateEntity(entity);
                       
PickerEntity entity2 = new PickerEntity();
entity2.Key = entity.Description;
entity2 = userPicker.ValidateEntity(entity2);

                       
SPFieldUserValue fuv = new SPFieldUserValue(web, Convert.ToInt32(entity2.EntityData[PeopleEditorEntityDataKeys.UserId]), entity2.Description);


// "RName" is the name of the sharepoint people picker field to update
listItem["RName"] = fuv;

HandleEventFiring eventFiring = new HandleEventFiring();
eventFiring.AccDisableEventFiring();
listItem.Update();
eventFiring.AccEnableEventFiring();


-------------------

public class HandleEventFiring : SPItemEventReceiver
        {
            public void AccDisableEventFiring()
            {
                this.DisableEventFiring();
            }

            public void AccEnableEventFiring()
            {
                this.EnableEventFiring();
            }
        }







    

Wednesday, 20 November 2013

Workflow Error - Failed on Start (retrying)

If you encounter this error message "workflow error - failed on start (retrying)" in visual studio .net workflow, you can try the following solutions to fix the issue:

  • Change the Correlation Token value to be unique. The workflow and each activity should have a unique value. The workflow itself and each task you need to reference in the workflow must have a separate correlation token. Refer to this link http://msdn.microsoft.com/en-us/library/ms475438.aspx for more details. 

In the below example, I set the correlation token of the workflow in onWorkflowActivated1 to "workflowToken" and then the correlation token of the workflow task createEndorserTask to "taskToken".

correlation token

Figure 1: workflowToken


correlation token

Figure 2: taskToken



  • Check the dll in the workflow.xml (CodeBesideAssembly). It should be the same as the one in the GAC.





Tuesday, 19 November 2013

How to Save a File to SQL Database

Here are the steps on how to save a file to sql database using LINQ.


  1. Define your table. In this sample we created an Attachments table having 3 fields FileID (int), FileName (nvarchar(100)) and FileContent (varbinary(MAX)). FileContent field will contain the bytes of our file. We set it to MAX to accommodate any file size.










  1. Add your table to your repository module. In this case I used a simple LINQ to SQL just to make it simple















I created a simple repository class to expose some methods like add, save and get.

public class AttachmentRepository
{
    private DataClassesDataContext db = new DataClassesDataContext();

       public AttachmentRepository()
       {
              //
              // TODO: Add constructor logic here
              //
       }

    public void Add(Attachment at)
    {
        db.Attachments.InsertOnSubmit(at);
    }

    public void Save()
    {
        db.SubmitChanges();
    }

    public List<Attachment> GetAllAttachments()
    {
        return db.Attachments.ToList();
    }
}


  1. Layout your UI. Here we have two controls asp FileUploader and asp Button.






  1. Add a button click event on your upload button. In the code below, we only add a file to the database if there is a file uploaded using .HasFile property. Since we already have a repository using LINQ to SQL we can directly assign the Filename and FileBytes to our attachment class.

protected void btnUpload_Click(object sender, EventArgs e)
    {
        if (FileUploadSample.HasFile)
        {
            AttachmentRepository atRepo = new AttachmentRepository();
            Attachment at = new Attachment();
            at.FileName = FileUploadSample.FileName;
            at.FileContent = FileUploadSample.FileBytes;
            atRepo.Add(at);
            atRepo.Save();
        }       
   }


  1. Verify your Database if the file was indeed saved.








Finally I added a gridview to show the uploaded data