Wednesday, August 12, 2009

Serach only word documents in sharepoint 2007 search.

Serach only word documents in sharepoint 2007 search.
There are two ways to search only word documents in sharepoint site



1. Creating Search Scope
2. Property search



1. Creating Search Scope:Navigate to "Search Settings" in Search Category.
Click on "Metadata Property Mappings" and check for "FileExtension" has check for 'Allow this property to be used in scopes' as below.

Now click on "View scopes" in Scopes category. Click on "New Scope" provide the following detailsTitle as "word docs" and select "Use the default Search Results Page" radio button and click on "ok"click on "Add rules" against to newly created "word docs" and provide following informationselect "Property Query (Author = John Doe)"select "FileExtension" from Add Property restrictions dropdown.provide "doc" value in the subsequent textbox.select "Require" radio button.click on "ok"Go back to search settings, click on 'Content sources and crawl schedules' select 'Start Incremental crawl' from'Content sources and crawl schedules'.
That's it. Go back to sharepoint site. Navigate to 'Advanced Search'.provide the keyword that you want to search in "All of these words:" and select "Word docs" from 'Result type'and click on 'Search' button to get the expected result.


2. For example if you are looking for "title" keyword in word documents.provide the information as 'title filetype:doc' in search box which yields the same results as above for this no need to set the search scope

Wednesday, May 20, 2009

Creating Content Types using Features

Content Type is a logical collection of site columns.(refere my last post to know more about site columns).
Any page layout you create as a template for pages on your site must be associated with a content type. Generally each column in the content type will be matched to a field control on the page layout, allowing the author to enter content to be stored in each column.

Fortunately creating content types as features is fairly simple - CAML only, no need for a feature receiver (code). Alas VSeWSS can't help us much here but don't forget to use the CAML schema intellisense in VS by ensuring the XML file we're about to write is linked to the schema at C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\XML\wss.xsd.

Initially, the part that can seem complex is the ID structure for a content type. Having been happily using GuidGen in Visual Studio every time we need an ID for something in a feature (though never trusting the first one ;-)), it comes as a surprise to have to read documentation just about IDs. As explained in Content Type IDs, the structure reflects the ancestry/parentage of a content type, meaning the parent content types can be determined very efficiently since simple string/byte matching can be used thus reducing database lookups.

The basics are:

find the ID of the content type you are deriving from. This can be done by either examining the content type in the SharePoint UI (Site Settings > Manage Content Types) and copying the ID from the URL querystring. Alternatively, search the feature files which the MS developers used to deploy the out-of-the-box content types. The former is probably simpler but the latter gives more scope for learning.
Add '00' and then a GUID you have generated (i.e. with GuidGen) to the end (suffix). You now have a valid content type ID. Note that you'll get a meaningful exception on feature activation if it's not.
For any child content types, to generate their IDs you can now add a simple ID such as '01' or '02' to the ID generated in the previous step. It's not necessary to suffix the ID with '00' and another GUID now since your unique ID is in the string. This means any ID's you generate will be different from anyone else's, so you can use the simple option and use a 2 digit number rather than another GUID. This means your content type IDs shouldn't grow too long.
The rest is fairly simple. Just add a FieldRef element for each site column the content type uses, specifying it's ID and name. Note that the approach we used to create our site columns meant that we got to specify the ID for them in CAML. We just need to dig out the IDs we specified there. So in both features, the IDs are in easily edited XML rather than being in any compiled code or similar so they are fairly loosely-coupled. Of course in many cases you'd choose to have both artifacts in the same feature, and in the future I'll post about factoring with relation to features.

You should end up with something like for each content type you are deploying:-



Note that it's not necessary to repeat the fields declared in parent content types, though I notice some of the Microsoft features do this.

So now you have your content types deployed, they can now be used in document libraries/lists or associated with any page layouts you have. So next time is deploying master pages/page layouts/CSS etc. as a feature, including having the layouts automatically bound to the content types.
Reference:http://www.sharepointnutsandbolts.com/2007/04/deploying-content-types-as-feature.html

Tuesday, April 14, 2009

Creation of Site Columns using features

We can add a custom column to the sharepoint list or document library. Suppose if we have column called "Department", and if this need to be present in each and every list or document library. Instead of creating custom column for each and every list/document library, we create site column once and which can be used across all the lists/document libraries. This new feature available only in Moss 2007.

