Monday, September 29, 2008

MOSS deploy dll in bin folder

This article i hope will help many starters as well as experienced SharePoint developers to understand the way SharePoint uses the dll deployed in its site directory bin folder which is located under the inetpub/virtual directory folder. As we all know and have used mostly (atleast in our case) deployment of dll (Custom WebPart, Custom control etc) in GAC (Global Assembly Cache) was the way to develop SharePoint solutions. But there is another very good approach which is mentioned below in steps. That is to deploy the dll directly to the site bin folder. Here are the steps to accomplish:

1. Set Output path of the projects (Project in which you are keeping webpart control classes) to the site bin folder. You can find the path by navigating to C:\Inetpub\wwwroot\virtual directory\port number\bin

2. Build the solution and make sure it is compiling successfully.
3. Add a safe control entry to the web config file. Do not mention public key token. Do not strong name the project.
4. That's it, your code is deployed in the site's bin directory and its information is located in the config file. Go Ahead and populate the web part gallery with the web part and add it  to a page.

Advantages:
1. Biggest advantage is the fact  that you do not have to reset iis after every compilation of code.
2. You can directly copy the dll from the other bin folders to this as and when required.

DisAdvantage
1. As you are deploying code to the bin folder of particular site, it will not be available globally. That means you will need to add the dll to every site's bin folder.

I hope this article will clear most of your doubts. In case something is not understood, do write a comment to this post or email us at sharepointkings@gmail.com

SPBuiltInFieldId and SPBuiltInContentTypeId : two useful classes

Hi All,

There is an interesting thing that I found and it is very useful.

This will help in avoiding writing the Column Name Titles at some extend.

I found two classes that have built-in feature to get the all built in Columns .

These two classes are :

SPBuiltInFieldId

SPBuiltInContentTypeId

For example,

Instead of using "Title" which refers to “Title” column, we can use SPBuiltInFieldId.Title . So no margin of error in typing, because sometimes we want to refer columns like Created By, Last Modified, which includes (space) which gets converted to _x0020_ at the time of code. so better to rely on given class rather than declaring and using our own as far as default column names are concern.

Same way for all built in content types.

SPBuiltInFieldId.Created_x0020_By
SPBuiltInFieldId.Created_x0020_Date
SPBuiltInFieldId.ID
SPBuiltInFieldId.JobTitle
SPBuiltInFieldId.Last_x0020_Modified


Same goes for SPBuiltInContentTypeId.

I hope this will help you...

Friday, September 26, 2008

Creating Discussion list programmatically

Hi All,

I come across to one class which is actually useful for creating a discussion because it has built in feature to do it.

I thought of sharing as of course with you all.

Here is a way to create discussion list programmatically.

First take an object of Web.

Considering that i am working in webpart.

SPWeb objWeb = SPContext.Current.Web;
objWeb.AllowUnsafeUpdates = true;

objWeb.Lists.Add("My DiscussionMalay", "MyDiscussion11", SPListTemplateType.DiscussionBoard);


Here all we need to do is use SPListTemplateType for creating Discussion.

Then main portion comes here,

SPListItem objItem = SPUtility.CreateNewDiscussion(objList.Items, "This is the subject of Discussion");


Check, SPUtility class actually allows us to create a discussion.

objItem[SPBuiltInFieldId.Body] = "This is the Body of the Discussion";

objItem.Update();

objWeb.Update();

objWeb.AllowUnsafeUpdates = false;


And That's it. your job is done...

Wednesday, September 24, 2008

Custom alert in SharePoint

We all know one of the very good features in Moss is Alerts.

And default alert message is also very good.

But as usual we all need to create a custom alerts mail in our SharePoint system.
We may need some style change, header/footer/logo change and also some business logic before sending alert mail.

So here is the way to change default alert mail in SharePoint.

We had this requirement a long time ago but we are not able to do it but suddenly we came across the KB on Microsoft Support site which explain step by step how to do that. Here is the link for KB 948321.

We tried that code and it worked like a charm.
Here is the same code but with some logical comment added by us just to understand the things.
But we recommended that follow the steps from the same link above(KB 948321)
using System;
using System.Text;
using System.Web;
using System.Collections.Generic;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;


