Thursday, November 26, 2009

Add Lookup Column to SharePoint List Programmatically


In one of my previous article I discussed how to create a SharePoint list programmatically in C#. There I didn’t discuss how we can add lookup field for our newly created list. Let’s see how, this is a sample code.
        public void createList()
        {
            // choose your site
            SPSite site = new SPSite("http://merdev-moss:5050");
            SPWeb web = site.OpenWeb();
            SPListCollection lists = web.Lists;

            // create new Generic list called "My List"
            lists.Add("My List", "My list Description", SPListTemplateType.GenericList);

            SPList newList = web.Lists["My List"];

            // create Text type new column called "My Column"
            newList.Fields.Add("My Column", SPFieldType.Text, true);

            /*create lookup type new column called "Lookup Column"
            * Here I am going to get the information from the "Title"
            * column of a list called "User Roles"
            */
            SPList targetList = web.Lists["User Roles"];

            newList.Fields.AddLookup("Lookup Column", targetList.ID, false);
            SPFieldLookup lkp = (SPFieldLookup)newList.Fields["Lookup Column"];
            lkp.LookupField = targetList.Fields["Title"].InternalName;
            lkp.Update();

            // make new column visible in default view
            SPView view = newList.DefaultView;
            view.ViewFields.Add("My Column");
            view.ViewFields.Add("Lookup Column");
            view.Update();
        }
In the above code I have created Generic list and lookup column. You can use whatever list type and field type according to your requirement. To learn more about SharePoint lists, follow "SharePoint List C# Part 1".

Monday, November 23, 2009

Remove Event Receiver in Sharepoint List


In this post I’m going to describe how you can remove an Event Receivers from SharePoint List programmatically. This will be very useful if you have deployed and active custom features, because if you create a custom feature for a custom list, that feature will be added to all the custom lists. Then if you want to create list dynamically and don’t want to add those features you can use this code to remove unwanted events.
public void  removeEvents()
{
 // choose your site
 string strUrl = "http://mysite:5050/";
 using (SPSite site = new SPSite(strUrl))
 {
  using (SPWeb web = site.OpenWeb())
  {
   SPListCollection lists = web.Lists;
   SPList list = web.Lists["My List"];
      
   SPEventReceiverDefinitionCollection erdc = list.EventReceivers;
   List <SPEventReceiverDefinition> eventsToDelete = new List <SPEventReceiverDefinition>();
      
   foreach (SPEventReceiverDefinition erd in erdc)
   {
    if (erd != null)
    {
     try
     {
      eventsToDelete.Add(erd);
     }
     catch (Exception e)
     {
      Console.Write(e.ToString());
     }
    }
   }
   foreach (SPEventReceiverDefinition er in eventsToDelete)
   {
    //if(er.Type == SPEventReceiverType.ItemAdded)
    er.Delete();
   }  
  }
 }
}
Before delete the Event Receiver, if you want you can check the type and delete. In the above code I have commented that part. So if you use the above code as it is, it will remove all the Event Receivers.

Friday, November 13, 2009

SharePoint charting (Chart inside web part)


In my article on "SharePoint Web Part Development Tutorial" I discussed how we can develop and deploy custom SharePoint web part with visual designing. Now let’s see how we can add a chart for that web part. Finally you will be getting a result like following picture.



To create the above chart I’m getting data from a SharePoint list as follow.



You can see I’m showing the chart inside my custom web part called "My first custom Web Part". There I used the code from "Free Google Chart SharePoint Web Part" and customized it as I want. These are the steps to add nice chart to your web part for free.

First Create your custom web part, don’t deploy at this stage.

Then add a Class called “Chart.cs” and replace the code using following code.

View Code

using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using Microsoft.SharePoint;