The simplest way of creating site column is navigate to SiteActions->Site Settings->Modify all site settings->click on Site columns under Galleries section, shows the list of all available site columns.

We can create a column with list of available data types.

Creating Site column with feature.

We can create the Site columns with feature.xml.
Create a folder called Moss.Features.SiteColumn
Create two xml files feature.xml and Element.xml as follows.
copy the below code in feature.xml

Id="{8C41689F-F45F-4b28-85B8-44C4B5197D02}"
Title="Moss.Features.SiteColumns"
Description="Custom MySite Columns"
Version="1.0.0.0"
Scope="Site"
Hidden="false"
xmlns="http://schemas.microsoft.com/sharepoint/">

Location="Elements.xml" />



Copy the below code in Elements.xml



ID="{4C67267C-B950-4cd4-8038-DEACA9EC2F74}"
Name="MyTitle"
Group="MyColumns"
DisplayName="MyTitle"
Type="Text"
Required="FALSE"
Sealed="TRUE"
MaxLength="250">



Note: here "Type" data type. You can mention any available datatypes.

Move this folder to 12hive feature folder, and install the feature as

stsadm -o installfeature -name Moss.Features.SiteColumns

Activate the feature as

stsadm -o activatefeature -name Moss.Features.SiteColumns -url http://servername:portno

This creates new site column called "MyTitle".
You can reuse this site columns for lists/document libraries.

stay glued for content types, Page Layouts, Master pages in my next posts.

Get back to me if you have any queries.
shreecanth@gmail.com

Sunday, April 5, 2009

Increasing the performance of Publishing site of Moss 2007 in Mobile Devices

Have you ever been get a chance to look at how much size each page (empty moss pages or custom webpart with no data- pages hosted on moss) takes loading in moss 2007?
It takes nearly 500kb for each page load in moss 2007 site collection.

For each request to the Moss 2007 publishing page loads following basic files

Core.css
Controls.css
Core.js
Init.js
Ie55us.js
Editingmenu.js
Spellcheck.js

and lot more...

The Read access users doesn't require of loading all these files.
These files loaded into the in page, even though if we define our custom master page without any links to the above files.

But this can be a performance problem when the moss 2007 site is requested from the Mobile PDA applications.
We need to make our master page and conent pages lighter weight so that it can be easily accessed in the mobile devices.
To remove these files we need to create one HttpModule, which does the clean up of unneccesary files.

There is a great article available for removing of these files
http://www.ie-soft.de/blog/PermaLink,guid,968b0588-f306-467b-be51-54f7a8f2079d.aspx

Happy coding...

Thanks,
Shreecanth

Sunday, March 29, 2009

Power of web.config changes in Asp.net 1.1

To inherit my asp.net page from our custom developed page.
All asp.net pages are inherit from System.Web.UI.Page class
for example
namespace Myproject.web
{
public class MyCustomPage: System.Web.UI.Page
{
}
}
public class Login: MyCustomPage
{
}
Instead of this we have a better workaround for this process.
Add the following tag in our web.config entry, by doing this whenever we add aspx page to our solution it automactically inherits from "MyCustomPage"

its really works wonder....
Reference article:http://ryanfarley.com/blog/archive/2004/06/08/766.aspx

Saturday, February 7, 2009

Differnce between Asp.net and Sharepoint safe mode parser

When a request is comes for an .aspx page Sharepoint ISAPI takes care about who will serve the request. Asp.net or Safemode parser(sharepoint).Before this you should know the concept of sharepoint ghosted and unghosted pages.In sharepoint some pages are lie in physical folder of server i.e, _layouts or _vti_bin folder. These pages are accessible for all applications.These pages are call ghosted pages.If we edit these pages through designer or through front page 2003 the pages become unghosted and a copy of each page is stored in the application content database. To make it clearghosted pages are those rows in the docs table which have null values for the Content column and a non-null value for the SetupPath column which points to a file on the file system itself. The referenced file essentially serves as a template and content source.Any webpart page or normal pages are ghosted by default.
The main difference between Asp.net and sharepoint pareser is, in asp.net for each first request of the page is compiled into assembly, and next request onwards the compliled page gets executed. In sharepoints safe mode parser is not compiled. They are interpretative pages. Remember its not possible to make unghosted page to its original ghosted pageSo if there is any inline server code in aspx page the safe mode parser will not allow the page to load

