Pages

Thursday, January 17, 2013

Customize Search Box in SharePoint

Search in SharePoint is important to drive adoption and in SharePoint 2010 Enterprise search has improved and come a long way. People look to search for information rather than clicking through or navigating to find the information. SharePoint is an excellent Enterprise Content Management (ECM) tool because it is more a platform than simple tool Developers are given independence to take SharePoint to any level they want. In this blog we will see how we can customize search by creating custom controls and adding code. We will not be touching on adding best bets, and keywords to drive better results.

People always had requirement to customize the search box that is present in SharePoint out Of the Box (OOTB). This is definitely doable and to everyone's surprise it is lot easier to achieve this than many thing. We will see step by step in process of achieving this in this blog.

SharePoint has a nice delegate architecture where there is no need to modify the page for changing or modifying a certain functionality in the page. For example we can use delegate control to replace the OOTB search box with custom search box and perform the operation that we want to do in the search box. It is an unintrusive way of high jacking the functionality.
In order to replace the search box with custom control we fist have to create a project in Visual Studio.

Open Visual Studio and Create a Empty SharePoint Project




Once we have the project next step is to add Mapped folder "Control Templates". This is where the user controls go in SharePoint. We will be creating a user control similar to a search box and replace it.





Now we will add a user control called "CustomSearch.ascx" this is the control that we will use with delegate control to replace the existing search box.





Now I am adding a textbox and image with link similar to the OOTB search box. In order to show the difference I am adding the text as "Custom Search the site"

<input type="text" id="search_box" name="search_box" runat="server"  placeholder="Custom Search the site..." onkeypress="javascript: return DoPostBackOnEnterClick(event);" />
<a title="Search" id="goSearch" href="javascript:__doPostBack('search_go');">
<img id="cbl_search_go" src="/_layouts/images/gosearch15.png" alt="Search" class="srch-gosearchimg" style="border:1px solid #e3e3e3;" onmouseover="this.src='/_layouts/images/gosearchhover15.png'"
     onmouseout="this.src='/_layouts/images/gosearch15.png'"  /> </a>
I am setting all the attributes similar to the OOTB search box. obvisouly I am adding an postback on click using javascript and on enter click to mimic the OOTB as close as possible.
Now our user control is ready and we can now see how we can include this as a delegate control. In order to use this as delegate control we need to include it in an element file which we can deploy with a feature. So lets us create a element file. You can an element file by right click on the project and add a new item and select empty element file.





We now have the element file and we are almost done. All we have left to do is add this control and so we can deploy it (include it in the master page only if you have a custom Master Page).
<!—Custom Search Box --> 
  <Control Id="SmallSearchInputBox" Sequence="10"
     ControlSrc ="~/_controltemplates/CustomSearch.ascx">
  </Control>
This is the line that needs to be added in the element file to get it deployed. Note the important thing here is the sequence number and ID. I have given the sequence number of "10" which less than the OOTB sequence number and I am using the same ID as "SmallSeachInputBox".  The reason behind that is when this control gets deployed SharePoint loads all the controls as delegate control and since our sequence number is smaller this control will be loaded instead of OOTB control. Once we have the element file we can include this element file with any feature and deploy it and activate the feature.This is what you will see once you deploy this.



 Hope this blog is useful to you all and any feedback and comments are welcome.

Enjoy Coding and Customizing. SharePoint.

Friday, November 30, 2012

Set Masterpage Poweshell SharePoint



PowerShell commands come handy when you have to perform administrative tasks in your SharePoint environment. In past where you have to write code or a small utility program like a console application or Windows Form application can now be achieved using PowerShell script. . I use this a lot with my clients and since PowerShell script is run by the administrators the IT people love it and don’t have to worry about anything.
In the recent times I have been asked by my clients to provide them with a script to set master pages across multiple site collection in a web application in order to push their branding. I thought that the same script will be useful for a lot of people like me and decided to share the script here by making the script more generic than the one I wrote for my clients.
#Enter the site URL
$siteUrl = Read-Host "Enter Site URL"
$rootSite = New-Object Microsoft.SharePoint.SPSite($siteUrl)
$spWebApp = $rootSite.WebApplication
foreach($site in $spWebApp.Sites)
{
$web = Get-SPWeb $site.Url
$featureFolderNameSite = "PublishingSite"
$featureFolderNameWeb = "PublishingWeb"
$FeatureIDSite = Get-SPFeature -Site $web.Url | Where {$_.DisplayName -eq $featureFolderNameSite}
$FeatureIDWeb = Get-SPFeature -Web $web.Url | Where {$_.DisplayName -eq $featureFolderNameWeb}
# Check Publishing feature is active at site level and site collection level
#if not active activate.
if($FeatureIDSite -ne $null)
{
   Write-Host $featureFolderNameSite "is already activated at :" $web.Url
}

else
{
    Enable-SPFeature -Identity $featureFolderNameSite -Confirm:$false -Url $web.Url
    Write-Host $featureFolderNameSite "has been activated at :" $web.Url
}

if($FeatureIDWeb -ne $null)
{
    Write-Host $featureFolderNameWeb "is already activated at :" $web.Url
 }

else
{
    Enable-SPFeature -Identity $featureFolderNameWeb -Confirm:$false -Url $web.Url
    Write-Host $featureFolderNameSite "has been activated at :" $web.Url
}
$web.CustomMasterUrl = "/_catalogs/masterpage/nightandday.master"
$web.MasterUrl = "/_catalogs/masterpage/nightandday.master"
$web.Update()
$site.Dispose()
}
$rootSite.Dispose()