namespace SharePointKings.CustomWebParts
{
public class CustomAlert : IAlertNotifyHandler
{
#region IAlertNotifyHandler Members

public bool OnNotification(SPAlertHandlerParams ahp)
{
try
{
//find the site
SPSite site = new SPSite(ahp.siteUrl + ahp.webUrl);
//open the web
SPWeb web = site.OpenWeb();
//get the list that has been changed(modified)
SPList list = web.Lists[ahp.a.ListID];
//get the item that has been changed
SPListItem item = list.GetItemById(ahp.eventData[0].itemId);


//path to reach to that item
string FullPath = HttpUtility.UrlPathEncode(ahp.siteUrl + "/" + ahp.webUrl + "/" + list.Title + "/" + item.Name);
//path to reach to that list
string ListPath = HttpUtility.UrlPathEncode(ahp.siteUrl + "/" + ahp.webUrl + "/" + list.Title);
//path to reach to that web
string webPath = HttpUtility.UrlPathEncode(ahp.siteUrl + "/" + ahp.webUrl);

string build = "";

//eventType string will get that item is Added/Changed or deleted
string eventType = string.Empty;

if (ahp.eventData[0].eventType == 1)
eventType = "Added";
else if (ahp.eventData[0].eventType == 2)
eventType = "Changed";
else if (ahp.eventData[0].eventType == 3)
eventType = "Deleted";

//this way you can build your email body
//also you can apply the bussiness logic that which field to show
//change your highlighted words every thing you can do
build = "<style type=\"text/css\">.style1 { font-size: small; border: 1px solid #000000;" +
"background-color: #DEE7FE;}.style2 { border: 1px solid #000000;}</style></head>" +
"<p><strong>" + item.Name.ToString() + "</strong> has been " + eventType + "</p>" +
"<br> this is test by <strong>SharepointKings</strong><br> looks nice" +
"<table style=\"width: 100%\" class=\"style2\"><tr><td style=\"width: 25%\" class=\"style1\">" +
"<a href=" + webPath + "/_layouts/mysubs.aspx>Modify my Settings</a></td>" +
"<td style=\"width: 25%\" class=\"style1\"> <a href=" + FullPath + ">View " + item.Name + "</a></td>" +
"<td style=\"width: 25%\" class=\"style1\"><a href=" + ListPath + ">View " + list.Title + "</a></td>" +
" </tr></table>";

//title of the email
string subject = list.Title.ToString();
//over here sending mail is done by SPUtility so check the configuration
//of central admin for outgoing email.
SPUtility.SendEmail(web, true, false, ahp.headers["to"].ToString(), subject, build);
//we don't know why but we as per KB we have to return false.
return false;
}
catch (System.Exception ex)
{
return false;
}
}

#endregion
}
}


After completion of code follow the steps for register these codes in your site, again go to for KB 948321

Here is the overview what to do, this is not the steps to follow just an over view.

For that you need to generate copy of alertTemplates.xml file
Note: Do not directly modify the alertTemplates.xml file. Directly modifying this file is unsupported.Change the Properties tag in that xml with your solution’s assembly.
And use
stsadm -o updatealerttemplates <<with mentioned parameters>>
And restart the Windows SharePoint Services Timer service.

You done it man!!!

Tuesday, September 23, 2008

How to pass parameters to workflow programmatically

Hi All,

Workflow, being my passion for working and always many times i come across to a task related to workflow , i explore many things.

In this post, i would like to share my knowledge about How to pass parameters to workflow programmatically.

Why do you need to pass the paramter to the workflow?

Answer is simple, there might be a chance where you do not use the Assoication and Initiation form with the workflow, everything is dependent on runtime. In this fashion there is no use of using the Association and Initiation form.

So sometimes you need to use the parameters for the workflow which you can pass it at the time of triggering the workflow from code.

I usually enjoy doing work with workflow programmtically. Because everything is possible with code that is what i bilieve.

So Here let me take you to a small trip to a way you can pass the workflow programmatically.

Please go through my post Starting Workflow Programmatically regarding starting workflow from code to know about WorkflowManager and WorkflowAssociation classes, which i will not cover in this post. here we will actually concentrate on passing the parameter.

To Pass the Paramter, First all you need to do is make one class and place Serializable attribute on it and define public properties and one public method which serializes the data in to the XML Format so that it becomes generic for using in any application to even pass it to Web Services.



So, lets start.

(1) Define one class with properties

