Tuesday, November 6, 2012

Programming in Sharepoint 2010

Move Item and Document

​using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Configuration;
using System.Xml;
using System.Xml.Linq;
using Microsoft.SharePoint;
namespace BPCLContentArchival
{
    class MoveItemMethods
    {
        #region Global Variables
        private static string LogFilePath = ConfigurationManager.AppSettings["LogFileFolderPath"];
        private static string RecordListXML = ConfigurationManager.AppSettings["RecordListXML"];
        #endregion
       
        /// <summary>
        /// Logging is a method to add record in log Files
        /// </summary>
        /// <param name="exMessage">Pass Exception</param>
        /// <param name="functionName">Pass Meassage</param>
        private static void Logging(Exception exMessage, string functionName)
        {
            string FileName = Convert.ToDateTime(DateTime.Today).ToString("dd-MMM-yyyy");
            using (StreamWriter writer = File.AppendText(LogFilePath + "\\" + FileName + ".txt"))
            {
                writer.Write("\r\nLog Entry : ");
                writer.WriteLine("{0} {1}", DateTime.Now.ToLongTimeString(),
                    DateTime.Now.ToLongDateString());
                writer.WriteLine("  :");
                if (exMessage != null)
                {
                    writer.WriteLine("Source Function:{0}", functionName);
                    writer.WriteLine("  :{0}", exMessage.Message);
                    writer.WriteLine("  :{0}", exMessage.StackTrace);
                }
                else
                {
                    writer.WriteLine("Source Function:{0}", functionName);
                }
                writer.WriteLine("-------------------------------");
                // Update the underlying file.
                writer.Flush();
                // Close the writer and underlying file.
                writer.Close();
            }
        }
        /// <summary>
        /// CreateListNameTableStructure is  a method to Create DataTable Structure.
        /// </summary>
        /// <returns>Returns DataTable Structure</returns>
        public DataTable CreateListsNameTableStructure()
        {
            DataTable ListsName = new DataTable();
            DataColumn SiteUrl = new DataColumn("SiteUrl");
            DataColumn Source = new DataColumn("Source");
            DataColumn Destination = new DataColumn("Destination");
            DataColumn Type = new DataColumn("Type");
            try
            {
                /// Add Columns to DataTable.

                SiteUrl.DataType = System.Type.GetType("System.String");
                Source.DataType = System.Type.GetType("System.String");
                Destination.DataType = System.Type.GetType("System.String");
                Type.DataType = System.Type.GetType("System.String");
                ListsName.Columns.Add(SiteUrl);
                ListsName.Columns.Add(Source);
                ListsName.Columns.Add(Destination);
                ListsName.Columns.Add(Type);
                Console.WriteLine("CreateListsNameTableStructure() : Create DataTable Structure.");
                Logging(null, "CreateListsNameTableStructure() : Create DataTable Structure.");
               
            }
            catch (Exception ex)
            {
                Logging(ex, "Error in CreateListsNameTableStructure()");
            }
            finally
            {
                SiteUrl = null;
                Source = null;
                Destination = null;
                Type = null;
            }
            return ListsName;
       }
        /// <summary>
        /// ReadRecordXMl is a method to read values from XML File
        /// And Add values in DataTable
        /// </summary>
        /// <returns>Returns DataTable with values</returns>
        public DataTable ReadRecordXML()
        {
            //RecordListXML = "RecordListNames.xml";
            string SiteUrl = string.Empty;
            string Source = string.Empty;
            string Destination = string.Empty;
            string Type = string.Empty;
            DataRow row;
            DataTable ListsName = CreateListsNameTableStructure();
            string xmlPath = Path.GetFullPath(Environment.CurrentDirectory) +"\\"+ RecordListXML;
            Console.WriteLine("ReadRecordXML() : Record List XML Path=" + xmlPath);
            Logging(null, "ReadRecordXML() : Record List XML Path=" + xmlPath);
            XDocument groupsXml = XDocument.Load(xmlPath);
            try
            {
                var fields = from fieldsGroup in groupsXml.Root.Elements("Field")
                             select new
                             {
                                 SiteUrl = fieldsGroup.Attribute("SiteUrl").Value,
                                 Source = fieldsGroup.Attribute("Source").Value,
                                 Destination = fieldsGroup.Attribute("Destination").Value,
                                 Type = fieldsGroup.Attribute("Type").Value
                             };
                ///Start of For Loop: Add row with values from xml to DataTable
                foreach (var fieldsGroup in fields)
                {
                    row = ListsName.NewRow();
                    row["SiteUrl"] = fieldsGroup.SiteUrl;
                    row["Source"] = fieldsGroup.Source;
                    row["Destination"] = fieldsGroup.Destination;
                    row["Type"] = fieldsGroup.Type;
                    ListsName.Rows.Add(row);
                }
                ///End of For Loop
                Console.WriteLine("ReadRecordXML() : Add values from XMl file to DataTable.");
                Logging(null, "ReadRecordXML() : Add values from XMl file to DataTable.");
            }
            catch (Exception ex)
            {
                Logging(ex, "Error in ReadRecordXML()");
            }
            finally
            {
                 SiteUrl = null;
                 Source = null;
                 Destination = null;
                 Type = null;
                 row = null;
                 xmlPath = null;
                 groupsXml = null;
            }
            return ListsName;
        }
        /// <summary>
        /// MoveToDocLib is a method to move Document from Source Library to Destination Library
        /// </summary>
        /// <param name="siteUrl">Pass Site url of SiteCollection</param>
        /// <param name="Source">Pass Source Library Name</param>
        /// <param name="Destination">Pass Destination Library Name</param>
        public void MoveToDocLib(string siteUrl, string Source, string Destination)
        {
            SPQuery qry = new SPQuery();
            string camlquery = string.Empty;
            string destlibUrl = string.Empty;
            SPListItemCollection Srccollitem;
            SPList destlib;
            SPFile moveFile;
            try
            {
                using (SPSite rootSite = new SPSite(siteUrl))
                {
                    using (SPWeb spWeb = rootSite.OpenWeb())
                    {
                        //TODO: only less than operator
                        camlquery = "<Where>"
                                          + "<Lt>"
                                          + "<FieldRef Name='Expiry_x0020_Date' />"
                                          + "<Value IncludeTimeValue='FALSE' Type='DateTime' ><Today /></Value>"
                                          + "</Lt>"
                                          + "</Where>";
                        qry.Query = camlquery;
                        ///Get the Collection of SourceLibraryDocument by Caml Query
                        Srccollitem = spWeb.Lists[Source].GetItems(qry);
                        destlib = (SPDocumentLibrary)spWeb.Lists[Destination];
                        destlibUrl = destlib.RootFolder.Url;
                        ///Start of ForEach Loop to Move Document one by one from Source List ot Destination List.
                        foreach (SPListItem item in Srccollitem)
                        {
                            moveFile = item.File;
                            Console.WriteLine("MoveToDocLib() : FileName=" + item.File.Name + ", SiteUrl=" + siteUrl + ", Source=" + Source + ", Destination=" + Destination);
                            Logging(null, "MoveToDocLib() : FileName=" + item.File.Name + ", SiteUrl=" + siteUrl + ", Source=" + Source + ", Destination=" + Destination);
                            moveFile.MoveTo(destlibUrl + "/" + moveFile.Name, true);
                        }
                        ///End of ForEach Loop
                    }
                }
            }
            catch (Exception ex)
            {
                Logging(ex, "Error in MoveToDocLib()");
            }
            finally
            {
                 qry = null;
                 camlquery = null;
                 destlibUrl = null;
                 Srccollitem=null;
                 destlib=null;
                 moveFile=null;
           
            }
          
        }
        /// <summary>
        /// MoveToList is a method to move Item from Source List to Destination List
        /// </summary>
        /// <param name="siteUrl">Pass Site url of SiteCollection</param>
        /// <param name="Source">Pass Source List Name</param>
        /// <param name="Destination">Pass Destination List Name</param>
        public void MoveToList(string siteUrl, string Source, string Destination)
        {
            SPQuery qry = new SPQuery();
            string camlquery = string.Empty;
            SPListItemCollection Srccollitem;
            SPList destlib;
            SPListItem item;
            SPListItem targetItem;
            try
            {
                using (SPSite rootSite = new SPSite(siteUrl))
                {

                    using (SPWeb spWeb = rootSite.OpenWeb())
                    {
                        camlquery = "<Where>"
                                           + "<Lt>"
                                           + "<FieldRef Name='Expiry_x0020_Date' />"
                                           + "<Value IncludeTimeValue='FALSE' Type='DateTime' ><Today /></Value>"
                                           + "</Lt>"
                                           + "</Where>";
                        qry.Query = camlquery;
                        ///Get the Collection of SourceListItem by Caml Query
                        Srccollitem = spWeb.Lists[Source].GetItems(qry);
                        destlib = spWeb.Lists[Destination];
                        ///Start of For Loop to move items one by one from Source List to Destination List
                        for (int i = Srccollitem.Count - 1; i >= 0; i--)
                        {
                            item = Srccollitem[i];
                            targetItem = destlib.Items.Add();
                            ///Start of ForEach Loop to add value of each Field from Source to Destionation
                            foreach (SPField f in item.Fields)
                            {
                                //Copy all except attachments.
                                if (!f.ReadOnlyField && f.InternalName != "Attachments"
                                    && null != item[f.InternalName])
                                {
                                    targetItem[f.InternalName] = item[f.InternalName];
                                }
                            }
                            ///End of ForEach Loop
                            Console.WriteLine("MoveToList() : ItemName=" + item.Name + ", SiteUrl=" + siteUrl + ", Source=" + Source + ", Destination=" + Destination);
                            Logging(null, "MoveToList() : ItemName=" + item.Name + ", SiteUrl=" + siteUrl + ", Source=" + Source + ", Destination=" + Destination);
                            spWeb.AllowUnsafeUpdates = true;
                            targetItem.Update();
                            item.Delete();
                            spWeb.AllowUnsafeUpdates = false;
                        }
                        ///End of For Loop.
                    }
                }
            }
            catch (Exception ex)
            {
                Logging(ex, "Error in MoveToList()");
            }
            finally
            {
                qry = null;
                camlquery = null;
                Srccollitem=null;
                destlib=null;
                item=null;
                targetItem=null;
           
            }
           
        }
        /// <summary>
        /// GetArchivalDetails is a method to get Data from DataTable.
        /// And according to Type it Call method to Move File/Item from 1
        /// Library/List to another Library/List.
        /// </summary>
        public void GetArchivalDetails()
        {
            DataTable dt;
            string siteurl=string.Empty;
            string Source=string.Empty;
            string Destination=string.Empty;
            string Type=string.Empty;
            try
            {
                Console.WriteLine("GetArchivalDetails() : Start Of Function.");
                Logging(null, "GetArchivalDetails() : Start Of Function.");
                dt = ReadRecordXML();
                ///Start of For Loop to get parameter use to move Item.
                for (int i = 0; i < dt.Rows.Count; i++)
                {
                    siteurl = dt.Rows[i]["SiteUrl"].ToString();
                    Source = dt.Rows[i]["Source"].ToString();
                    Destination = dt.Rows[i]["Destination"].ToString();
                    Type = dt.Rows[i]["Type"].ToString();
                    Console.WriteLine("GetArchivalDetails() : SiteUrl=" + siteurl + ", SourceListName=" + Source + ", DestinationListName=" + Destination + ", Type=" + Type);
                    Logging(null, "GetArchivalDetails() : SiteUrl=" + siteurl + ", SourceListName=" + Source + ", DestinationListName=" + Destination + ", Type=" + Type);
                    if (Type == "Library")
                    {
                        MoveToDocLib(siteurl, Source, Destination);
                    }
                    else if (Type == "List")
                    {
                        MoveToList(siteurl, Source, Destination);
                    }
                }
                ///End of for Loop.
                Console.WriteLine("GetArchivalDetails() : End Of Function.");
                Logging(null, "GetArchivalDetails() : End Of Function.");
            }
            catch (Exception ex)
            {
                Logging(ex, "Error in GetArchivalDetails()");
            }
            finally
            {
                 dt=null;
                 siteurl = null;
                 Source = null;
                 Destination = null;
                 Type = null;
           
            }
           
        }
    }
}

