Monday, June 22, 2009

How to customize edit forms in SharePoint designer 2007

Hello Friends

v      Business Case:

Let’s say we have custom list and when any user enters a new item into list, every field must be editable, but when user edits any item, at that time some of fields should not be editable, they should come only for display purpose.

v      Possible Solution:

We can develop custom web part and write code to make some fields read only but we can easily achieve above functionality by just customizing edit forms into SharePoint designer.

v      Solution:

A very simple solution

1>     Open SharePoint Designer 2007

2>     Open your SharePoint site

3>     Open Custom list

4>     Select Editform.aspx and .right click on it same file

5>     Click on “New from Existing Page” Option value, it will create one new custom ASPX page for us from existing one.




















6>     Delete one web part which is already there into page and add click on Insert SharePoint Controls  -> Custom List Form.



7>     Select Appropriate List, it’s content type and Type of Form to create as per below image.

























8>     Click Ok button. It will automatically add one new Data Form Web part with all list fields in edit mode.

9>     Now you can change this form as per your needs and requirements. Like if you do not want some of fields then you can delete those fields from current page. In my requirement I have to make “EmployeeID” as read only field means user can see the field but they can’t change the field values..

10>  Select EmployeeID Field from user interface. Click on “tag Properties”, there you can see “Control Mode” as Edit.












11>  when you click on ControlMode option, you can see available values that are Invalid, Display, Edit and New. Select “Display” as option value for displays purpose.















12>  Save form under your current site name -> Lists->List Name and give file name with .aspx extension.


















13> Select List -> Right Click List Properties and Go to Supporting Files and In Edit Item Form Properties, Browse to Your newly created Form and click on apply and Save the site.



14>  Go to your SharePoint site .Select list and click on edit item, here in edit page you can see the result.

















In these ways from SharePoint designer, we can make some of the fields as read only and editable also, I think, SharePoint designer is very powerful tool; just we need to find in which way we can take advantage of designer functionality!!

How to access fields of List Item in ItemAdding and ItemUpdating event handlers into SharePoint

When we need to validate something or put restriction before adding or modifying data, at that time we need to use ItemAdding or ItemUpdating Event Handler, here I’ll demonstrate how to access fields of List into event handlers.

Example:

As per my requirements, I don’t want to add duplicate Name into List. For this I need to check that condition before I add and update item to List, I need to use “ItemAdding” and “ItemUpdating” event handlers

public override void ItemAdding(SPItemEventProperties properties)
{
string strName = string.Empty;

foreach (DictionaryEntry entry in properties.AfterProperties)
{
if (entry.Key.Equals("Name"))
{
strName = entry.Value.ToString();
}
}

SPList list = properties.OpenWeb().Lists[properties.ListId];
SPQuery query = new SPQuery();
query.Query = "<Where><Eq><FieldRef Name='" + list.Fields["Name"].InternalName + "' /><Value Type='Text'>" + strName + "</Value></Eq></Where>";
if (list.GetItems(query).Count > 0)
{
properties.Cancel = true;
properties.ErrorMessage ="Name already exists!";
}
}
public override void ItemUpdating(SPItemEventProperties properties)
{
string strName = string.Empty;
foreach (DictionaryEntry entry in properties.AfterProperties)
{
if (entry.Key.Equals("Name"))
{
strName = entry.Value.ToString();
}
}
SPList list = properties.OpenWeb().Lists[properties.ListId];
SPQuery query = new SPQuery();
query.Query=  "<Where><And><Neq><FieldRef Name='"+ list.Fields["ID"].InternalName+ "' /><Value Type='Number'>"+ properties.ListItemId+  "</Value></Neq><Eq><FieldRef Name='"+ list.Fields["Name"].InternalName+ "' /><Value Type='Text'>"+ strName+ "</Value></Eq></And></Where>" ;
if (list.GetItems(query).Count > 0)
{
properties.Cancel=true;
properties.ErrorMessage ="Name already exists!";
}
}

Wednesday, June 17, 2009

