Sunday, June 28, 2009

Getting all documents in document library inside all folders

Hi All,

Many times we require getting all documents in the entire document library including sub folders. For this we need to use the ViewAttributes property on SPQuery object and set it to specify Scope=\"Recursive\

If we don’t do this, then result we will get it all documents from the top folder only.

Here is a simple way, we will achieve this.

SPList objList = objWeb.Lists["{name of the doc lib}"];

SPView objView = objList.Views["name of the view"];

SPQuery objQuery = new SPQuery(objView);

objQuery.ViewAttributes = "Scope=\"Recursive\"";

SPListItemCollection objItemColl = objList.GetItems(objQuery);


Sometimes we may require returning the result from specific folder inside the document library.

At this time, we need to use SPFolder class and set the SPQuery object’s Folder property to the object of SPFolder.

Here is a way.

SPFolder objFolder = objList.RootFolder.SubFolders["name of the folder"];
objQuery.Folder = objFolder



That is it. Your job is done.

Saturday, June 27, 2009

Understanding of securing objects in WSS 3.0

Hi All,

There is a way how we can secure the object in WSS. When I say secure it means objects exposes several methods which will allow us to determine the rights or the permission related stuff on list / document library level, item level and individual site level.

Here we are talking about understanding DoesUserHavePermissions method on these securable objects.

Let us take an example one by one. First we will talk about permission checking on site level.

Let’s say we have taken the reference of current site and it is stored in objWeb, then this method checks if the current user has permission to View the List Items?

if(objWeb.DoesUserHavePermissions(SPBasePermissions.ViewListItems))
{
// your code goes here
}


Second, we talk about the same permission set but on the list level.

Let’s say we have taken the reference of lstContacts and wants the check for the same view list items permission, then

if(objList.DoesUserHavePermissions(SPBasePermissions.ViewListItems))
{
// your code goes here
}


And at last the same with each item of list / doc lib as SPListItem object objItem.

if(objItem.DoesUserHavePermissions(SPBasePermissions.ViewListItems))
{
// your code goes here
}


This method actually does not throw the exception if the permission is not there for the user, but there is one more method which does exactly the same thing, but throws the exception if the permission is not there for the user.

e.g. objWeb.CheckPermissions(SPBasePermissions.ViewListItems)

Above method checks the permission for the current user, but sometimes you may also require to check the same permission for some other user, well in that case, use the same method with overloaded method which has first parameter as string which takes the Login with domain name.

objItem.DoesUserHavePermissions({loginname}, SPBasePermissions.ViewListItems))

Well sometimes i think, is the name of this method correct? I mean shouldn't it be DoesUserHasPermission? if we see real grammer? your thoughts on this, readers? :)

Thank you

Friday, June 19, 2009

Using SPWebApplicationBuilder class for creating Web Application programmatically

Hi All,

We all know that the Web Application is the main container for all site collections. Ultimately it is the whole and sole of all sites created later on.

So in this article, we will learn how to create Web Application programmatically with SPWebApplicationBuilder Class. When we instantiate the object of SPWebApplicationBuilder class, it automatically provides the default values for the required settings.

However there are many other properties that you can set. These are the same properties that we set from UI in central administration at the time of creating web application.

Here is a list of some properties. You can find all properties from of course MSDN.

ApplicationPoolId. – GUID of the application pool that will get created for web application.

ApplicationPoolUsername. – User name of the windows account under whom web application will run.

ApplicationPoolPassword- Password of the windows account under whom web application will run.

CreateNewDatabase. – Gets or sets the Boolean value indicating to create the database for web application or not.

DatabaseName – Name of the database

Port – Port number on which web application runs

Here is a way we will proceed to create web application. First instantiate the SPWebApplicationBuilder class object.

Then you can set different properties. Here I am setting only port number.

Then get the SPWebApplication class object by calling the create method on SPWebApplicationBuilder object.

Here is a short code.

SPWebApplicationBuilder objWebAppBuild= new SPWebApplicationBuilder(SPFarm.Local);
objWebAppBuild.Port = 8880;
SPWebApplication objWebApp= objWebAppBuild.Create();
objWebApp.Provision();


Just to check one important thing is under which account code is running.

That’s it. Your job is done.

Thursday, June 18, 2009