Tuesday, 28 February 2012

Use to add or remove user from site collection Administrator in c# in sharepoint

using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.Administration;
using System.Configuration;

namespace CCMListUserProject.EventRCCMListUser
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class EventRCCMListUser : SPItemEventReceiver
    {

        private string SiteUrl = ConfigurationManager.AppSettings["SiteURL"];
        private string AdminUrl = ConfigurationManager.AppSettings["AdminUrl"];
        private string ListName = ConfigurationManager.AppSettings["CCMListName"];
        private string DomainName = ConfigurationManager.AppSettings["DomainName"];
       /// <summary>
       /// An item is being added.
       /// </summary>
       public override void ItemAdding(SPItemEventProperties properties)
       {
           base.ItemAdding(properties);
       }

       /// <summary>
       /// An item is being deleted.
       /// </summary>
       public override void ItemDeleting(SPItemEventProperties properties)
       {
           if (properties.ListTitle.ToString() == ListName)
           {
               SPListItem _currentItem = properties.ListItem;

               using (SPSite spSite = new SPSite(SiteUrl))
               {
                   SPWebApplication spwebapp = new SPWebApplication();
                   spwebapp = spSite.WebApplication;
                   SPSiteCollection allsitecoll;
                   allsitecoll = spwebapp.Sites;
                   foreach (SPSite site in allsitecoll)
                   {
                       SPWeb web = site.OpenWeb();
                       string CCMUserName = DomainName + "\\" + _currentItem["CCMUserName"].ToString();
                       SPUser objSpuser = web.AllUsers[CCMUserName];
                       objSpuser.IsSiteAdmin = false;
                       web.AllUsers.Remove(CCMUserName);
                       SPSecurity.RunWithElevatedPrivileges(delegate()
                       {
                           web.AllowUnsafeUpdates = true;
                           objSpuser.Update();
                           web.AllowUnsafeUpdates = false;
                       });
                   }

               }
               using (SPSite spSite = new SPSite(AdminUrl))
               {

                   SPWeb web = spSite.OpenWeb();
                   string CCMUserName = DomainName + "\\" + _currentItem["CCMUserName"].ToString();
                   SPUser objSpuser = web.AllUsers[CCMUserName];
                   objSpuser.IsSiteAdmin = false;
                   web.AllUsers.Remove(CCMUserName);
                   SPSecurity.RunWithElevatedPrivileges(delegate()
                   {
                       web.AllowUnsafeUpdates = true;
                       objSpuser.Update();
                       web.AllowUnsafeUpdates = false;
                   });

               }
           }    
           base.ItemDeleting(properties);
       }

       /// <summary>
       /// An item was added.
       /// </summary>
       public override void ItemAdded(SPItemEventProperties properties)
       {
           if (properties.ListTitle.ToString() == ListName)
           {
               SPListItem _currentItem = properties.ListItem;

               using (SPSite spSite = new SPSite(SiteUrl))
               {
                   SPWebApplication spwebapp = new SPWebApplication();
                   spwebapp = spSite.WebApplication;
                   SPSiteCollection allsitecoll;
                   allsitecoll = spwebapp.Sites;
                   foreach (SPSite site in allsitecoll)
                   {
                       SPWeb web = site.OpenWeb();
                       string CCMUserName = DomainName + "\\" + _currentItem["CCMUserName"].ToString();
                       web.AllUsers.Add(CCMUserName, "", "", "");
                       SPUser objSpuser = web.AllUsers[CCMUserName];
                       objSpuser.IsSiteAdmin = true;
                       SPSecurity.RunWithElevatedPrivileges(delegate()
                       {
                           web.AllowUnsafeUpdates = true;
                           objSpuser.Update();
                           web.AllowUnsafeUpdates = false;
                       });
                   }

               }
               using (SPSite spSite = new SPSite(AdminUrl))
               {

                   SPWeb web = spSite.OpenWeb();
                   string CCMUserName = DomainName + "\\" + _currentItem["CCMUserName"].ToString();
                   web.AllUsers.Add(CCMUserName, "", "", "");
                   SPUser objSpuser = web.AllUsers[CCMUserName];
                   objSpuser.IsSiteAdmin = true;
                   SPSecurity.RunWithElevatedPrivileges(delegate()
                   {
                       web.AllowUnsafeUpdates = true;
                       objSpuser.Update();
                       web.AllowUnsafeUpdates = false;
                   });

               }
           }    
           base.ItemAdded(properties);
       }

       /// <summary>
       /// An item was deleted.
       /// </summary>
       public override void ItemDeleted(SPItemEventProperties properties)
       {
           base.ItemDeleted(properties);
       }


    }
}