namespace ProjectView{
public class Chart{

protected string _BGColor = "FFFFFF";
protected string _ChartColor = "0099ff,ff0000";
protected int _ChartHeight = 400;
protected LegendPositions _ChartLegend;
protected string _ChartTitle = "Burn Down Chart";
protected ChartTypes _ChartType;
protected int _ChartWidth = 720;
protected string _DataField = "Planned Effort,Actual Effort";
protected string _LabelField = "Title";
protected string _ListName = "";
protected string _SiteName = "http://merdev-moss:5050/";
protected string _ViewName = "";

public enum ChartTypes{
Line,
VerticalBar,
Pie,
Pie3D,
HorizontalBar
}
public enum LegendPositions{
horizontal_top,
vertical_left,
horizontal_bottom,
vertical_top,
vertical_bottom,
vertical_right
}
public string createChartString(string listName){
_ListName = listName;

string str = "";
string str2 = "";

SPSite site = new SPSite(this._SiteName);
SPWeb web = site.OpenWeb();
try{
if (!string.IsNullOrEmpty(this._ListName)){
SPList list = null;
SPListItemCollection items = null;
try{
string[] strArray3;
int num5;
list = web.Lists[this._ListName];
if (!string.IsNullOrEmpty(this._ViewName)){
SPView view = list.Views[this._ViewName];
items = list.GetItems(view);
}
else{
items = list.Items;
}
string str3 = "";
float num2 = 0f;
int num3 = 0;
bool flag = true;
char[] separator = new char[] { ',', ';' };
string[] strArray = this._DataField.Split(separator);
string[] strArray2 = new string[strArray.Length];
foreach (string str4 in strArray){
str2 = str2 + "<br>Series=" + str4;
if (!list.Fields.ContainsField(str4)){
str = str + "<p>Data List column not specified or not found:" + str4 + "</p>";
flag = false;
}
}
if (!list.Fields.ContainsField(this._LabelField)){
str = str + "<p>Label List column not specified or not found:" + this._LabelField + "</p>";
flag = false;
}
if (!flag){
goto Label_0868;
}
foreach (SPListItem item in items){
num3++;
try{
int index = 0;
foreach (string str5 in strArray){
string[] strArray7;
IntPtr ptr2;
float num = Convert.ToSingle(item[str5]);
if (num > num2){
num2 = num;
}
if (!string.IsNullOrEmpty(strArray2[index])){
string[] strArray6;
IntPtr ptr;
(strArray6 = strArray2)[(int)(ptr = (IntPtr)index)] = strArray6[(int)ptr] + ",";
}
string str6 = num.ToString().Replace(",", ".");
(strArray7 = strArray2)[(int)(ptr2 = (IntPtr)index)] = strArray7[(int)ptr2] + str6;
index++;
}
}
catch{
str = str + "<p>Data column error:" + this._DataField + "</p>";
}
try{
if (str3 != ""){
str3 = str3 + "|";
}
if ((this._LabelField != "LinkTitle") && (item.Fields[this._LabelField].FieldValueType == typeof(DateTime))){
str3 = str3 + ((DateTime)item[this._LabelField]).ToString("MMM yyyy");
}
else if (item[this._LabelField] != null){
str3 = str3 + item[this._LabelField].ToString();
}
continue;
}
catch{
str = str + "<p>Label column error:" + this._LabelField + "</p>";
continue;
}
}
string str7 = "";
string str8 = "";
string str9 = "";
string str10 = "";
string str11 = "";
string str12 = "";
string str13 = "";
if (!string.IsNullOrEmpty(str3)){
str3 = str3.Replace("&", "%26");
}
string str14 = num2.ToString().Replace(",", ".");
switch (this._ChartType){
case ChartTypes.Pie:
str7 = "p";
str9 = str3;
str12 = "0," + str14;
goto Label_051D;

case ChartTypes.Pie3D:
str7 = "p3";
str9 = str3;
str12 = "0," + str14;
goto Label_051D;

case ChartTypes.Line:
str7 = "lc";
str8 = "x,y";
str10 = "0:|" + str3;
str11 = "1,0," + str14;
str12 = "0," + str14;
goto Label_051D;

case ChartTypes.VerticalBar:
str7 = "bvg";
str8 = "x,y";
str10 = "0:|" + str3;
str11 = "1,0," + str14;
str12 = "0," + str14;
str13 = "a";
goto Label_051D;

case ChartTypes.HorizontalBar:
str7 = "bhg";
str8 = "x,y";
strArray3 = str3.Split(new char[] { '|' });
str3 = "";
num5 = strArray3.Length - 1;
goto Label_04DE;

default:
str7 = "p";
goto Label_051D;
}
Label_04AE:
if (str3 != ""){
str3 = str3 + "|";
}
str3 = str3 + strArray3[num5];
num5--;
Label_04DE:
if (num5 >= 0){
goto Label_04AE;
}
str10 = "1:|" + str3;
str11 = "0,0," + str14;
str12 = "0," + str14;
str13 = "a";
Label_051D:
if (str == ""){
object obj2 = str;
str = string.Concat(new object[] { obj2, "?chs=", this._ChartWidth, "x", this._ChartHeight });
if (!string.IsNullOrEmpty(this._ChartTitle)){
string str15 = this._ChartTitle.Replace(" ", "+");
str = str + "&chtt=" + str15.Replace("&", "%26");
}
str = (str + "&cht=" + str7) + "&chts=000000,17" + "&chd=t:";
int num6 = 0;
string[] strArray8 = strArray;
for (int i = 0; i < strArray8.Length; i++){
string text1 = strArray8[i];
if (num6 > 0){
str = str + "|";
}
str = str + strArray2[num6];
num6++;
}
str = str + "&chf=bg,s," + this._BGColor;
if (this._ChartColor != ""){
str = str + "&chco=" + this._ChartColor;
}
if (str9 != ""){
str = str + "&chl=" + str9;
}
if (str8 != ""){
str = str + "&chxt=" + str8;
}
if (str10 != ""){
str = str + "&chxl=" + str10;
}
if (str11 != ""){
str = str + "&chxr=" + str11;
}
if (str12 != ""){
str = str + "&chds=" + str12;
}
if (str13 != ""){
str = str + "&chbh=" + str13;
}
str = str + "&chg=" + ((100.0 / ((double)num3))).ToString("F") + ",20";
if (strArray.Length > 1){
str = str + "&chdl=";
int num7 = 0;
foreach (string str16 in strArray){
if (num7 > 0){
str = str + "|";
}
str = str + str16;
num7++;
}
str = str + "&chdlp=";
switch (this._ChartLegend){
case LegendPositions.horizontal_top:
str = str + "t";
break;

case LegendPositions.horizontal_bottom:
str = str + "b";
break;

case LegendPositions.vertical_top:
str = str + "tv";
break;

case LegendPositions.vertical_bottom:
str = str + "bv";
break;

case LegendPositions.vertical_left:
str = str + "l";
break;

case LegendPositions.vertical_right:
str = str + "r";
break;
}
}
str2 = str2 + "<br>" + str.Replace("&", "<br>&");
str = "http://chart.apis.google.com/chart" + str;
}
}
catch{
str = this._ListName + ": Sharepoint List not found!";
}
}
else{
str = "No Sharepoint List defined!";
}
}
catch (Exception){
str = "<br>Site not found:" + this._SiteName;
}
Label_0868:
return str;
}
}
}