[Serializable()]
public class WorkflowParameters
{
private string _ZipCode = default(string);


public string ZipCode
{
get { return _ZipCode; }
set { _ZipCode = value; }
}


private string _CountryCode = default(string);

public string CountryCode
{
get { return _CountryCode; }
set { _CountryCode = value; }
}

public string getInitXmlString(WorkflowParameters objParams)
{

WorkflowParameters data = new WorkflowParameters();

data._CountryCode = objParams._CountryCode;

data._ZipCode = objParams._ZipCode;


using (MemoryStream stream = new MemoryStream())
{
XmlSerializer serializer = new XmlSerializer(typeof(WorkflowParameters));

serializer.Serialize(stream, data);

stream.Position = 0;

byte[] bytes = new byte[stream.Length];

stream.Read(bytes, 0, bytes.Length);

return Encoding.UTF8.GetString(bytes);

}
}

}

Here as you can see we have defined two properties ZipCode and CountryCode as an example. you make paramters accordingly to your need.

(2) Next, step is to dynamically execute the workflow, for this code you can refer post 1. I am working with event handler of a list, so here is a code which demonstrate the idea about executing workflow from event handler. change this code according to the code where you writing it.

SPWorkflowManager objWorkflowManager = null;
SPWorkflowAssociationCollection objWorkflowAssociationCollection = null;

SPListItem item = properties.ListItem;

objWorkflowManager = item.Web.Site.WorkflowManager;

objWorkflowAssociationCollection = item.ParentList.WorkflowAssociations;

foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection)
{
//Find the GUID for the workflow association

WorkflowParameters objParams = new WorkflowParameters();

objParams.ZipCode = "12345";
objParams.CountryCode = "USA";

string strSerializedParams = objParams.getInitXmlString(objParams);

objWorkflowAssociation.AssociationData = strSerializedParams;

if (String.Compare(objWorkflowAssociation.BaseId.ToString("B"),
"{workflow_ID}", true) == 0)
{
objWorkflowManager.StartWorkflow(item, objWorkflowAssociation,
objWorkflowAssociation.AssociationData, true);

}
}

As you can see here we have created an object of our previous defined class which is serializable. we set the properties and passed it to a public method of the same class and then we get the string as in the form of XML, which is then assigned to the AssociationData of workflowassociation which is passed to a workflow.

(3) Now you need to retrive these data in the workflow. Now you have to go to a Workflow Code. Let us assume that we fetch these data in Workflow Invoke Activity.

//Assume that this is the activity that executes when workflow triggers

private void onWorkflowActivated1_Invoked(object sender, ExternalDataEventArgs e)
{

//Fetch with workflow properties InitiationData property which gets the
//Parameters passed to it.

string strParametrsPassed = workflowProperties.InitiationData;

//Now this string returns you string in XML format which looks like this,

//<?xml version="1.0"?>
//<WorkflowParameters xmlns:xsi="http://www.w3.org/2001/XMLSchema-//instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
// <ZipCode>12345</ZipCode>
// <CountryCode>USA</CountryCode>
//</WorkflowParameters>

}


Ignore any whitespaces in the output shown for XML. it is just to get the idea.

And, so you got XML here, just play with XML class and use these parameters in your code.

We can always refine any of the above code, this is just to demonstrate the concept.

That's it. your job is done.

Thursday, September 18, 2008

Working with versions in List programmatically

Hi All,

Our SharepointKings team really wanted to share this because when we needed this kind of facility we did not find many articles on this topic. so we thought to dig in this and find out something.

Ok, let's get to the business straight forward. The requirement was to have History for the List. Yes, a history for the list.

So bottom line is working with versions in List programmatically.

So we thought that there is a default facility in Document Library for Version and it is very famous for versions, but we actually never came across list history. so we decided to look on the List Settings and yes we were right, we found that there is an option to have version for the List also.

To Enable the Versions, Go to List Settings and go to Version Settings and then Select Create a version each time you edit an item in this list? to true. there you go, you have just made versoning option on.

Now, Try to edit any item from that list and then Select the ECB of that Item, see you will find Version History option, Click on that and you will see all changes that you have just performed. So this is very nice for the End User.

But, What about the Developer if they have to do it by code and display the result of any previous version????
So this article focuses on this.

Let me give you a brief introduction on what all classes we will require to get this thing done.

Let's consider a scenario where you need to check all versions of all ListItems in the List.

First you take an object of the list in which you need to find our the versions of ListItems.

Considering that i am writing code in Web Part, change the code accordingly (If Needed).

SPList objList = SPContext.Current.Web.Lists["{your_list}"];