How to customize the Theme in SharePoint

Hi All,

Many times we require customizing theme of SharePoint site. For Creating Theme we first need to create one folder in the 12\TEMPLATE\THEMES Folder under 12 hive structure.

Copy any of the folders from that THEMES folder and give that new folder your appropriate unique name. Let’s say we give the new folder “XTheme” as name of it. Ultimately this folder will contains css files, images , color of font and all.

Now you need to find one file in the folder that you have copied, check for .inf file and rename it to the foldername.inf.

Now open this .inf file and give the same name to the to the title in the [info] and [titles] sections of the file.

Now modify and make the changes according to your business need. Colors, styles, images and everything.

You now also need to add one image especially for preview purpose when you will view this from Site Theme option.

Copy your image to the 12\TEMPLATE\IMAGES folder. Let’s say we call it as XTheme.gif

Now find one more file at this location 12\TEMPLATE\LAYOUTS\1033 which is SPTHEMES.xml. You need to add this THEME as templates collection like this.

<Templates>
<TemplateID>XTheme</TemplateID>
<DisplayName> XTheme </DisplayName>
<Description>This is my new THEME</Description>
<Thumbnail>images/XTheme.gif</Thumbnail>
<Preview>images/XTheme.gif</Preview>
</Templates>


Now reset the IIS, I guess it will not require but then also just to be on safer side, reset the IIS and now you should be able to change the Site Theme to the your custom theme.

That’s it. Your job is done.

Wednesday, June 17, 2009

Access denied when crawling MOSS Content in crawl Log.

Hi All,
when you try to crawl the site content from central admin in MOSS and look into crawl log the site is not crawled properly and showing you following error.

"Access is denied. Verify that either the Default Content Access Account has access to this repository, or add a crawl rule to crawl this repository. If the repository being crawled is a SharePoint repository, verify that the account you are using has "Full Read" permissions on the SharePoint Web Application being crawled. (The item was deleted because it was either not found or the crawler was denied access to it.)"

try following steps to get rid of this kind of error:

1. Click Start, click Run, type regedit, and then click OK.
2. In Registry Editor, locate and then click the following registry key:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
3. Right-click Lsa, point to New, and then click DWORD Value.
4. Type DisableLoopbackCheck, and then press ENTER.
5. Right-click DisableLoopbackCheck, and then click Modify.
6. In the Value data box, type 1, and then click OK.
7. Quit Registry Editor, and then restart your computer.

Source: http://support.microsoft.com/kb/896861



Tuesday, June 16, 2009

Hiding specific item from ECB menu

Hi All,

I am going to share how we can hide a specific item from the ECB menu.

Before starting this topic, I would like to say that even we have the feature method to add the menu item to ECB menu list but there is no reverse way to hide any specific menu item from ECB menu list. The reason behind this is they are rendered by JavaScript file which is core.js.

Now it is not recommended that you modify this core.js JavaScript file. So here what we will do is we will copy the core.js and paste at the same location and rename it with your appropriate name let’s say customcore.js.

Now the other thing to do is allow and render the customcore.js file through the custom masterpage.

Here make a note that we also need core.js file used by custom masterpage, so we use Defer=”true” in as an attribute.

Perform the steps mentioned below.

(1) Copy the core.js and paste it at the same location and rename it to customcore.js
(2) In customcore.js remove the entries that you don’t want in ECB menu list.
(3) Copy the Default.master and rename it to custom.master.
(4) In custom master page add following lines.

<SharePoint:ScriptLink language="javascript" name="core.js" Defer="true" runat="server"/>
<SharePoint:ScriptLink language="javascript" name="customcore.js" Defer="true" runat="server"/>

(5) Save the custom master page, upload it to the master page gallery and apply the custom.master as default master page for your site.

That's it. your job is done.

Monday, June 15, 2009

Understanding Feature activation dependencies

Hi All,

When you create the feature, it can also include the dependencies. Let’s say, we have one feature that is dependent on the other feature, that means when we activate one feature, it actually requires the other feature already been activated, at that time we can use this feature dependencies.

A very good example of this is TeamCollab feature which activates many other features automatically. It creates several list templates and makes it available for the site.

Let me give you a very simple example of Feature Dependencies.