Thursday, 5 January 2012

Terms & Conditions in my link

Remove User who complete the Document

using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using System.Configuration;

namespace SharePointProject_RemoveUser.EventReceiver_RemoveUser
{
    /// <summary>
    /// List Item Events
    /// </summary>
    public class EventReceiver_RemoveUser : SPItemEventReceiver
    {
        private string libname = ConfigurationManager.AppSettings["MyDocumentLibraryName"];
        private string docstatus = ConfigurationManager.AppSettings["MyDocumentLibraryDocStatus"];
        private string docsharedmembers = ConfigurationManager.AppSettings["MyDocumentLibrarySharedMembers"];
        private string docAuthor = ConfigurationManager.AppSettings["MyDocumentAuthor"];
        /// <summary>
        /// An item was updated.
       /// </summary>
       public override void ItemUpdated(SPItemEventProperties properties)
       {

           try
           {

               if (properties.ListTitle.ToString() == libname)
               {

                   SPListItem _currentItem = properties.ListItem; /// Gets Items from listitem.

                   if (!string.IsNullOrEmpty(_currentItem[docstatus].ToString())) /// Check DocStatus not Empty.
                   {
                       if (_currentItem[docstatus].ToString().ToLower() == "completed") //// Check DocStatus is Completed
                       {
                           SPUser user = properties.Web.CurrentUser; // Getting Current User
                           string fieldValue = _currentItem[docsharedmembers].ToString(); ///Getting Mutiple Users from Shared Member.
                           string Author = _currentItem[docAuthor].ToString();  ///Getting Created by User.
                           SPFieldUserValueCollection users = new SPFieldUserValueCollection(_currentItem.Web, fieldValue); ///Collect Multiple Users.
                           SPFieldUserValueCollection AuthorUser = new SPFieldUserValueCollection(_currentItem.Web, Author); ///Collect created by User.
                           SPFieldUserValueCollection values = new SPFieldUserValueCollection(); ///Use to Store the Filter Users

                           ///Use this condition for clearing shared members field if Author completed the status
                           if (AuthorUser[0].User.LoginName.ToString().ToLower() == user.LoginName.ToString().ToLower() && users.Count >= 0)
                           {
                               users.Clear();
                               _currentItem[docstatus] = _currentItem[docstatus].ToString();
                               _currentItem[docsharedmembers] = users;
                           }
                           else
                           {
                               /// Use condition to Remove users from shared members field .
                               foreach (SPFieldUserValue uv in users)
                               {
                                   if (uv.User.LoginName.ToLower() != user.LoginName.ToLower())
                                   {
                                       values.Add(new SPFieldUserValue(properties.Web, uv.User.ID, uv.User.Name));
                                   }
                               }
                               _currentItem[docstatus] = ""; ///empty the status field
                               _currentItem[docsharedmembers] = values;
                           }

                           _currentItem.Update();

                        
                       }

                   }


               }
           }
           catch (Exception)
           {

               //   throw;
           }
         

           base.ItemUpdated(properties);
       }


    }
}