SPQuery objQuery = new SPQuery();

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

SPListItemCollection objItemColl = objList.GetItems(objQuery);


Note that update your code accordingly in single line. here code is written in multiple lines only for readability.

Here what we have done is we got all ListItems so far for the list.

Now, we will proceed in getting the versions of each ListItem.

foreach (SPListItem objItem in objItemColl)
{

SPListItemVersionCollection objVerisionColl = objItem.Versions;

//Above Line gets all versions of the ListItem. If it returns 1, that means nothing is modified. no version //for this item.

if (objVerisionColl.Count > 1)
{
//Navigate to each version of the ListItem
foreach (SPListItemVersion objVersion in objVerisionColl)
{
int versionID = objVersion.VersionId;

//Returns incremental IDs starting from 512,1024,1536... for each version

DateTime timeofcreation = objVersion.Created;

//VersionLabel - Gets 1.0,2.0,3.0 as default versions for each iteration

string strVersionLabel = objVersion.VersionLabel;

SPListItem objLstItm = objVersion.ListItem;

}
}
}


This means If the ListItem is modified for 3 times, the above loop for that ListItem will execute 3 times and you will get the VersionId as 512,1024,1536 Likewise. VersionLabel as 3.0, 2.0, 1.0. It returns by default from latest to oldest.

So This is the way to get all versions of the ListItem. So now the question is how to get the Data of old versions.Check out the last line in the loop which actually gets the SpListItem of that Version.

So first get the SPListItem that you want and then check for all versions just like the above code and use simple technique to retrieve the data. Consider i have three columns. FirstName, LastName and Address in the List.

So all i have to do is, once i get the Version that i want to fetch take its SPListItem object and then access its fields,

string strFirstName = Convert.ToString(objLstItm["FirstName"]);
string strLastName = Convert.ToString(objLstItm["LastName"]);
string strAddress = Convert.ToString(objLstItm["Address"]);


Now you have the old version data on your hand. Play with it on your own way!!!!

Tuesday, September 16, 2008

SharePoint search Step by Step (Part 2)

Hi we are back for search again.
If you missed then here is the link of SharePoint search Step by Step (Part 1)

Now as per continuation to the part 1 we are discussing for the second step.
After getting result in SharePoint default search we will get the crawled content programmatically.
Now for that we referred a lot of link on the net and here are the most useful ones and we are very thankful to them for guidance.
MSDN: Windows SharePoint Services Search SQL Syntax

The secrets of SQL Syntax Queries for Relevant Results in MOSS 2007 Enterprise Search

Here we go.

First of all we will show you how to search for a particular lists column programmatically. If you want the search from some related lists or entire site or in documents only then everything can be done but for that concept should be clear.

As you already created your separated content source (check part one). now we have to create a scope for the same.

How create a Scope?
Go to “Shared Service Provider site (SSP site)”
Go to “Search Settings.”
In the “Scopes “section click “View scopes”
Click in the “New Scope “
Give Title and description and press ok.
After that click on add rules link appear as per screen shot.



Click on that Add rules link.
Here is the catch.
Please refer this technet link for Manage scope rules