How to add/update SharePoint person/group field from Object model

While adding/updating the person/group field, we need to take care, because it’s required to be in specific format like value must be ID;#Name when assigning value.

Example code:
using (SPSite site = SPContext.Current.Site)
{
using (SPWeb web = site.OpenWeb())
{
try
{

web.AllowUnsafeUpdates = true;
string loginName = "domainname\\username";
SPUser theUser = web.SiteUsers[loginName];
SPList theList = (SPList)web.Lists["firstcustomlist"];
SPListItem theItem = theList.GetItemById(1);

theItem["usercol"] = theUser.ID.ToString() + ";#" + theUser.Name;
theItem.Update();
theList.Update();
}
catch (Exception ex)
{
string msg = ex.Message;
}
}
}

How to display users to SharePoint People Picker control and get data from SharePoint People Picker control

In below example, I’ll demonstrate how to display users to people picker web control and get data from the same control. I have field called “Staff Assigned” and its data type is People/Group.

Below code will tell us how we can take data from that people/Group field and display to people picker SharePoint web control and also get data from people picker and give back to people/Group field from object model programmatically.

//Display users from people/Group field to People Picker Control

if (itmAudit["Staff Assigned"] != null)
{
char[] to_splitter = { ';' };
string to_list = itmAudit["Staff Assigned"].ToString(); // Reads value stored in SPList. (i.e., "Domain\User1; Domain\User2")
string[] arr = to_list.Split(to_splitter);
string user = string.Empty;
System.Collections.ArrayList entityArrayList = new System.Collections.ArrayList();
for (int i = 1; i < arr.Length; i++)
{
if ((i % 2) != 0)
{
user = arr[i].Substring(arr[i].IndexOf("#") + 1);
PickerEntity entity = new PickerEntity();
entity.Key = user;
entity = userPicker.ValidateEntity(entity);
entityArrayList.Add(entity);
}
}

userPicker.UpdateEntities(entityArrayList);

//Save users to people/Group field from People Picker Control

SPFieldUserValueCollection values = new SPFieldUserValueCollection();
foreach (PickerEntity entity in userPicker.ResolvedEntities)
{
SPFieldUserValue fuv = new SPFieldUserValue(SPContext.Current.Web, Convert.ToInt16(entity.EntityData[PeopleEditorEntityDataKeys.UserId]), entity.Description);

values.Add(fuv);
}

itmAudit["Staff Assigned"] = values;

How to get Versioned Multi Line Text as Plain Text of Multiline Text (Append Text/Version Applies) Field in SharePoint

Example:

In custom list we have field “Comments” and it’s type is Multi Line Text with Version and selected ”Allow append text” as option, now if we want to check all Versioned Comments /History of comments with entered text, date and time and person name then if we try to access it’s field value programmatically by list item then it will always returns latest version.

Below code will explain and demonstrate how we can take version of multiline text values with username, date and time.
public static string GetVersionedMultiLineTextAsPlainText(SPListItem item, string key)

{

StringBuilder sb = new StringBuilder();

foreach (SPListItemVersion version in item.Web.Lists[item.ParentList.ID].Items[item.UniqueId].Versions)

{

SPFieldMultiLineText field = version.Fields[key] as SPFieldMultiLineText;

if (field != null)

{

string comment = field.GetFieldValueAsText(version[key]);

if (comment != null && comment.Trim() != string.Empty)

{

sb.Append("");

sb.Append(version.CreatedBy.User.Name).Append(" (");

sb.Append(version.Created.ToString("MM/dd/yyyy hh:mm tt"));

sb.Append(") ");

sb.Append(comment);

}

}

}

return sb.ToString();

}

Tuesday, June 16, 2009

Monday, June 15, 2009

Visual Studio 2005/2008 Sharepoint Workflow with Active Directory

Hello Friends

Business Case:

In Project, Requirement is like develop one workflow steps like

 1>     Create task and Assigned To is its manager which is decided by Active Directory

2>     Tasks are created like Originator à Project Manager à Director àDeputy à Superintendent. (Means we have to go to that level until whose manager does not exit.)

3>     For every user we have to create one task .If it is approved or deferred we have to send mail. If it is approved we have to send mail to person who has created task for the manager and create a new task for next level.

4>     Now if a person does not look at that task up to some duration we have to send email to person for overdue task and extend its due date for one day.

5>     If person deferred task workflow must be terminated. And email also sends for task is deferred or cancelled.

6>     Main requirement is that we have to search for manager from Active Directory.

Solution:

Develop a Sequential workflow.

Let us go into detail

1>     Create new project Project Type Sharepointà Sequential Workflow.

2>     Now Select activity that is “TaskCreated”.

3>     Then we have to add one while activity where we put one condition check that manager name is empty or not and if not then workflow must be stopped.

4>     Now there is one limitation of while activity is we add only one activity under while activity so I add one sequence activity and in that I add conditionactivitygroup there.

5>     In that I add one activity which is “CreateTask” Activity .Then on I add “OntaskCreated” Activity.

6>     Then I have to do like when task status changed from not started to Completed or Deferred we have to wait So I add one condition activity group which has condition like up to taskiscompleted == true.

7>     In group of activities I took 2 Sequence Activity. First Sequence activity is as under


























 8>     And another one is as follows.








































9>     In last once again we have to write one code activity which takes managername of current user.

10>  Workflow is completed

11>  How we can take manager name from Active Directory.

For that we have to use one directory Add reference

using System.DirectoryServices;

and also for regx you have to use

using System.Text.RegularExpressions;



        private string getManagersName(string employeesName)

        {

            string managersName = string.Empty;



            // Strip off the domain reference: eg: somecompany\\someusername. "somecompany\\" is the domain reference

            string cleanUserName = employeesName.Substring(employeesName.LastIndexOf('\\') + 1);



            // Setting the Active Directory folder to the root foler

            DirectoryEntry adFolderObject = new DirectoryEntry();



            // Creating the AD Searcher Object

            DirectorySearcher adSearcherObject = new DirectorySearcher(adFolderObject);



            // Setting the Search Scope to the AD Root tree and the subtree

            adSearcherObject.SearchScope = SearchScope.Subtree;



            // Get the UserName of the person who uploaded the document from the Document Library

            employeesName = workflowProperties.Item.GetFormattedValue("Created By");

             cleanUserName = Regex.Replace(employeesName, @"<(.|\n)*?>", string.Empty);



            // Set the Active Directory Search Filter to the, now stripped, username

            adSearcherObject.Filter = "(CN=" + cleanUserName + ")";



            // Execute the Active Directory Search

            SearchResult adObject = adSearcherObject.FindOne();



            // The Active Directory Search will return several properties for the Manager Object.

            // Store them in an array

            string[] properties;



            // Ensure that the user has a value in the Manager field

            if (adObject.Properties["Manager"].Count > 0)

            {

                // The properties are "," delimited, so we will split the properties on that character

                properties = adObject.Properties["Manager"][0].ToString().Split(',');



                // The Manager Name field starts with "CN=...", so stripping that off leaves us with the

                // Managers Name

                managersName = properties[0].Substring(3);



                // Get the Domain of the Users Active Directory Root

                string domain = adFolderObject.Name.Substring(3);



                // Convert the manager string to a SPU User Field

                managersName = workflowProperties.Web.AllUsers[domain + "\\" + managersName].ToString();

            }



            // return the managers name or an empty string, if there is no manager

            return managersName;

        }



12>  Second thing When you have list field type as “People Or Group” if you access fieldvalue and you want that thing display as “domainname\username”.You must have to use

employeesName = employeesName.Substring(employeesName.IndexOf(@"\") + 1);



13>  When you want to access some users which are in list and you want to use that name in task assigned list so you have to do one change and that is go to that edit that column and make Show Field as “Account”.







































Now I will give you concept wise description.

ConditionedActivityGroup:

The ConditionedActivityGroup activity is a CompositeActivity, meaning the ConditionedActivityGroup activity is group of other activities. The ConditionedActivityGroup activity runs and re-executes child activities based on the evaluation of their when conditions. All rules are evaluated whenever required based on their data and state change dependencies. All of activities until an until condition is true of ConditionActivityGroup.

UntilCondition = this._IsTaskCompleted == True

SequenceActivity :

The SequenceActivity is a CompositeActivity, meaning the SequenceActivity can contain other activities.

The SequenceActivity class coordinates a set of child activities in an ordered manner, one at a time. The SequenceActivity is completed when the final child activity is finished .There is one when condition is attached with Sequence Activity. If we do not specify that condition then it executes all activities under Sequence activity one at time but if we wish to executes all activities must run under some condition we can specify that thing under when condition and when it is true then and only then all activities run.

First Sequence Activity When Condition : None

Second Sequence Activity When Condition : this._IsTaskCreated == True && this._IsTaskCompleted != True

DelayActivity:

The Delay activity causes the containing branch of the workflow to wait for a specified amount of time

I need that otherwise workflow goes into infinite loop I have to tell workflow to wait for 2 minutes. Then check code condition for due date.

Web Part error “Custom Web part properties does not show up”

Today I was struggling with custom web part properties error; it was giving me error “Custom Webpart properties do not show up”.

The error solution was that if you inherit your web part from System.Web.UI.WebControls.WebParts.WebPart then you have to insert these lines for custom web part properties

[Personalizable(PersonalizationScope.Shared), WebBrowsable(true), SPWebCategoryName("MediaServerURL"),Category("Miscellaneous")].
And when you inherit your web part from this namespace Microsoft.SharePoint.WebPartPages.WebPart then you have to insert below lines for custom web part properties


[Browsable(
false), Category("Miscellaneous"), DefaultValue(defaultAssociatedListID), WebPartStorage(Storage.Shared), FriendlyName("AssociatedListID"), Description("AssociatedListID Property")]

I hope this will help to someone.

Sunday, June 14, 2009

How site Templates can be moved to Central Site Template Gallery

Hello Friends,

Business Case:

 In our organizations there are more than one Intranet Portals. Different web application like one is parent and web application for each department – its sub department, each for user required solutions (we called as application). Now main requirement is every portal has look wise same. Like every intranet portal must have some of lists like “Department, Divisions, Menus, etc. “. Some of intranet portal does not have Quick Launch and while some have. Welcome page must be same. Site themes some of font styles, home logo, banners must be same.

Problem:

Problem is for every application we have to manually create lists and makes entry as well as we have to change quick launch and also some other layouts modification we have to do manually from SharePoint Designer. Really a very tedious work for developers.

Existing Scenario:

Created web application from central Admin by selecting one of template from out of box and did manually changes. Same thing do again and again!! Wastage of time.

Possible Scenario:

So we decided that we have to create our own site Template and apply that site template to newly created web application depends on requirement whether we require new application with quick launch or not.

 Possible Solutions:

We have two options to create custom template 1) Site Definition 2) Site Template

Let me explain you when we have to use SiteTemplate & SiteDefinition and

When we discuss this topic how can we forget about Ghosting & UnGhosting and main topic is when we use siteTemplate how we can add that thing to CentralAdmin.

What is Ghosting-Unghosting & Difference between Ghosting & Unghosting:

When you create a new site, SharePoint doesn't have same pages for different sites— default.aspx and so on—into a new database table or directory. These files exist once and only once on each of the front end Web servers. Instead, SharePoint creates a reference to those files in the database tables that define the new site, a process called "ghosting." The outcome is that the site appears to have its own unique pages, but the pages are actually shared across all sites that use the same definition. So ghosting is jargon which is used in SharePoint 2003 and same concept but in SharePoint 2007 it is known by new word and that is “Uncustomized”.

This has two distinct advantages over copying the files to each site individually when the site is created. It saves space. Say example, If you have a hundreds sites, rather than having a hundreds copies of same file you still have only one copy. It improves performance. The server needs to cache only one copy from the file system, which can improve performance by freeing cache memory for other things. Loads the file from the Web server's local file system improves performance by eliminating the overhead of the database call and the network traffic to the database. One interesting benefit of this approach is that when you make a change to one file on the file system, that change takes effect across all the sites that have been created. There are some limitations like SharePoint can not ghost every page so we use concept Unghosting. Unghosting means when we customize page whose customization stored in database it is known as “unghosting” in SharePoint 2003 and “customized” in SharePoint 2007. Unghosting lets users customize their own sites without impacting other users who might be using the same file. But unghosting also has a performance impact negatively. Normally there are some of Site templates are already available which are out of box to Site Templates Like “Team Site”, “Blank Site”, Meeting workspace” There is very common and frequently requirement for customizing portal sites and other SharePoint sites. There are normally two approaches uses for customizing sites they are: 1> Site Definition 2> Site Templates Let I will give you description of every approach and also let you know when we have to use both.

 When to use Site Definition:

 A site definition defines a unique type of SharePoint site.When we use site definitions we require access to the file systems of the Web server. When we use site definition we will edit the Schema files directly. In spite of deploying a site definition requires more tedious and manually work, site definitions typically perform better when cached on the file system instead of in the database. We have finer level of customization by directly editing all the schema files and not depending on the existing site definition as a site template does. To introduce new file types, view styles, and drop-down edit menus, just need to edit the schema files that make up the site definition. Custom Site Definition also has capability of versioning. Using custom site definitions excludes your sites from potential upgrade issues. However, there is no easy way to modify site definitions once they are deployed. You can only add new types, view types to the site definition once it is deployed. 

 When to Use Site Templates Site templates, compared to site definitions, are easy to create and deploy. Because customization can be done through SharePoint Designer 2007 or user interface. Modification is really easy as compared to Site Definition and it does not effect to existing sites created by that templates. Deployment is simple because template data is stored centrally in the configuration database. Because it is slow to store templates in and retrieve them from the database, site templates can result in slower performance. Templates in the database are compiled and executed every time a page is rendered. Windows SharePoint Services does some performance optimization whereby it stores templates on the local Web server and a copy (or “ghost”) of the page in the configuration database. Rendering pages from the database will result in an initial performance penalty. If the site definition does not exist on the server, the site template fails.

 Solutions Offered Finally:

Typically, because of these issues, site templates are not as efficient as site definitions in a large-scale environment. It is used when we have to go for very small changes to like changes in logo, small things. Site templates are stored in the Site Template Gallery of the top-level site in a site collection, where they become available for subsite creation on all sites in the site collection.

How site Templates can be moved to Central Site Template Gallery?

Here it is: When we create some Site templates we can use it any site and now if you want to display that site template in Central Admin and apply it to entire web application and globally Available …we have to use stsadm command line tool and use addtemplate command. In my project we want one siteTemplate which does not have Quick Launch and some lists are common like Office, Division and Department. So first we think that we have to create site definition because we want that thing as globally available to Central Admin. But we are unaware of functionality of stsadm addtemplate command. Then once we know about that first I updated default.master from SharePoint Designer. In that site I added 3 lists Office, Division and Department. Then from siteSettings we save that template as Site Template to Local drive.

Then use command

stsadm –o addtemplate -filename “C:\CustomTemplate.stp” –title “A Template without Quick Launch” Description of the command is as follows:

 Command Syntax like: stsadm -o addtemplate -filename -title

 

Parameters


























ParameterValueRequired?Description
FilenameA valid file name, such as “C:\Templates\SampleTemplate.stp”YesFile name of the template that you are adding
TitleA valid title of a template, such as “Sample Template”YesTitle of the template that you are adding
descriptionA valid description of the template, such as “This is a sample template”NoDescription of the template that you are adding

 

Stsdm –o addtemplate –filename  “Path of file siteTemplatefile” –title  “Title of SiteTemplate when it displays at SiteTemplate Tag”

Don’t forget to do iisreset and now it is available to central admin as global template.

  • Second way to do this thing is:


In code, use AddCustomGlobalWebTemplate method of the SPGlobalAdmin class to add a site template to the gallery.

Friday, June 12, 2009

How to set version history of multiline into SharePoint list

Hello friends

When we need to maintain comments history in sharepoint list for every item , like comment description, User name and date and time of comments entered, what we need to do is , add one custom field in your list as “Comments “(or you can use any User Friendly field Name) and make its type as “Multi Line of Text” and make sure you select “Append changes to Existing Text”

List its versioning Settings must be set.

Now this will show you result of that Comments







So here may be same user or different user can add their comments and it display like User Name, Date-time of entered comment, and Comment Description in the same list item.

Tuesday, June 9, 2009

One of more field types are not installed properly in CAML Query

Hello Friends,
I got error "One of more field types are not installed properly" .
What does this mean?Let me first explain basic concept which is related to this error and you will find solution.
Concept:

Whenever creating any column for list, SharePoint creates three names for it.
  1. External name /Display Name to display in views, forms
  2. Internal name we use in CAMP Query, Assign Values
  3. Static Name : Name which is used by field type.
If you are creating field from code behind then you can assign internal name as per your choice, but when doing it through SharePoint interfface, it gives you option to enter display name, and it creates internal name by itself. When internal name is defined, if you have any of the non alphabet as part of name SharePoint converts them to special hex codes.
For e.g. trying to create field “Emp Name” gives internal name as “Emp_x0020_Name”
You can think like why this description is needed!!!But for the error like "One of more field types are not installed properly" in their applications.“You must understand this concept vey well. You must have clear picture of that.
So now for that error there is no problem with creating list and their fields.
The problem is simple:
CAML Query always uses Internal Name.
CAML Query uses Internal name not display name.If you have a field called "Program ID" (for example), in CAML you should refer to it as “Program _x0020_ID", because the internal name is encoded to avoid special characters.

Also, the internal name may be totally different from the display name - this will happen if you created a field and then renamed it.
Let’s Say we create a custom List name as “Employee” . Now Title field is already available.
Now I want to rename “Title” with “EmployeeID” But when I rename it ,it only and only changes display name but its internal name does not change. And Internal name is always created when we create field first time. We can not change internalname afterwards. So the internal name remains the same as the old name, but the display name changed. You can change the display name as many times as you want, but can never change the internal name once column is created.
So, how to know about the internal name for field?
Let me clear entire picture by elaborate an example. Every List has Field name as “Created By” field which is having internal name “Author” and Display Name as “Created By”.
If you want to know internal name of particular field how you can indentify .Go to ListàList Settingsà Click On Column (Created By) à so you have Edit Column Page. On that page you can see Column Name Textbox has its display name as “Created By”. Now Look at Addressbar It looks like this.
http://SharepointURL/_layouts/FldEditEx.aspx?List=%7BE6C3FC5E%2D04E6%2D4393%2DB637%2D031CE08C620B%7D&Field=Author
Internal Name of any field is identified by Field=InernalNanme. So Internal Name is for “Created By” is “Author”.
So Now If you wish some easier way to write CAML and do not want to find internal name by checking “Field” from address bar use Some CAML Query Builder.
I provide One table so you can convert Hex code to Character like Program _x0020_ID as so we have x0020=”” See last Row of this table “Program ID”

Character

Internal Hex Code

~

_x007e_

!

_x0021_

@

_x0040_

#

_x0023_

$

_x0024_

%

_x0025_

^

_x005e_

&

_x0026_

*

_x002a_

(

_x0028_

)

_x0029_

_

_

+

_x002b_

-

_x002d_

=

_x003d_

{

_x007b_

}

_x007d_

:

_x003a_


_x0022_

|

_x007c_

;

_x003b_


_x0027_

\

_x005c_

<

_x003c_

>

_x003e_

?

_x003f_

,

_x002c_

.

_x002e_

/

_x002f_

`

_x0060_
 
_x0020_


Disha Shah