Now change the variable names according to your site, list and columns.

Then Add this line to your .ascx file.

Now replace your "Page_Load" method as follows.

Now you can built and deploy your web part to see the result. You can get VerticalBar,Pie,Pie3D and HorizontalBar charts by changing the "ChartType" in the above code.

Create SharePoint list programmatically C#


In this article I’m going to discuss how we can create a SharePoint list programmatically in c# and how we can add columns to the created list. Actually this is very simple task; this is a sample code.
        public void createList()
        {
            // choose your site
            SPSite site = new SPSite("http://merdev-moss:5050");
            SPWeb web = site.OpenWeb();
            SPListCollection lists = web.Lists;

            // create new Generic list called "My List"
            lists.Add("My List", "My list Description", SPListTemplateType.GenericList);

            SPList list = web.Lists["My List"];

            // create Text type new column called "My Column" 
            list.Fields.Add("My Column", SPFieldType.Text, true);

            // make new column visible in default view
            SPView view = list.DefaultView;
            view.ViewFields.Add("My Column");
            view.Update();
        }
In the above code I have created Generic list and normal Text column. You can use whatever list type and field type according to your requirement. To learn more about SharePoint lists, follow "SharePoint List C# Part 1".

If you want to add lookup columns please refer "Add Lookup Column to SharePoint List programmatically".