Monday, November 5, 2012

Create a Workflow using Visual Studio 2010

Introduction

In this article we can experiment with creating a Workflow using Microsoft Visual Studio 2010. Visual Studio along with SharePoint 2010 Extensions provides sophisticated development tools to enable Workflow development.

Types of Workflows

There are basically two types of workflows inside Visual Studio:
  • Sequential Workflow
  • State Machine Workflow
Sequential Workflow once invoked continues execution until it is completed.
State Machine Workflow will have states persisted in between. The state could be continued execution between machine restarts.
In this example we are trying to create a Workflow which on activation updates the null Address column of the Manager list. (You need to have a Contact template named Manager.)
Step 1: Create Sequential Workflow Project
For the time being, we can start with a Sequential Workflow. Start Visual Studio and create a new project from the template SharePoint > Sequential Workflow.

In the next screen select the option Site Workflow as shown below:

In the next screen, leave the default option saying the user manually starts the Workflow. Click the Finish button to create the project.

You will get the following screen once the project is created.

Step 2: Create Activity
We need to create an Activity to perform our job.

What is an Activity?

A Workflow consists of a series of Activities. We can add Activities using the Toolbox. There are different types of Activities like Code Activity, SendEmail, etc. For our example we are using the more functional Code Activity.

Drag and drop a Code Activity from the toolbox. You can locate this from the v3.0 group inside Toolbox.