Now as we are searching from only one specific list so we are using the first option (Web Address (http://server/site)).



After adding rule to the scope go to search setting page and click “Start update now”


Wait for scopes to Update.
After that click in view scopes in your newly created scope items is start appearing.
Now time to create a metadata property.

How to create metadata property?

Go to SSP site -- search setting -- Metadata property mappings – New Managed Property


Name the property

Select second option[Include values from a single crawled property based on the order specified]

Click on add mapping



Select a “Sharepoint” category.
And find your column. It should named with prefix “ows_(your field name)”
Press ok

If you will not find your column then crawl your content source once.
And do not forget to check Allow this property to be used in scopes.
Only then we can use it in Code.

Full crawl your content source.

Now you are ready to rock.

Here is the simple code snippet for the query
SPSite spSite = new SPSite("<<your site name>>");
ServerContext src = ServerContext.GetContext(spSite);

using (Microsoft.Office.Server.Search.Query.FullTextSqlQuery fquery = new Microsoft.Office.Server.Search.Query.FullTextSqlQuery(src))
{
fquery.StartRow = 0;
fquery.RowLimit = 10;
fquery.HighlightedSentenceCount = 3;
fquery.EnableStemming = true;
fquery.TrimDuplicates = false;
fquery.KeywordInclusion = KeywordInclusion.AllKeywords;
fquery.ResultTypes = ResultType.RelevantResults;
string strcolumns = "Rank,Title, IsDocument,WorkId,Title,Author,HitHighlightedSummary,Size,Path,PictureThumbnailURL,CollapsingStatus,SiteName,Write,Description,ContentClass,HitHighlightedProperties";

fquery.QueryText = "SELECT " + strcolumns + " FROM Scope() WHERE ";
fquery.QueryText += " \"scope\" ='<<your ' AND ";
fquery.QueryText += “ FREETEXT(<<Your managed property name”, '" + << your search text >> + "') ) ";
fquery.QueryText += " ORDER BY Rank Desc";
ResultTableCollection rtCol = fquery.Execute();
ResultTable relevantResults = rtCol[ResultType.RelevantResults];
DataTable dt = new DataTable();
dt.Load(relevantResults, LoadOption.OverwriteChanges);
<<bind dt with grid>>
}



There is another discussion for how to use FullTextSqlQuery.
We will try provide you full information regarding this code, that how this code works, soon.
Try this stuff and let us know where you stuck.

How to start workflow programmatically

Hi All,

Sometimes i wonder about the Workflow triggering technique from the List and Document Library. I wonder because of one observation.

Let me share it with you, when you attach the workflow to a list or document library we have an option to configure it that when to trigger, is it on adding of the new item or is it on Updating the item. Adding a new item is a one time job, so for this scenario, it looks perfect for me.

But, when i consider trigger when updating item, it is something that i do not think this is done properly.

Because Once you open the ListItem for edit, do not edit anything and press OK. What happens, Still Workflow Triggers.

Now the question is, is it really cool to trigger the workflow even if you have not made any changes???????? I do not think so...


So bottom line is to check the proper condition in code and then dynamically from code, trigger the workflow.

Here is a way to trigger the workflow from code.

First you need to take the SPWorkflowManager Object.

SPWorkflowManager objWorkflowManager = null;


Then use SPWorkflowAssociationCollection object. every List and Document library has association with the workflow, to get this we have to use this object to collect all workflows which are associated with the List or DocumentLibrary.

SPWorkflowAssociationCollection objWorkflowAssociationCollection = null;

I consider that i am using Event Handler, if you are using this code anywhere else, change the Web and Site objects accordingly.


We have WorkflowManager object at Site Level, so first we will take it.

objWorkflowManager = item.Web.Site.WorkflowManager;


Then we will take all association of the workflow for specific list.

objWorkflowAssociationCollection = item.ParentList.WorkflowAssociations;


Now consider a scenario, where you have multiple workflows associated with the same list or document library. So First we need to find the correct Workflow Association to trigger only that workflow.

So for that first Loop through all Associations,

foreach (SPWorkflowAssociation objWorkflowAssociation in objWorkflowAssociationCollection)

{
if (String.Compare(objWorkflowAssociation.BaseId.ToString("B"), {"Workflow_GUID"}, true) == 0)

{

//We found our workflow association that we want to trigger.

//Replace the workflow_GUID with the GUID of the workflow feature that you
//have deployed.

objWorkflowManager.StartWorkflow(item, objWorkflowAssociation, objWorkflowAssociation.AssociationData, true);
//The above line will start the workflow...
break;
}
}


That's it. your job is done.

Saturday, September 13, 2008

Backup Restore in Server Farm (Recover disaster in MOSS)

Hi All,
This post will help you when your SharePoint Central administrator site has got disappeared suddenly from IIS / not opening or corrupted yet all rest of the sites are working well.
Following solution will also let you know, how to take farm backup in SharePoint Server farm?
Ok guys then you need to follow the following steps to get it back.
First take full backup of your farm.
To take a backup of your farm when you have suppose two SharePoint Servers and One database server
1. Server A at 192.168.1.1 IP
2. Server B at 192.168.1.2 IP
3. Database Server C at 192.168.1.3 IP
So create one folder at Server B (192.168.1.2) C:\Backup name it “Backup” right click it and Share this folder and give rights to “Every one user”.
stsadm –o backup –directory -backupmethod
Fire command stsadm –o backup –directory file://192.168.1.2/c$/backup -backupmethod “full”
Here, we are taking backup for our safety so that we can recover if any thing wrong happen.
Ok, good after taking backup take a backup of your all virtual directories because next step is to run SharePoint configuration wizard so it may replace your web.config in virtual directories so it is safe to take backup of virtual directories.
Now run SharePoint configuration wizard on any server. Select use existing server farm and select the same configuration database let wizard finish all steps.
Cheers, hope it will work for you.
For more information write us at sharpointkings@gmail.com
Let us know your feedback through comments or mail us if this solution works for you it will encourage us to write more articles.

SharePoint search Step by Step (Part 1)

This article is for How to using SharePoint search programmatically.

In this post we will show you only how to configure search from SSP.

Most of the time we have requirement for implementing custom SharePoint search. Because of custom business logic we need to search SharePoint content programmatically.

There is a lot of stuff available for SharePoint ECM search but not step by step from starting.

As this is our first post in search series so we are explaining the basic search.

The scenario: (in simple functional way)
We have a web application and in that a site collection.
In that site collection on the Top level site only we have lists and document libraries.
And we have to search on that site collection.
Search result will be on simple custom web part but not on the default one.
And the business logic must apply on result set. (We will take this in later posts)


Now here is how we start.
This post will explain how to configure SharePoint default search step by step.
Steps:
1) Make SharePoint default search up and running.
2) After getting result in SharePoint default search we will get the crawled content programmatically.
3) Use Microsoft.Office.Server.Search DLL to query and get specific result according to business logic.