To learn how to create List View, refer "Create SharePoint List View Programmatically".

Tuesday, November 10, 2009

Use Custom Workflow Actions in SharePoint Designer


In my previous article on "SharePoint Workflow Actions for Designer in Visual Studio" I discussed how to create and deploy a custom workflow action to use in the SharePoint designer.In this article I’m going to discussed how you can use the added action in the SharePoint Designer.

First open your site in the SharePoint Designer and create new workflow as shown in following figure.

new workflow

Then select the SharePoint list that the workflow should attached to and selects the start option of the workflow as following figure.



Now you can find the newly deployed custom action in the "Extras" category. Chose it and click the "Add" button. Then you have to specify the parameters if your custom action asked for them as follow.





Now everything is done and you can test your work flow. To do this, go to selected list and click on the arrow appear when you put the mouse on title of a list item. Then select the "Workflows" option.



Follow my article on "SharePoint Workflow Actions for Designer in Visual Studio" to learn how to create and deploy a custom workflow action to use in the SharePoint designer.

Friday, November 6, 2009

SharePoint Workflow Actions for Designer in Visual Studio


Using Microsoft Office SharePoint Designer 2007, you can design workflows without writing custom code. Microsoft has provided an article on Create a Workflow which helps you to get started by explaining some key design considerations and providing a basic procedure, but the problem is there are only few limited actions available in SharePoint Designer 2007 to develop your custom workflows (Figure 1).



You can develop custom actions using Microsoft Visual Studio 2005 or higher and deploy in your SharePoint server. Then you will see your custom action when you click More Actions (Figure 1).

In this article I’m going to show you how to add custom actions to SharePoint site and use it in SharePoint Designer 2007 to develop SharePoint workflows. For your ease here I have included all the necessary screen shots and coding step by step.

Building Custom Workflow

First create new project in Microsoft Visual Studio, there select Project Type as workflow and template as Workflow Activity Library (Figure 2). I have given "MyFirstWorkflow" for the name.



Then Add reference to the "Microsoft.SharePoint.dll" and "microsoft.sharepoint.WorkflowActions.dll". They can be found in your SharePoint server’s ISAPI folder (Figure 3 & 4).





You should copy those files from the same directory to a directory on your local computer if you are developing your project on a machine not having SharePoint or MOSS.

Now you can give a name to your Activity, Here I gave "SampleActivity" as Figure 5 and drag-and-drop codeActivity from Toolbox (Figure 6).





Now replace your Activity1.cs file using following code. If you are using different name spaces and class names, you have to change this code according to those names.
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
using Microsoft.SharePoint;
using System.Diagnostics;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;

namespace MyFirstWorkflow
{
    public partial class SampleActivity : SequenceActivity
    {
        SPList _list;
        private EventLog _log;

        public SampleActivity()
        {
            InitializeComponent();
        }
        public static DependencyProperty __ContextProperty = DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(SampleActivity));

        [DescriptionAttribute("__Context")]
        [BrowsableAttribute(true)]
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        public WorkflowContext __Context
        {
            get
            {
                return ((WorkflowContext)(base.GetValue(SampleActivity.__ContextProperty)));
            }
            set
            {
                base.SetValue(SampleActivity.__ContextProperty, value);
            }
        }