Step 3: Add code for the Activity
Now we need to add code for this Activity. Double click on the codeActivity1 item shown above. Place the following code in the appearing code view.
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
    using (SPWeb web = SPContext.Current.Web)
    {
        SPList list = web.Lists["Manager"];
        foreach (SPListItem item in list.Items)
        {
            if (item["Address"] == null)
            {
                item["Address"] = "PLEASE SET THE ADDRESS!";

                item.Update();
            }
        }
    }
}
Step 4: Build and Deploy the Solution
Now we are ready to build and deploy the solution. Right click on the solution and use the Build and Deploy command.

Step 5: Execute the Workflow inside SharePoint
Now we are ready to test the Workflow inside SharePoint. As the Workflow was created as a Site Workflow it will be accessible for all the Lists and Libraries. You can click the Lists link inside the site.

Now click on the Site Workflows link. You will get the following screen.

Before executing the Workflow, you need to create a Manager item with Address not assigned.
Click on the highlighted button and your workflow gets executed. Wait for a while and you can see the invalid manager record is updated with the message.

This concludes our article on Workflow using Visual Studio.

SharePoint 2010: Programming with Business Data Connectivity Model Using Visual Studio 2010

Abstract: In this article, we will be discussing integration between SharePoint 2010 web site and External Data Source using Visual Studio 2010 Business Data Connectivity Model project template
SharePoint as a web application platform is becoming popular amongst various domains of application development. There are several requirements for integrating a SharePoint 2010 Web Site with an external system which consumes data. If a developer has a strong programming background using Visual Studio 2010, the SharePoint 2010 Templates integrated with VS2010 prove useful to provide such an integrated solution.
In today’s scenario, where SharePoint 2010 based applications are used for automation purpose, similar integration requirements are going to popup every now and then. In VS 2010, the ‘Business Data Connectivity Model’ project template allows developers to design solutions for SharePoint 2010 for External Data Source integration.
In this article, we will be discussing integration between SharePoint 2010 web site and External Data Source using VS 2010 capabilities. You may be having some doubts about whether to use SharePoint 2010 Designer or Visual Studio 2010 for external content types, so here are some differences between them:
  • SharePoint Designer 2010 directly connects to the SharePoint 2010 site and external content type is directly written in the business data store. Unlike SPS 2010 Designer, VS2010, creates a model file with extension “.bdcm”. This file defines all external content types. This file then gets packaged into the project output assembly and then gets deployed as .WSP file in SharePoint 2010.
  • VS 2010 allows External Content Types (having data provided by .NET assemblies), which makes the code in the assembly as a proxy for External Data communication. Such an approach allows developer to add custom security code, additional business rules for working with more than one data source at a time.
For this application, I am using an already existing site ‘hxxp://win-v04rsve054t/sites/ss’. The SQL Server Database used here is ‘Company’ and the table is as shown below
image

Working with External Data Communication using VS 2010

Step 1: Open VS2010 and Create a new Empty SharePoint Project, name it as ‘SPS_ECM_ProductList’.
image002
Make this project as deploy as farm solution as shown below:
image
Step 2: In this project, right click and add a new Business Data Connectivity Model, name it as ‘ProductModel:
image
Once you click OK, a model gets generated as shown below:
image
If you have worked with ADO.NET Entity Framework, you will find a similar type of entity generated. The reason behind this similar type of representation is because the BDCM is based upon ADO.NET EF. The Identifier1 represents the primary or Identity for the Item from the source. The ReadList method is designed to return collection type of data from the source and ReadItem is defined to return a single record from the source.
Step 3: For this demo, we are going to use LINQ to SQL for connecting to SQL Server database and its ProductInfo table. On the project, right click and add a new LINQ to SQL class as shown below and name it as ‘ProductInfoDataModel’:
image006
Complete the Database connectivity Wizard.
image007
Step 4: Once the DataModel is available with us, it’s time to configure the BCDM. Rename ‘Entity1’ to ‘ProductInfo’ and ‘Identity1’ to ‘ProductID’ and set its type to Int32 as shown below:
image008
The final design will be as shown below:
image009
Step 5: Now is the time for us to define operations (methods) for BCDM. Open BDC Explorer and rename ‘ReadList’ to ‘ReadProductList’, Expand ‘ReadProductList’ and rename the returnParameter from ‘Entity1List’ to ‘ProductList’ as shown below:

image010
This is an out return type from the method. Now right-click on ‘ProductList’ and select ‘properties’, as shown below:
image011
Click on Type Name
image012
Select ‘ProductInfo’, as the method returns a List of ProductInfo and keep the ‘Is Enumerable’ checkbox checked, which indicates that the collection will be returned from the method.
Expand ProductInfo and you will find ‘Identifier1’ and ‘Message’ properties there, so change them to ‘ProductInfo’ properties. Right-Click on ‘ProductInfo’ and select ‘Add Type Descriptor’ and add ProductID, ProductName,Manifacturer and Price in it and set its data types. The final design will be as shown below:
image013
Step 6: Now repeat similar steps for ‘ReadItem’ method and rename it to ‘ReadProduct’. To define ‘id’ and ‘return’ parameter, copy the ProductInfo from ‘ReadProductList’ and paste in ‘returnParameter’ of ‘ReadProduct’. Just click on ‘Yes’ in the message box that appears
image014
Also copy ‘ProductID’ from the returnParameter of the ReadProductList and paste it in the ‘id’ of the ‘ReadProduct’ method. You will see a similar message as shown above for replacing Type Descriptor, just click ‘Yes’
image015
Step 7: Click on ‘ProductInfo’ in BDCM designer, the method info will be as shown below:
image016