Limitation of enabling session state

By default in Sharepoint session state is disabled. when you open any site collection web.config file you will see below line commented in http module
'add name="Session" type="System.Web.SessionState.SessionStateModule" '
The difference between session state in sharepoint and .net
In .net session can be enabled at page level. So the pages which doen't have the session can avoid the performance hit associated with it.But in sharepoint once the sessionstate is enabled for the application, all the the unghosted(customized) page forced to use sessionstate whether or not controls on that page require session state.
For ex: Assume your SharePoint server contains mostly unghosted pages. Let’s say there are 1000 unghosted pages on the site. You create a web part that requires session state. Let’s say that web part is only used on a few select pages (i.e. 2-3 pages). Enabling session state so that 2-3 pages can use the web part suddenly slows down the performance of the 998 other pages.SSo it is advisable not to use session state in sharepoint which degrades the performance of the application

Saturday, January 31, 2009

SPDisposeCheck v1.3.1 is released

Hi,

SPDisposeCheck is a tool to help SharePoint Developers follow memory management best practices when using the SharePoint API with IDisposable objects including SPSite and SPWeb.

This tool Can be downloadable at http://code.msdn.microsoft.com/SPDisposeCheck

Go through below site for more information.

Source:http://blogs.msdn.com/pandrew/archive/2009/01/29/spdisposecheck-v1-3-1-is-released.aspx


Saturday, January 24, 2009

Setting custom property to the webpart - usercontrol

There are occasions when it may be necessary to provide web part users with a richer interface for setting custom properties than SharePoint provides out-of-the-Box

Setting up the custom properties for a webpart is very easy and straight
farward approach.

Recently i came acorss requirement in one of my webpart i need to set the custom property.
we usually go for usercontrol for better look and easily maintainable instead of writing entire code in webpart itself.
In my scenario i have one usercontrol form which has a cancel button, on clicking on cancel the redirection happens basing on the configurable property.
So for this usercontrol i need to pass the custom property value, i am getting the value in webpart but had very tough time trying to pass the value to the usercontrol.


But after tweaking my head at last got succeded by doing

1. Not enabling the click event for the Cancel button in usercontrol itself, declare the click event for the usercontrol in webpart itself
2. In the create child controls mehtod find the cancel button Id, and writing the event for the cancel button

Code:

publice string _navigateUrl=string.empty;

public class CustomWebpartProperties : System.Web.UI.WebControls.WebParts.WebPart
{
UserControl customUsercontrol ;
[WebBrowsable(true), WebDisplayName("Navigate Url"),
WebDescription("set the path")]
public string CustomURL
{
get
{
return _navigateUrl;
}
set
{
_navigateUrl = value;
}
}
Button btnCancel;
public override ToolPart[] GetToolParts()
{

ToolPart[] allToolParts = new ToolPart[3];
WebPartToolPart standardToolParts = new WebPartToolPart();
CustomPropertyToolPart customToolParts = new CustomPropertyToolPart();

allToolParts[0] = standardToolParts;
allToolParts[1] = customToolParts;
allToolParts[2] = new CustomToolPart();

return allToolParts;
}







protected override void CreateChildControls()
{
customUsercontrol = (UserControl)Page.LoadControl(@"/wpresources/TesUsercontrol.ascx");

btnCancel = (Button)UserControlContactUsByEmail.FindControl("btnCancel");
btnCancel.Click += new EventHandler(btnCancel_Click);


base.Controls.Add(customUsercontrol);
base.CreateChildControls();
}

protected override void Render(HtmlTextWriter writer)
{
writer.Write(NavigateUrl);
customUsercontrol.RenderControl(writer);
}

void btnCancel_Click(object sender, EventArgs e)
{
//redirection code
SPUtility.Redirect(NavigateUrl, SPRedirectFlags.UseSource, HttpContext.Current);
}

}