The script takes the Site URL from the user and loops through all the available site collection present in the web application in which the current site collection is part and sets the master page on all the site collections. The script also activates publishing feature at the site collection level and at site level before setting the master page if it is not activates already.

Tuesday, August 14, 2012

Add Event Handler to Specific List or Library

Event Handlers in SharePoint is the de-facto choice if someone wants to perform some operation synchronously. Some would also point out about Workflows, though workflows can perform the same operation but workflow is acting asynchronously. Suppose you want to set the document or item metadata while adding you would have to use event handler or suppose you want to prevent somebody from deleting an item from a list or library you will be using event handlers. In SharePoint 2010 there are more event handler definition added compared to MOSS 2007. You can find these information here.

In this article let us take a look at how you can register event handlers for a specific list or library. We are focusing on registering it to specific list or library because by default event handlers get registered to all the list or library of particular type. For example if you specify "ListTemplateId=100" event receiver gets registered to all lists that are of type "Custom Lists" Often times you would want the event receiver to be registered to a particular list rather than all the lists in the site. Registering event receivers to a particular List or library give you the flexibility to define an operation specific to the list or library.

There are few different ways you can register event handlers for a list or library.

If you do not worry about event handler getting attached to all the list of a type but just want to control the operation for a specific list you register the event handler on a feature and by checking the List Title you can perform the operation for the specific List.You can use the List Title from properties to prevent event firing for other libraries or lists depending on your type of event receiver.

if(properties.List.Title == "your listname")
{
}

If  you are particular about the event handler getting attached to multiple list and  you like to take control of everything under you then you can use List eventreceiver property to set event receiver for your specific list or library. You can create a feature and in Feature activation you can register the event only for your list. The code below is an example that I use for setting the event handler for Shared Documents library in SharePoint
//This is a web feature

  public override void FeatureActivated(SPFeatureReceiverProperties properties)
        {
            using (SPSite site = new SPSite(((SPWeb)properties.Feature.Parent).Url))
            {
                using (SPWeb web = site.OpenWeb())
                {
                    SPList sharedDocuments = web.Lists["Shared Documents"];
                    if (sharedDocuments != null)
                    {
                        SPEventReceiverDefinition listeventreceiver =  sharedDocuments.EventReceivers.Add();
                        listeventreceiver.Class = "TestEventReceivers.TestListEventReceiver";
                        listeventreceiver.Assembly = System.Reflection.Assembly.GetExecutingAssembly().FullName; // you can give the assembly name in string format.
                        listeventreceiver.SequenceNumber = 4000;
                        listeventreceiver.Type = SPEventReceiverType.ItemAdded;
                        listeventreceiver.Update();

                    }
                }
            }
        }
In FeatureActivated Method you need to check for existance of event receiver and if not you can add your event receiver. You need to have a class defined for your event receiver.
Event Receiver Example
 public class TestListEventReceiver : SPItemEventReceiver
    {
        public override void ItemAdded(SPItemEventProperties properties)
        {
            base.ItemAdded(properties);
        }
    }

The above operation is similar for assigning event receiver to content type, then use the event in any library or list it is used.

Another way you could assign Event Receiver is by using the list URL. This is a nice and handy way if you are deploying a solution as part of your product or offering and you are creating a List Instance using <ListInstance> in your feature and have defined URL or you already have created the list manually in a site and you have the List URL.

When you create Event Receivers in your solution in Visual studio you will have the following line added

<Receivers ListTemplateId="101">

Replace the List template in the above line as follows. Now you have List instance specific event receiver added.

<Receivers ListUrl="Lists/MyDocuments">
 
I am assigning to a Library in the above example.