Step 8: Now we need to add Create, Update and Delete method. So click on the ‘Add to Method’ at the bottom:
image017
You will get a List of methods:
image018
Add Creator, Updater and Deleter methods and rename them as ‘CreateProductInfo’, ‘UpdateProductInfo’ and ‘DeleteProductInfo’
image019
image020
image021

Step 9: Now its time for us to write the code for database connectivity and implement Create, Read, ReadList, Update and Delete methods. Now the question is how to configure the Database ConnectionString to BDCM and access it in code. Go to the BDC Explorer and select ‘LocalSystemInstances’, rename ‘ProductModel’ to ‘productModelDBConnect’, go to the properties and select ‘Custom Properties’ and add a connection string as shown below:
image022
In the project, add a reference to ‘Microsoft.BusinessData’ assembly from the following path:
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\ISAPI\Microsoft.BusinessData.dll
Step 9: Open ‘ProductInfoService.cs’ and write the following code which performs CRUD operations:
using System;
using System.Collections.Generic;
using System.Linq;
using SPS_ECM_ProductList;
using Microsoft.BusinessData.SystemSpecific;
namespace SPS_ECM_ProductList.ProductModel
{
/// <summary>
/// All the methods for retrieving, updating and deleting data are implemented in this class file.
/// The samples below show the finder and specific finder method for Entity1.
/// </summary>
public class ProductInfoService : IContextProperty
{
internal string AccessConnectionString()
{
Microsoft.BusinessData.MetadataModel.Collections.INamedPropertyDictionary dictionary =
this.LobSystemInstance.GetProperties();
if (dictionary.ContainsKey("CompanyConnStr"))
{
return dictionary["CompanyConnStr"].ToString();
}
return null;
}
/// <summary>
/// This is a sample specific finder method for Entity1.
/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.
/// </summary>
/// <param name="id"></param>
/// <returns>Entity1</returns>
public ProductInfo ReadProduct(int id)
{
ProductInfoDataModelDataContext objContext =
new ProductInfoDataModelDataContext(AccessConnectionString());
ProductInfo Product = objContext.ProductInfos.Single(p => p.ProductID == id);
return Product;
}
/// <summary>
/// This is a sample finder method for Entity1.
/// If you want to delete or rename the method think about changing the xml in the BDC model file as well.
/// </summary>
/// <returns>IEnumerable of Entities</returns>
public IEnumerable<ProductInfo> ReadProductList()
{
ProductInfoDataModelDataContext objContext =
new ProductInfoDataModelDataContext(AccessConnectionString());
return objContext.ProductInfos.ToList();
}
public ProductInfo CreateProductInfo(ProductInfo newProductInfo)
{
ProductInfoDataModelDataContext objContext =
new ProductInfoDataModelDataContext(AccessConnectionString());
objContext.ProductInfos.InsertOnSubmit(newProductInfo);
objContext.SubmitChanges();

ProductInfo Product =
objContext.ProductInfos.Single(p => p.ProductID == newProductInfo.ProductID);
return Product;
}
public void UpdateProductInfo(ProductInfo productInfo)
{
ProductInfoDataModelDataContext objContext =
new ProductInfoDataModelDataContext(AccessConnectionString());
ProductInfo Product = objContext.ProductInfos.Single(p => p.ProductID == productInfo.ProductID);
Product.ProductName = productInfo.ProductName;
Product.Manifacturer = productInfo.Manifacturer;
Product.Price = productInfo.Price;
objContext.SubmitChanges();
}
public void DeleteProductInfo(int productID)
{
ProductInfoDataModelDataContext objContext =
new ProductInfoDataModelDataContext(AccessConnectionString());
ProductInfo Product = objContext.ProductInfos.Single(p => p.ProductID == productID);
objContext.ProductInfos.DeleteOnSubmit(Product);
objContext.SubmitChanges();
}
public Microsoft.BusinessData.Runtime.IExecutionContext ExecutionContext
{
get;
set;
}
public Microsoft.BusinessData.MetadataModel.ILobSystemInstance LobSystemInstance
{
get;
set;
}
public Microsoft.BusinessData.MetadataModel.IMethodInstance MethodInstance
{
get;
set;
}
}
}