This class is used to set the new custom tool part and provides the user to enter the
value for url.
public class CustomToolPart : Microsoft.SharePoint.WebPartPages.ToolPart
{
Label lbl;
Panel customToolPart;
TextBox txt;


protected override void CreateChildControls()
{
customToolPart = new Panel();
txt = new TextBox();
txt.ID = "tb";

lbl = new Label();
lbl.ID = "lbl";
lbl.Text = "Navigate Url";

customToolPart.Controls.Add(lbl);
customToolPart.Controls.Add(new LiteralControl("
"));
customToolPart.Controls.Add(txt);
Controls.Add(customToolPart);
base.CreateChildControls();
}

public override void ApplyChanges()
{
ContactUsByEmail wp = (ContactUsByEmail)this.ParentToolPane.SelectedWebPart;
wp.NavigateUrl = txt.Text;
//Button btnClick = (Button)wp.FindControl("btnCancel");
//btnClick.Click += new EventHandler(btnClick_Click);
}

}


shoot a mail to shreecanth@gmail.com if you need any further assistance.

Sunday, January 18, 2009

Best Practices: SharePoint Object Model for Performance Tuning

While working with SharePoint object model, most of developers will use SPWeb, SPSite, SPList objects intensively.

Some of developers who reported performance issues in their production environment after their project deployment. Their code works well in most of the scenarios but whenever the data get increases then there might be potential performance hits because of not handling the APIs properly.

In this post I will give information about some common methods that we are using in most of the scenarios and very important points that we need to remember in perspective of application’s performance. We do have two cool MSDN articles gives information about the best practices with SharePoint object model and I will recommend you all to go through those articles as well. Also we do have an excellent blog by Roget Lamb by giving the detailed information of Dispose Patterns with examples.

Best Practices: Common Coding Issues When Using the SharePoint Object Model

Best Practices: Using Disposable Windows SharePoint Services Objects

Roger Lamb’s cool post about SharePoint 2007 and WSS 3.0 Dispose Patterns by Example

Lots of situations where we will use APIs for retrieving information about Lists and List Items. In SharePoint, lists are the objects storing large amount of data. So we need to be little cautious while working with those APIs, because internally those APIs are calling some SQL queries to pull the data which has been stored the SharePoint Content DBs.

The performance issues may happen in some cases if numbers of lists are very high or in some cases total number of lists will be less but the items will be very large.

First we can take a look at different approaches of getting SPList instance and we can choose the best method to increase the performance. We have more than one method or property which will return the same result. For Eg: SPList.Item.Count & SPList.ItemCount will return the number of items, so here we need to decide which one need to opt in our code implementation to enhance the performance.

Scenario 1 : Retrieve SPList instance

SPWeb.Lists (“name”) – Not Good

using (SPSite site = new SPSite(strSite))

{

using (SPWeb web = site.OpenWeb())

{

SPList oList = web.Lists ["MyList"]

}

}

In this case, it loads the metadata* of the all lists in that specific SPWeb object. Then it does SPList.Title comparison with metadata of all the lists returned and then it returns the matching list from the SPWeb.Lists collection.

SPWeb.GetList (string strUrl) – Good

using (SPSite site = new SPSite(strSite))

{

using (SPWeb web = site.OpenWeb())

{

SPList oList = web.GetList("http://Site/list/AllItem.aspx")

}

}

In this case, first retrieves the list GUID from the url (database hit), then it loads the metadata* for that specific list.

metadata * = list of all information of List like its schema, fields info, content type info, column and items count.

Consider a scenario of a SharePoint site which contains 1000 lists.

If we use SPWeb.GetList(), it will load the SPList by finding out the exact GUID of that SPList from the SharePoint content DB and loads the metadata.

But if that is the scenario with SPWeb.Lists[“MyList”] then, SPWeb.Lists will load the metadata of all the 1000 lists in memory and then it does SPList.Title ( here it is “MyList”) comparison with metadata of all the lists returned and then it returns the matching list from the SPWeb.Lists collection.

If you debug the code in winDbg then you can find out the GC Heap size and then you can realize how badly it is affecting the performance of your application, sometimes for each SPList it will take some MB's.

So now we can consider this matter while writing code and use SPWeb.GetList() instead of using SPWeb.Lists[“MyList”].

Scenario 2 : Retrieve SPListItem

SPList.Items[int idx] – Not Good

using (SPSite site = new SPSite(strSite))

{

using (SPWeb web = site.OpenWeb())

{

SPList oList = web.GetList("http://Site/list/AllItem.aspx");

for(int idx =0; idx<>

{

string strLstItemName = oList.Items[idx].Name;

}

}

}

In this case, for each iteration oList.Item[idx] will load a SPListItemCollection. Eg: consider a list has 1000 list items. So whenever this code executes, for each iteration it will create a separate SPListItemCollection and it will create a huge memory consumption in the GC Heap by creating 1000 SPListItemCollection instances

SPListItemCollection[int idx] - Good

using (SPSite site = new SPSite(strSite))

{

using (SPWeb web = site.OpenWeb())

{

SPList oList = web.GetList("http://Site/list/AllItem.aspx");

SPListItemCollection oListItems = oList.Items;

for(int idx =0; idx<>

{

string strLstItemName = oListItems[idx].Name;

}

}

}

In this case, we can see the the only code change between this one and the not good one is, here we are first taking all the items from the list and populating it in a SPListItemCollection. And then we are iterating only that SPListeItemCollection and finding out the specific list item. Here the advantage is that, in the memory this code will load only one SPListItemCollection.

Scenario 3 : Retrieve SPListItem in Event Handlers

SPListItem – Not Good

public override void ItemAdded(SPItemEventProperties properties)

{

using (SPSite oSite = new SPSite(properties.WebUrl))

{

using (SPWeb oWeb = oSite.OpenWeb())

{

SPList oList = oWeb.Lists[properties.ListId];

SPListItem oListItem = oList.GetItemByUniqueId(properties.ListItemId);

}

}

}

In this case, we are unnecessarily giving extra load to the memory by adding so many memory consuming APIs. For each iteration, oList.Item[idx] will load a SPListItemCollection. Please see the Good method below.

SPListItem – Good

public override void ItemAdded(SPItemEventProperties properties)

{

SPListItem oItem = properties.ListItem;

}

In this case, we have reduced lots of code and it will return the current ListItem by using this single line of code. Avoid creation of SPWeb & SPSite instances, because in an event handler those are directly accessble through the SPItemEventProperties.

Scenario 4 : Retrieve SPListItem Count

SPList.Item.Count – Not Good

using (SPSite site = new SPSite(strSite))

{

using (SPWeb web = site.OpenWeb())

{

SPList oList = web.GetList("http://Site/list/AllItem.aspx");

int iCount = oList.Items.Count;

}

}

In this case, oList.Items.Count, first it will load all the SPListItems in the memory and then it will find out the total count. For eg: Consider a list with 1000 list items. Then in this scenario the above code will load all the 1000 SPListItems and then return the total count, which will really create some performance hit.

SPList.Item.ItemCount – Good

using (SPSite site = new SPSite(strSite))

{

using (SPWeb web = site.OpenWeb())

{

SPList oList = web.GetList("http://Site/list/AllItem.aspx");

int iCount = oList.ItemsCount;

}

}

In this case, ItemCount is a part of metadata of the SPList object and this will get generated whenver we create a SPList instance. So there is no any overburden to the list to find out its total number of list items.

Scenario 5 : A list of recommended properties and methods

Not Good (replace this by the Good one)

Good

SPList.Items.Count

SPList.ItemsCount

SPList.Items[Guid]

SPList.GetItemByUniqueId(Guid)

SPList.Items[Int32]

SPList.GetItemById(Int32)

SPList.Items.GetItemById(Int32)

SPList.GetItemById(Int32)

Scenario 5 : Specify the RowLimit Property while using SPQuery Object

SPQuery.RowLimit Good

SPQuery oQuery = new SPQuery();

oQuery.RowLimit = 2000;

Performing an SPQuery without setting RowLimit will perform purely and will be fail on large lists. Thus it will be always recommend to specify the RowLimit between 1 and 2000. Because if we didn’t mention it, in SQL server it ill return the resullt by using “select top x from table”, here the x will be a very large number. So it would give a very good performance if we limit the row by explicilty setting the RowLimit.

Also, the query must use an indexed field or it will cause a complete table scan and WSS will block it on a large list.

I hope all these information will help the developers while writing the code in their custom SharePoint applications. Since in SharePoint most of the data are storing in the lists, the maintenance of those tables in DB as well through code (by querying through SharePoint APIs) will be always be a best practice. Also everybody can consider these points while reviewing the code.

Using Visual Studio TFS 2008, we can do the performance testing of methods by profiling the methods and we can do a load runner test by simulating the requests from users and the time. It is really a great facility in VS 2008.

Happy coding

Srikanth Sapelly