        public static DependencyProperty ListIdProperty = DependencyProperty.Register("ListId", typeof(string), typeof(SampleActivity));

        [DescriptionAttribute("ListId")]
        [BrowsableAttribute(true)]
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        public string ListId
        {
            get
            {
                return ((string)(base.GetValue(SampleActivity.ListIdProperty)));
            }
            set
            {
                base.SetValue(SampleActivity.ListIdProperty, value);
            }
        }

        public static DependencyProperty ListItemProperty = DependencyProperty.Register("ListItem", typeof(int), typeof(SampleActivity));

        [DescriptionAttribute("ListItem")]
        [BrowsableAttribute(true)]
        [DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
        public int ListItem
        {
            get
            {
                return ((int)(base.GetValue(SampleActivity.ListItemProperty)));
            }
            set
            {
                base.SetValue(SampleActivity.ListItemProperty, value);
            }
        }

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            _log = new EventLog("Add Description");
            _log.Source = "Share Point Workflows";

            try
            {
                //Execute method as a elevated method
                SPSecurity.CodeToRunElevated elevatedExecuteMethod = new SPSecurity.CodeToRunElevated(ExecuteMethod);
                SPSecurity.RunWithElevatedPrivileges(elevatedExecuteMethod);
            }
            catch (Exception ex)
            {
                _log.WriteEntry("Error" + ex.Message.ToString(), EventLogEntryType.Error);
            }
            return ActivityExecutionStatus.Closed;
        }

        private void ExecuteMethod()
        {
            try
            {
                //retrieveing the Site object
                SPSite _site = new SPSite(__Context.Site.Url);

                //retrieveing the Web object
                SPWeb _web = (SPWeb)(__Context.Web);

                //retrieveing the list object
                _list = _web.Lists[new Guid(this.ListId)];

                //retrieveing the list item object
                SPListItem _listItem = _list.GetItemById(this.ListItem);

                _site.AllowUnsafeUpdates = true;
                _web.AllowUnsafeUpdates = true;

                _listItem["Description"] = "This is sample description";

                _listItem.Update();
                _list.Update();

                _site.AllowUnsafeUpdates = false;
                _web.AllowUnsafeUpdates = false;
            }
            catch (Exception ex)
            {
            }
        }
    }
}
In the above code you can see some methods to get the current Site, Web, List and List Item. You don’t need to change those things. In the above simple example I have fill the "Description" column using my custom action written inside the "ExecuteMethod()" method. You can write any custom event which cannot be done using given actions in SharePoint designer.

Signing your Project

To deploy this custom workflow to GAC and the Microsoft Office SharePoint Server, we should assign a Strong Name key and sign the control.

To do this, right click the "MyFirstWorkflow" node in Solution Explorer and select Properties. Then select the Signing tab from the choices on the left. Check the "Sign the assembly" box and select from the "Choose a strong name key file" drop down list (Figure 7).



There give a key file name and click ok. Now you can build your project and ready to deploy.

Deploying to Server

To deploy your custom workflow action to the SharePoint server, follow these simple steps.