The above code shows that an interface ‘IContextProperty’ is implemented which can access the Business Data Connectivity service. The method ‘AccessConnectionString’ reads the ConnectionString from the ‘LocSystemInstance’ properties collection using the Key of the Connection string set in Step 8.
Step 10: Open Feature1.Template.xml and add the following Xml which helps in deploying the application on the web site.
<Properties>
<Property Key="SiteUrl" Value="hxxp://MyServer/sites/ss"/>
</Properties>
Step 11: Deploy the application and using F5 to run it. This will start the SharePoint web site. To display the ProductInfo List on the Quick launch, click on ‘Site Actions’ on the top-left and select ‘More Options’ as shown below
image023
This action will open the ‘Create’ window. Select ‘Data’ from Filter type and select ‘External List’ as shown below:
image024
Click on the ‘Create’ button. A new Window will open where you need to set the Name of the List and also choose the External Content type to use as the Data source for the list:
image025
This will open the ‘External Content Type Picker’ window. Select ‘ProductModelDBConnect’ and click on ’OK’:
image026
This takes you back to the previous window where you Click on ‘Create’ and a new List will be created on the Quick Launch bar of the site.
Step 13: Now to set the access rights from the SharePoint Site to External Data Source, add the current login user from the List and set its access rights. You can do this using the ‘Central Administration Web Site’. Select ‘Application Management’ > Service Applications > Manage Service Applications > Business Data Connectivity Service. Here Select ‘ProductInfo’ checkbox and click on ‘Set Objects Permissions ’:
image027
Add the User and set his/her rights as shown below :
image028
This is required because the connection will be made from your Web Site hosted in IIS, to the External Data Source using Business Data Connectivity Web Service. So to authenticate and authorize the user, we need to set the access rights. Click on Ok.
Step 14: Return to the site and click on the ‘ProductInfoList’ (note: Your application in VS2010 must be running). A List Data appears:
image029
Now you can test your Insert, Update and Delete operations.
Note: You must deploy the project assembly created in VS2010 in GAC so that it can be used by Web Site for performing CRUD operations.
Conclusion: Using VS 2010 SharePoint template, it is easy to design more controlled source code for Business Data Connectivity model using sophisticated programming methodology. Here a developer has complete freedom to implement domain specific logic to establish connectivity to an external data system from the SharePoint Web site.

Sunday, November 4, 2012

SharePoint 2010: Change the “Add New Item”

The Goal

To change from “Add new item”:
    AddNew1
to “Click here to add team tasks”:
    AddNew2

ID’s used by web parts

Each web part has a different ID and some share a common ID. You will need to modify the following code examples with the ID used by your list. Note that some lists share the same ID, like Tasks and KPIs.
Note: Many of these IDs have changed in 2010!
If the ID you need is not in this table, display the web page with the web part, use the browser’s View Page Source option and search for the message text. Then look backward in the <A> tag and find the ID.
Web Part Default message ID for “.getElementById” in the code below
Announcements Add new announcement “idHomePageNewAnnouncement” (changed in 2010)
Links Add new link "idHomePageNewLink" 
Calendar Add new event "idHomePageNewEvent"
Picture Library Add new picture “idHomePageNewItem”  *  (changed in 2010)
KPI List Add new item "idHomePageNewItem"  *  (changed in 2010)
Tasks Add new item "idHomePageNewItem"  *  (changed in 2010)
Project Tasks Add new item "idHomePageNewItem"  *  (changed in 2010)
Document Library Add new document "idHomePageNewDocument"  (changed in 2010)
Wiki Add new Wiki page "idHomePageNewWikiPage"   (changed in 2010)
Discussion Add new discussion "idHomePageNewDiscussion"  (changed in 2010)
Custom List Add new item “idHomePageNewItem” *   (changed in 2010)
* = Shared with another list

If there is only one “Add new” message on a page

I.e. there is only one web part on the page that uses that ID then we can use this simple code:
<script>
  document.getElementById("idHomePageNewItem").innerHTML="your new text goes here"
</script> 

But the IDs won’t always work!

SharePoint can build pages with multiple elements with the same ID. This is not proper HTML, but, they do it…
So we will need something a little more complex:
<script>
var ttnA = document.getElementsByTagName('A');
for (var j=0; j<ttnA.length; j++)
{
  if (ttnA[j].id == 'idHomePageNewItem')
  {
    ttnA[j].innerHTML='your new text goes here'
  }
}
</script>
This code runs through all of the Anchor (<A>) tags in the page looking for the ones with the ID we need and then changes the text as needed.
What if you only wanted to change the second web part that uses that ID to a new message? Then try this:
<script>
var ttnA = document.getElementsByTagName('A');
var ttnCounter = 0;
for (var j=0; j<ttnA.length; j++)
{
  if (ttnA[j].id == 'idHomePageNewItem')
  {
    ttnCounter ++;
    if (ttnCounter == 2)
      { ttnA[j].innerHTML='your new text goes here' }
  }
}
</script>

Where should you add the code?

Add the code to the page using SharePoint Designer
  1. Edit the page using SharePoint Designer
  2. Find the “<asp:content” tag for PlaceHolderMain and then find the matching end tag (“</asp:content>”)
  3. Just before the end tag, add the JavaScript listed above
Or add a Content Editor Web Part to the page
This is the easiest for testing, and does not require SharePoint Designer. In SharePoint 2007 this worked equally well for web part pages and View pages. In SharePoint 2010, adding a web part to a View page causes the View selector dropdown to be hidden, so the SharePoint Designer approach might be better for View pages. The CEWP works just fine for web part pages and the new “wiki style” home pages. The only got’ya is that they have removed the Source Editor button from the CEWP. If you use the Edit HTML button in the Ribbon you may find that your HTML and JavaScript gets modified by their editor. Best practice with the 2010 CEWP is to store your HTML and JavaScript in a text file in a library and then use the CEWP’s link to a file option.
  1. Create a text file with the JavaScript code and upload to a library
  2. In the library right-click the file, click Properties and copy the URL of the file
  3. Add an Content Editor Web Part (CEWP) below the web part you want to customize
  4. From the CEWP click web part’s dropdown arrow and click Edit Web Part
  5. Paste the URL you copied into the Content Link box

Hide the “+” image?

If you want to get rid of the little icon just before the “New Item” text then just add one more line of code after where you change the message:
     ttnA[j].innerHTML='Click here to add team tasks';
     ttnA[j].previousSibling.previousSibling.style.display='none';

 image    image