<Feature
Id={GUID}
Title={title}
Description={Description}
Version={version}
Hidden={value}
Scope={value}
xmlns={namespace} />

<ActivationDependencies>

<ActivationDependency FeatureId = {dependent Feature GUID}/>

</ActivationDependencies>


That means the feature inside the ActivationDependency must be activated before the main feature gets activated.

If the main feature is A and inside ActivationDependency we write feature B, then activating Feature A first activates feature B and then activates feature A.

Note that Feature B must be installed first at specific scope.

Other very important thing to note here is you must have to define feature B (Feature that goes inside ActivationDependency) as Hidden, otherwise SharePoint will throw error saying that the dependant feature is not enabled.

That's it. your job is done.

Sunday, June 14, 2009

Understanding Feature Stapling

Hi All,

In this article, we will discuss something about feature stapling.

If I have to tell you in a very simple manner what we mean by feature stapling then my answer would be a feature that can attached to multiple site templates as well as multiple custom site templates at one go.

That means, let’s say we create one simple feature of creating list with few columns and if we want to have this list created every time blank site or team site is created, then we can register this feature to be used in team site and blank site, so that whenever we create team site or blank site, the list gets created.

If you want to have the feature available in every type of site templates then also you can do it. That means you select any templates then also that list will get created in it. We will call it as Global Site availability for the feature.

Here is a way we can achieve this.

Take a look at this XML. We will already have the feature that we want to have it in Team Site and Blank Site. So we will create one feature for achieving the feature stapling and its elements.xml is mentioned here.

<Elements xmlns=http://schemas.microsoft.com/sharepoint/>
<FeatureSiteTemplateAssociation
Id=”{GUID of the feature that you want to make available in Team Site and Blank Site}”
TemplateName=”STS#0” />

<FeatureSiteTemplateAssociation
Id=”{GUID of the feature that you want to make available in Team Site and Blank Site}”
TemplateName=”STS#1” />
</Elements>

Here STS#0 and STS#1 refer to Team Site and Blank Site respectively.

That is it, Deploy this feature and activates it at Site Collection level or site, web application or farm level.

From Next time, if you create the Team Site and Blank Site, the feature that you mentioned in stapling will be there in that site created.

If you want this feature to be there in every site template, then just one change you need to make and the change is as follows.

TemplateName attribute value will be “GLOBAL#0”. That’s it.

Saturday, June 13, 2009

Adding Documents in document library with feature

After creating document library as feature people are asking how to add document in document library as feature.

Refer:How to add document library with folders and content types through feature/site definition.

So here is another simple solution for that.
Below is the feature file

<Feature
Id="BB964AFE-14E1-4f83-9703-73349007D904"
Title="Doclib with document"
Scope="Web"
Version="1.0.0.0"
Hidden="FALSE"
DefaultResourceFile="core"
xmlns="http://schemas.microsoft.com/sharepoint/"
Description="This Feature contains the doc lib with doc">
<ElementManifests>
<ElementManifest Location="element.xml" />
<ElementFile Location="sample\MyDoc1.doc" />
<ElementFile Location="sample\MyDoc2.doc" />
</ElementManifests>
</Feature>



Please note that we have to define our files that we want to put in document library.

This location is path of file from feature.xml.

Below is element.xml

<Elements
xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="withDoc"
Url="MyDoc"
Path="Sample"
RootWebOnly="FALSE">
<File Url="MyDoc1.doc" Type="GhostableInLibrary" />
<File Url="MyDoc2.doc" Type="GhostableInLibrary" />
</Module>
</Elements>


Here is the Description for each element.

Module is the most key element for this thing.

Name: name of the module (any) I have used same as feature name for understanding.

URL: Url of document library from site. If you want document in root level of document library then write only document library name over here. If you want document in some folder of document library then user “<Document Library Name>/<Folder Name>/<Folder Name>”

Path: physical path for document folder (files must have in some folder in feature folder) from feature.xml

RootWebOnly: weather allow this feature only at root level or you want this feature to be at sub site level. False will allow you to use this feature to sub site level also.

<File >
Tag


URL = path of the document after path of module.

Type = GhostableInLibrary : as we want the document to be in document library we have to use this tag.

This way you can add documents in document library.