Step 1)
Prerequisite: you must have and admin rights to configure search.
3 services should be started
1) Windows SharePoint Services Search
2) Office SharePoint Server Search
3) Indexing Service

Here is the link from where we got the basic reference.

First as per screen shot go to edit properties of SSP and change your password with the current one. This is none mandatory step but better to do so.



Go to SSP site.
Click on search setting.



Change Default content access account: with admin account



Click on “Content sources and crawl schedules”.
Edit “Local Office SharePoint Server sites”
Remove your site collection from Start Addresses and press ok.

Than create new contain source with Content Source Type as SharePoint Sites

And Start Addresses as your site collection. (that you removed from local office SharePoint Server Site)

And start full crawl



After these steps your default search should start.

After default search is running we will move towards get search result programmatically but you have to wait for the next post.

Friday, September 12, 2008

Turn off default send mail to newly added user

Hi All,

May times we require that it would be better if the default option (by default checked) when you add new user to site, it sends mail notification.

Use this option to send e-mail to your new users. You can personalize the message that is sent. This is the option which you find by default checked.

If you want to turn this off.

Do this steps.

(1) Open Program Files -> Common Files -> Microsoft Shared -> Web server
extensions -> 12 -> Template -> Layouts

(2) Open AclInv.aspx

(3) Find <wssawc:InputFormCheckBox
runat="server"
id="chkSendEmail"
Checked="True"
LabelText="<%$Resources:wss,aclver_SendEmailCheckbox%>"
ToggleChildren=true>

(4) You will find Checked = "True", make it "False", save it.

Your job is done. When you next time add user, the default Value will be unchecked for the Use this option to send e-mail to your new users. You can personalize the message that is sent. This is the option which you find by default checked option.

Thursday, September 11, 2008

How to get Image path of Type column in document library

Hi All,

Today i found one very interesting thing. I thought it may help you a lot in many cases.

I was developing webpart which functions like this.

I have document library and in that Document Library i have one column which specially identified a ContactID from other List. When i add that contact i also take the attachment and put it in that document library, so first when i get that ContactID (ID of the contact listItem), i insert a row in that document library with Contact ID in the ContactID column in that document library.

Because requirement was such that i needed to develop one webpart in which i can filter through the contact and see his/her related documents.

This post is not regarding this, but would be one of the scenario to explain what i am now about to tell you.

I also needed the icon with each respective documents. If the document is Docx, i needed to show the docx icon which sharepoint puts in Type column in Document Library. same goes for any files. Doc,Docx,XML,Xls,Xlsx,ppt etc.

so i wonder how sharepoint manages this, i tried to take the ListItem of the document library and tried to see that any of the Field gives the icon path or not. But no, none of the fields returns me the Icon of the path, or even none of the Field tells us that it uses which icon.

I search a bit, then i found that everything is in one Field which is called "DocIcon".

So assume that you have document library called "Shared Documents".

SPDocumentLibrary objDocLib =
(SPDocumentLibrary)SPContext.Current.Web.Lists["Shared Documents"];


Now, Lets say i am taking the First Document,