Drag and drop the compiled DLL (You can find it in your project folder's bin folder) into the Global Assembly Cache. The Global Assembly Cache is a special folder located at %WINDIR%\assembly where %WINDIR% is the full path to your Windows folder (e.g. C:\Windows or C:\Winnt).

Get the publicKeyToken property of our assembly. You can find it by right click on the file and select properties in "assembly" folder (Figure 8).



Update the "web.config file" by inserting fillowing line between <authorizedTypes> and </authorizedTypes> tags. (You can find your site’s web.config file in SharePoint server’s "C:\Inetpub\wwwroot\wss\VirtualDirectories\<your_site_port>" directory).
<authorizedtype Assembly="MyFirstWorkflow, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8f2766b10f337a33" Namespace="MyFirstWorkflow" TypeName="*" Authorized="True" />
Update the WSS.ACTIONS file by adding following line between

<Actions Sequential="then" Parallel="and"> and </Actions> tags. (You can find WSS.ACTIONS file in SharePoint server’s "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\1033\Workflow" directory).
<action Name="Add Description"
ClassName="MyFirstWorkflow.SampleActivity"
Assembly="MyFirstWorkflow, Version=1.0.0.0,
Culture=neutral, PublicKeyToken=8f2766b10f337a33"
AppliesTo="all"
Category="Extras">

<ruledesigner Sentence="Add Description to %1">
<fieldbind Field="ListId,ListItem" Text="this list" Id="1" DesignerType="ChooseListItem" />
</RuleDesigner>

<parameters>
<parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />
<parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />
<parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" />
</Parameters>
</Action>
Now deploying is completed, reset IIS and you can use your newly added custom action in the SharePoint Designer by going to "More Actions…" (Figure 1) when creating a workflow.

If you want more details on how to use custom actions when creating workflows follow my article "Use custom actions in SharePoint Designer".

Thursday, November 5, 2009

How to Select a Title for My Article


Your article title plays major role to driving long term search engine traffic. For the Title you have to give the overall idea of your article in simple phrase. The most important thing in article is making sure the title contains a strong keyword phrase.

Here I’m going to show you very simple way to select a best title for your article which contains a strong keyword phrase. I always use Query Suggestions in Google when selecting a title for my articles.

For example if I want to select a title for my article on developing SharePoint web part in visual studio, I’ll first search terms related to my article in Google. There as following picture you will be able to see what the things people search most are.



Then based on those results you can select the perfect title for your article by combining them. You can make this easier by using Google Keyword Tool. In the above example I selected my title as SharePoint Web Part Development Tutorial which contains most of keywords.

Wednesday, November 4, 2009

How To Make My Site Appear In Google Search

Search Engine Optimization (SEO) Techniques

If you search the above topic, in many articles you will see the same things like content is king, write unique content, get more back links etc. I was able to get significant traffic in to my blog within a 3, 4 weeks after starting it, because I used something really different than what you saw in other articles about SEO. This is how I did it.

Is the Content King?

Content is impotent but the king is website optimization. So you have to consider on both to get more traffic. You need to have good content but there the important thing is it should be different.

How to Optimize Your Pages?

First consider about Title tag of a particular page, your articles in that page should have a topic containing same key words appear in the Title. You can use bold and italics to highlight the keywords that are relevant to the article. If it is possible try to add those key words in to your main page.

If you are going to add META description tag and the META keywords tag they should have the same keywords that are relevant to the article's topic. Put your article related keywords in between H1, H2 and H3 tags. Use the ALT tag for images is always best practice.

Select the Correct Title for your Article

Here you should consider more about tour article’s title, keywords and header tags. They should match popular search keywords. I have discussed a simple way to do this in my article How to select a Title for my Article.

Back links, How I can Get Them?

Here one way back links plays major role in increasing link popularity. Two way links might be useful but one way back links have much higher weight. By submitting your website to forums, comments on blogs and using social networking websites you can get back links for your web site freely. I will write separate article on this topic soon.

Internal Linking

Internal links are very important. Here the tip is to let the internal link's anchor text contain the same keywords your original article has. For example when linking to your article that is called “ABC” from another page give the same link title as “ABC”.

Frequency of Update, Is It Important?

Yes, search engines give very high weight to frequently updated pages. Your search engine ranking will increase if your website gets updated frequently. More content gives more traffic, which is always true.

My Article Is New; Will It Appear in Search Result?

Yes, time doesn’t matter. You can see some new websites showing up in the top of Google search results after 3 or 4 weeks of their creation, you also can follow these things to achieve that. But remember old pages are always respected by search engines than newer ones.