If you want files to be in different folders then you have to use more than one module tag for diff folders.

Below is element for copying one doc in one library and another doc in another library.

<Elements
xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="withDoc"
Url="MyDoc/f1"
Path="Sample"
RootWebOnly="FALSE">
<File Url="MyDoc1.doc" Type="GhostableInLibrary" />
</Module>
<Module Name="withDoc2"
Url="MyDoc/f2"
Path="Sample"
RootWebOnly="FALSE">
<File Url="MyDoc2.doc" Type="GhostableInLibrary" />
</Module>
</Elements>


This step you can use for everything like putting any page in pages library, putting master page in master page library and all that.

Friday, May 1, 2009

Creating and Working with SharePoint Timer Job Definitions

Hi All,

Many times we require creating a timer job definition because of requirement logic. Let’s say, we have some requirement something like whenever list gets added to the site, site administrator should get email saying that this list is being added by so and so person at this time.

Second example, you are supposed to write a job which starts the workflow every night for an approval process of some data calculations.

Now we do not have anything like ListAdding and ListAdded event that gives the answer of our question or any other event that solves some requirement like second example.

In these cases, we can create custom timer job and specify when to run and what to do when it runs.

So let us go ahead and create a custom timer job.

For this, I suggest creating a feature class which installs the job definition when activated and removes the job definition when feature is deactivated or other way is to go to timer job definitions under Operations in central administration and disable that specific job definition.

Before starting up the example, I also would like to explain you few classes for scheduling. Depending upon the schedule that you want to set, you need to take the classes. For example we have SPWeeklySchedule, SPDailySchedule, SPMonthlySchedule, SPYearlySchedule, SPHourlySchedule, SPMinuteSchedule.

You must have got the idea by the name of these classes when to use them. If you want to run your job every hour, you have SPHourlySchedule; if you want it to run every minute then you have SPMinuteSchedule. You can get the idea about the properties that needs to be set when using respective classes from searching MSDN.

Here I am taking an example of SPMinuteSchedule to explain you the example. Do keep in mind that different classes have different properties to be set.

First thing, create a Feature class.

namespace xyz
{
public class ListAddedFeature : SPFeatureReceiver
{
const string LIST_ADDED_JOB_NAME = "ListJobNameAddingCheck";

public override void FeatureInstalled (SPFeatureReceiverProperties properties) {
}

public override void FeatureUninstalling (SPFeatureReceiverProperties properties) {
}

public override void FeatureActivated (SPFeatureReceiverProperties properties) {
SPSite site = properties.Feature.Parent as SPSite;

// make sure the job isn't already registered
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions) {
if (job.Name == LIST_ADDED_JOB_NAME)
job.Delete();
}

// install the job
ListAddingLatestJob taskLoggerJob =new ListAddingLatestJob(LIST_ADDED_JOB_NAME, site.WebApplication);

SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
schedule.Interval = 5;
taskLoggerJob.Schedule = schedule;

taskLoggerJob.Update();
}

public override void FeatureDeactivating (SPFeatureReceiverProperties properties) {
SPSite site = properties.Feature.Parent as SPSite;

// delete the job
foreach (SPJobDefinition job in site.WebApplication.JobDefinitions) {
if (job.Name == LIST_ADDED_JOB_NAME)
job.Delete();
}
}

}
}



This gives you an idea that when feature will be activated at that time job will be scheduled, if exists then removed and then scheduled and at the time of deactivating job will be removed. When you will activate the feature you will find the Job name in the Timer Job Definitions in the operations section of central administration under global configuration section and you can also see the timer job status but you won’t find your custom timer job there untill it executes atleast once. This will run every 5 minutes.

Here I also would like to share is what is the significance of BeginSecond and EndSecond and any such propoerty for Begin and End for any above class is that timer job starts at any random time between sub specified time durations. This is because if you have many timer jobs running at the same time, then it could put a heavy load on server.

Here is actual job definition class.