SPListItem objItem = objDocLib.GetItemById(1); // Make sure you have at least one doc, otherwise this will give Error

Now, Check for this condition,

if (objItem["DocIcon"] == null)


Because if sharepoint images does not have supporting type icon for that document type, lets say any file without any extesnion, this field will return you null. so first check this. now proceed.

string strFileType= Convert.ToString(objItem["DocIcon"]);


This returns you the type (it returns doc,docx,ppt,xls,xlsx,xml etc). So from here you can come to know what is the type of the document.

Now, interesting part comes. you must be wondering that OK, that is fine, but where is the icon path?

Here is a trick that i found,

Check the Images Folder inside C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\IMAGES.

Now Check you will find all the icons which sharepoint uses have .gif extension and all these icons have IC prefix with the extension and plus .gif at last. So have you got any hint? No??? no, problem, here we go. Check this out.

if (objItem["DocIcon"] == null)
{
picture.ImageUrl = @"_layouts\Images\" + "ICgen.gif";
}
else
{
picture.ImageUrl = @"_layouts\Images\" + "IC" + objItem["DocIcon"].ToString() + ".gif";
}


Consider picture as asp Image control, If you have noticed that if sharepoint does not have icon matching with the document type then it puts one white paper kind of icon and the name of that icon is ICgen.gif. so we have done same thing, if sharepoint does not have any supported icon for that document type, it will give objItem["DocIcon"] null. so we have also checked that and places the proper URL, and if we found that then we make combination of "IC" + objItem["DocIcon"].ToString() which is extension + ".gif" which is default extension of any images of sharepoint.

That's it. your job is done.

Tuesday, September 9, 2008

Attempted to perform an unauthorized operation.

Since last two days we are facing some strange error in SharePoint.
Attempted to perform an unauthorized operation

We are getting this error while updating something in SPWeb.

We are not getting why this error is occurred. We also try with admin login but still error shows that unauthorized operation.

Mean while we found strange solution for the strange problem.

Previously we are using SPWeb object with HTTPContext.Current.Web or properties.ListItem.Web in event handler.

Like
SPWeb objWeb= HTTPContext.Current.Web;
OR
SPWeb objWeb= properties.ListItem.Web;

But updating something regarding this web will cause this error.

So what we found that strange solution.
Do not use SPWeb object this way.
Create new SPWeb object with site.OpenWeb();

Like this
SPSite objSite = new SPSite(SiteUrl));
SPWeb objWeb= objSite. OpenWeb();

It worked for us.

But we don’t know what the reason will cause this problem and what the reason which solve this problem.

Friday, September 5, 2008

How to attach workflow to list from code

Hi All,

There may be the case where you need to Attach the Workflow to a list dynamically depending on several conditions in the code.

so here is the way to get this thing done from code.

For this, First you need to install the Workflow as a feature and then keep it there only, i suggest to install this feature at site collection level, so that you get this for each and every site where you need it.

Let me explain you several things,

Each web is having several workflow templates within. These are the default workflows that you can find when you go to the list or document library settings -> workflow settings. These are the templates for the workflow already installed for you to use. so when you navigate through the code, you will get all these.

Let's perform each step one by one.

(1) Navigate through the WorkflowTemplate collection on web. for this you need to use SPWorkflowTemplate class. Consider currentWeb as web.



SPWorkflowTemplate baseTemplate = null;

currentWeb.AllowUnsafeUpdates = true;

for (int iCount = 0; iCount <= currentWeb.WorkflowTemplates.Count - 1; iCount++)
{
if (currentWeb.WorkflowTemplates[iCount].Name == "{workflow_name}")
{
baseTemplate = currentWeb.WorkflowTemplates[iCount];
break;
}
}



Here just see that we have navigated through the workflow templates. Here you will find all default workflow names. Now as soon as you get your workflow name, you take that template in to the baseTemplate which is SPWorkflowTemplate object.

Now you have this object in your hand, you need to take two lists in your hand to get this work done.

(2)

SPList workflowhistory = currentWeb.Lists["Workflow History"];
SPList tasks = currentWeb.Lists["Tasks"];


These are the two lists which will be required when you will create the association with the list for workflow.

(3) Now create one association.

SPWorkflowAssociation newAssociation = null;

newAssociation = SPWorkflowAssociation.CreateListAssociation(baseTemplate,
"{Give name of the workflow}", tasks, workflowhistory);