Hide the entire message?

No tricks needed!  Just edit the web part and change the “Toolbar Type” to “No Toolbar”. (The “New” link we’ve been working with is the “Summary Toolbar”.)
image

Deploying a custom master page

Deploying a custom master page in SharePoint 2010

Lately I’ve been playing around with Visual Studio 2010 tools for SharePoint. I’ve been trying to come up with examples on how to use each of the available item templates.
Today I created a Module. A module can be used to deploy files to your SharePoint environment and the scenario I came up with was to use a module to deploy a master page.
  • I started out by creating an Empty SharePoint project. This can have any name you like and it can be both a farm and a sandboxed solution
  • Next add an new item to the project and choose a module
  • You can rename the module if you want to, I will leave the name at Module1
  • After the module is created it contains an elements.xml file and a sample.txt file. The sample.txt file can be renamed to sample.master.
Project structure
Project structure after adding a module and renaming the sample file to sample.master
I’m not a designer, so I wasn’t interested in creating a brilliant new design (good job, because I wouldn’t be able to do that!).
For the purpose of this example I just took the standard SharePoint 2010 master page contents.
  • Open up SharePoint Designer and open the site you are working on
  • Choose Master Pages on the left side
  • Open v4.master
Don’t let SharePoint fool you. There is a default.master, but this is the old SharePoint 2007 master page that is used if you perform a visual upgrade. When creating a site in SharePoint 2010 the master page that will be used by default is v4.master. I know it’s a bit confusing, but if you have been working with SharePoint for a while you won’t be surprised by this.
  • Copy the contents of v4.master and past them in your sample.master file in Visual Studio. Make the changes you want to.
  • Note how the elements.xml file has changed to reference the sample.master rather than the sample.txt
Contents of the elements.xml file 
The contents of the elements.xml file
  • Make sure the module is added to a feature in your project that is scoped at the site (= site collection) level
You could stop here and this solution will deploy your sample.master master page to the master page gallery of your site collection.
This will not apply the master page to the site collection when the feature gets activated though. It will only make it available for selection.
  • If you the master page to be applied when the feature gets activated you right click on the Feature1 and you add an event receiver. This will add a feature receiver file to the feature.
  • In this file we will add some code that will apply the sample.master master page when the feature gets activated and it will apply the v4.master when the feature gets deactivated.

[Update 10/12/2010]: Code updated because of improperly disposed SPSite and SPWeb objects. Thanks Donald Hessing and Rhys for pointing it out.

featurereceiver2 
Code used in the feature receiver
Now if you activate the feature the code in the feature receiver will run and will apply sample.master to the site. As you can see we change both the MasterUrl and the CustomMasterUrl. The MasterUrl is used on all pages that are not publishing pages. This means it is used on the pages in the sitepages library and on the pages in the _layouts directory like the settings page for instance. The CustomMasterUrl is only used on pages that are stored in the Pages library. This library is created when the SharePoint Server Publishing Infrastructure features is activated on the site collection and the SharePoint Server Publishing feature is activated on the site.
You can also use the SharePoint user interface to apply a new master page. The Site Master Page is the equivalent of the CustomMasterUrl and the System Master Page is what the object model calls the MasterUrl.
Changing the master page using the SharePoint UI
Changing the master page using the SharePoint user interface

How to embed the “Connect to Outlook” link in a page

I need to put a link to the "Connect to Outlook" script on a SharePoint 2010 page. I have built the stssync:// URL that triggers the Outlook sync: stssync://sts/?ver=1.1&type=discussions&cmd=add-folder&base-url=[MyServer]&list-url=[MyList]&guid=[MyGUID]&site-name=[MySiteName]&list-name=[MyListName]
Now the link works fine when pasted in IE address bar. However, I can't add it to a Sharepoint page - if I try to use the "insert hyperlink" button Sharepoint will complain about the stssynch:// protocol "URL must be in the form of http://" (or something to that effect).
I have tried to add a regular link that change the URL by editing the page's HTML. However, Sharepoint removes the link on saving the page.
How can I add the stssync:// link to a page? Is there any simple way to somehow "wrap" it in http or something?

Answer :


You can add the following code to a Content Editor webpart or directly onto the page. After adding the CEWP, in the ribbon use Editing Tools > Format Text > Edit HTML source.

 Code:
<script src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script language="javascript" type="text/javascript">
  function replaceURL() {
    $('#outlookLink').attr('href','stssync://sts/?ver=1.1&type=discussions&cmd=add-folder&base-url=[MyServer]&list-url=[MyList]&guid=[MyGUID]&site-name=[MySiteName]&list-name=[MyListName]');
  }

  _spBodyOnLoadFunctionNames.push("replaceURL");
</script>
<a id="outlookLink" href="#">Link to Outlook</a>
 
 
Here's what it is doing:
  1. Includes a reference to the jQuery library, which you can either do as in this example or you can download it to your site and include a reference to that location on your site instead.
  2. replaceURL() uses the jQuery .attr() method to change the href attribute of the anchor tag with the url that you want.
  3. _spBodyOnLoadFunctionNames.push() will call your function as soon as the page loads.
  4. Your link should have an id which you refer to in your function. The href can be anything, since it gets modified by your function as soon as the page loads.
NOTE: You could use straight javascript instead of jQuery, but the syntax is more complicated.