namespace xyz
{
public class ListAddingLatestJob : SPJobDefinition
{


public ListAddingLatestJob()
: base(){
}


public ListAddingLatestJob (string jobName, SPService service, SPServer server, SPJobLockType targetType)
: base (jobName, service, server, targetType) {
}

public ListAddingLatestJob(string jobName, SPWebApplication webApplication)
: base (jobName, webApplication, null, SPJobLockType.ContentDatabase) {
this.Title = "ListAdding Check";
}


public override void Execute (Guid contentDbId) {
// get a reference to the current site collection's content database

SPWebApplication webApplication = this.Parent as SPWebApplication;

SPContentDatabase contentDb = webApplication.ContentDatabases[contentDbId];

SPWeb objWeb = contentDb.Sites[0].RootWeb;

DateTime objTISiteCreationtime = objWeb.Created;

SPList taskList = contentDb.Sites[0].RootWeb.Lists["Tasks"];


SPQuery objQuery = new SPQuery();

objQuery.Query = "<Where><Gt><FieldRef Name=\"ID\"/><Value Type=\"Counter\">0</Value></Gt></Where>";

SPListItemCollection objCollection = taskList.GetItems(objQuery);

DataTable dtAllLists = objCollection.GetDataTable();

ArrayList objArrayList = new ArrayList();

if (dtAllLists != null)
{
if (dtAllLists.Rows.Count > 0)
{

for (int iCnt = 0; iCnt <= dtAllLists.Rows.Count - 1; iCnt++)
{

objArrayList.Add(Convert.ToString(dtAllLists.Rows[iCnt]["Title"]));
}
}
}


for (int iCnt = 0; iCnt <= objWeb.Lists.Count - 1; iCnt++)
{
if (!objArrayList.Contains(objWeb.Lists[iCnt].Title))
{
if (objWeb.Lists[iCnt].Created.ToShortDateString()
!= objTISiteCreationtime.ToShortDateString())
{

SPListItem newTask = taskList.Items.Add();

newTask["Title"] = objWeb.Lists[iCnt].Title;

newTask.Update();
//Write a logic to send a mail to admin

}
}
}


}

}
}


Do not go deep into the logic, as this is just to give an idea about the creation of timer job and along with that simple logic which checks for the lists created by default at the time of site creation which will have the created time same as time created for site.

What I am doing here is first I am storing List Names in the Tasks List (Just to demonstrate you, you can change the logic suiting to your need). I get all items from the tasks list and compare stored Title (List Name) with the each list name of the site, if not there that means it is newly created, send mail to admin and then add the list name again to tasks list title column. So this will keep on working and every five mintes, it will keep checking if newly list has been added or what and sends mail.

Please note that logic is not perfact, just to demonstrate you and give you an idear about Timer job definition and at the same time idea about how to implement List added logic. You can share the best idea with us.

IMP : How to debug the timer job definitions.

Other very important thing is debugging the timer job definitions. Debugging timer job definition is something different because its not about attaching w3wp process because this doesn’t run under web. So we do have other process here to attach to get this thing debug. Name of the process is OWStimer.exe. When you attach this process, then just wait for your timer to get to the right defined time by you and then it will automatically come for debugging. Means if you have set it to 2 minutes, then attach the OWStimer.exe process and just wait for 2 minutes. Every 2 minutes you will get the breakpoint hitting the location.

Ok, one more thing. If you have observed the Timer job definition in central administration, then it gives you an option to disable the job definition but it doesn’t allow to execute it at force.

One way to go about this is to use the stsadm –o execadmsvcjobs but the problem with this is it will execute all the administrative timer jobs without waiting for any job to run in schedule because it doesn’t take any parameter.

So solution is again code. Here is that one liner code that does stuff for us.

foreach (SPJobDefinition job in site.WebApplication.JobDefinitions) {
if (job.Name == LIST_ADDED_JOB_NAME)
job.Execute(site.WebApplication.ContentDatabases[0]);
}


That;s it. Your job is done.



Share your SharePoint Experiences with us...
As good as the SharePointKings is, we want to make it even better. One of our most valuable sources of input for our Blog Posts comes from ever enthusiastic Visitors/Readers. We welcome every Visitor/Reader to contribute their experiences with SharePoint. It may be in the form of a code stub, snippet, any tips and trick or any crazy thing you have tried with SharePoint.
Send your Articles to sharepointkings@gmail.com with your Profile Summary. We will Post them. The idea is to act as a bridge between you Readers!!!

If anyone would like to have their advertisement posted on this blog, please send us the requirement details to sharepointkings@gmail.com