As you can see, you have mentioned here the tasks list and workflowhistory list for this list.

(4) If you want to auto start this workflow at the time of new creating the item, set

newAssociation.AutoStartCreate = true;


Or if you want that when item is modified in the list, and at that time workflow triggers, set

newAssociation.AutoStartChange = true;


(5) Get the List object on which you want to attach the workflow.

SPList MyList = currentWeb.Lists["{listname}"];

MyList.AddWorkflowAssociation(newAssociation);

MyList.Update();

currentWeb.AllowUnsafeUpdates = false;


That's it. your job is done.

Thursday, September 4, 2008

Hide/Remove the View All Site Content link in SharePoint

Hide/Remove the View All Site Content link in SharePoint

Thanks a lot to Mark Wagner - Cogitation Blog who has showed a wonderful way of removing the “View All Site Content”.

http://www.crsw.com/mark/Lists/Posts/Post.aspx?ID=36


In our case we didn't need a feature to work it down. We preferred a delta change in the core.css. This made the change show fast.



There are many ways to do this.

One way is to open the default.aspx in Sharepoint Designer and remove the portion.
Another simple way of achieving this is to make a delta change in the
Core.css file

You can find the core.css file in the 12 Hive
12\TEMPLATE\LAYOUTS\1033\STYLES\CORE.CSS


Add this at the end of the file.

#ctl00_PlaceHolderLeftNavBar_idNavLinkViewAll
{
visibility:hidden;
}


Save it and refresh the page. “View All Site Content” is removed from the Site’s Quick Launch Menu.

Before the Delta change:



After the Delta change:

E-Mail notifications in Task List

Hi All,

May times it happens that we require to send a custom mail to a person who is assigned a task and not the default one that sharepoint sends for the task allocation.

In GUI, we can get through this when we go to Tasks List Settings -> Advanced Settings -> E-Mail Notification -> Select No for this.

This will do when you do it with the Interface.

Many times you may require to do it with the code, because may be you might not take any schema for tasks list because it's already there when you use Team Site as a template for your site.

So you need to programmatically set this property to false and then MOSS stops sending default task assigned message to a person to whom task gets allocated with the help of services.

Simple right this line.


SPList tasklist = Web.Lists["Tasks"];

tasklist.EnableAssignToEmail = false; //This property makes sending mail disabled

tasklist.Update();


That's it. your job is done.

Wednesday, September 3, 2008

Data at the root level is invalid. Line 1, position 1 in MOSS,WSS

Hi,
Today when I working on wss 3.0 / MOSS site suddenly I got an error saying , "Data at the root level is invalid. Line 1, position " . Then I come to know I have open one html file from virtual directory in SharePoint Designer, SharePoint designer automatically geneates some folder inside this directory which is the cause of an above error. so when I deleted this folder named "_vti_cnf" then site works fine..
hope will work for you... and you will take care in feature before openning files in SharePoint designer from your web application virtual directory...

Reference from http://forums.asp.net/p/985790/1270047.aspx#1270047

Setting Task Field Values in Custom .aspx Edit Form and accessing through ExtendedProperties

Hi All,

I have a desperate passion on working with windows workflow foundations, i love many things in that but at the same time certain thing happens in such a way that i think no, this should not be the case and never came to know why this happened.

Let me share you the scenario i faced before couple of days.

We know that when we make the aspx page that is associated with the Task Edit form, you can have the Task HashTable properties set on that page and then you can access those properties in the TaskChanged event in workflow.

I caught in a strange problem, i have made the properties on my custom task edit page, i was assigning the values in those HashTable Properties and retrieving them in TaskChangeevent handle in Workflow.

some of the properties have the same name and i was able to retrieve the values, but some of them gets converted to GUID and i cannot access them because they just do not exist in the HashTable collection. you have given some name to the properties and assign the value, but you have to retrieve that value with the help of that name of the property in workflow, but you will find that it will get converted in GUID.

I have done research on this, and suddenly i observed that all the properties which had name same as the any columns in the Task List, then it gets converted in GUID, Strange, very strange but yes this is true. and all those properties which are not the columns names in the Task List, i can retrieve them easily with the same name.

So Bottom line is never use any column name from TaskList in the HashTable collection of custom edit page for task edit, and once you have given property names which are not in the Task list, do not add any columns in the task list with the same column name which are in the property collection otherwise code will not find the column again and converts the column in GUID and you may lose value.



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