XmlNode return_node = listService.UpdateListItems(ListName, batchElement);
var id= return_node.SelectSingleNode("//@ows_ID").Value;
string srcUrl = "E:\\ASLog.txt";
FileStream fStream = File.OpenRead(srcUrl);
string fileName = fStream.Name.Substring(3);
byte[] contents = new byte[fStream.Length];
fStream.Read(contents, 0, (int)fStream.Length);
fStream.Close();
listService.AddAttachment(ListName, id, fileName, contents);
Tuesday, November 9, 2010
Monday, September 27, 2010
SharePoint Jokes.
Light travels faster than sound. This is why some SharePoint consultants appear bright until you hear them speak.
A good SharePoint consultant is someone who can tell you to go to hell in such a way that you look forward to the trip.
SharePoint work is something you do that nobody notices until you don't do it.
I should've known it wasn't going to work out between my ex-girlfriend and me. After all, I'm a SharePoint and she's a Documentum.
Kerberos with SharePoint is sort of like a bird, it's pretty cute until it shits on your head.
The secret to success as a SharePoint consultant is knowing who to blame for your failures.
SharePoint Consultant to client - 'We don't have a SharePoint performance problem; You have a perception problem.'
SharePoint analyst to programmer: "You start coding. I'll go find out what they want."
The first half of my life was ruined by my parents, and the second half by SharePoint.
TIP: If you are a SharePoint admin and you think nobody cares if you're alive, try missing a couple of SharePoint service packs.
I want to die peacefully in my sleep, like my grandfather.. Not screaming and yelling like SharePoint end users.
I like SharePoint, It fascinates me. I sit and look at it for hours.
What did one sharepoint site say to another sharepoint site?
Hey, aren't we called webs?
What did the end user say to the developer?
Oh, I didn't create that column, I was smart, I just renamed the "title" column!
What did one sharepoint web developer say to the asp.net developer?
Why me?
What did the production portal say to the author portal?
I'm sorry, I can't seem to find your object!
What did the parent content type say to the child content type?
I won't give you my jeans, but I'll buy you another pair just like them and we can share!
How many people does it take to create a web part?
two, one to write the code, another to figure out the permissions problem in production!
How many times does it take to create a Shared Service Provider?
3, one time to screw it up without knowing it, twice to do it because sharepoint won't do right the second time and
the third after you have blown away everything and started over!
What did the server admin say to the sharepoint web developer?
Why can't we just do this with static html?
what did the sharepoint 2003 environment tell the sharepoint 2007 environment?
Don't worry, reboot will still fix everything.
What did the sharepoint admin do to fix an "Unexpected Error has occured"
Delete sharepoint and start again!
What did one w3wp process say to the other?
Hey, can I borrow one of your SPSite's? You have plenty!
One day a user called the helpdesk, no one answered. Being that he was in the helpdesk office he walked down and asked the admin why they weren't answering.
She simply stated, they quit when they heard we were implementing sharepoint!
A consultant was asked to build an estimate for a SharePoint two layer approval workflow with SharePoint Designer.
The consultant never replied. When asked "why", he simply stated, "Impossible".
A good SharePoint consultant is someone who can tell you to go to hell in such a way that you look forward to the trip.
SharePoint work is something you do that nobody notices until you don't do it.
I should've known it wasn't going to work out between my ex-girlfriend and me. After all, I'm a SharePoint and she's a Documentum.
Kerberos with SharePoint is sort of like a bird, it's pretty cute until it shits on your head.
The secret to success as a SharePoint consultant is knowing who to blame for your failures.
SharePoint Consultant to client - 'We don't have a SharePoint performance problem; You have a perception problem.'
SharePoint analyst to programmer: "You start coding. I'll go find out what they want."
The first half of my life was ruined by my parents, and the second half by SharePoint.
TIP: If you are a SharePoint admin and you think nobody cares if you're alive, try missing a couple of SharePoint service packs.
I want to die peacefully in my sleep, like my grandfather.. Not screaming and yelling like SharePoint end users.
I like SharePoint, It fascinates me. I sit and look at it for hours.
What did one sharepoint site say to another sharepoint site?
Hey, aren't we called webs?
What did the end user say to the developer?
Oh, I didn't create that column, I was smart, I just renamed the "title" column!
What did one sharepoint web developer say to the asp.net developer?
Why me?
What did the production portal say to the author portal?
I'm sorry, I can't seem to find your object!
What did the parent content type say to the child content type?
I won't give you my jeans, but I'll buy you another pair just like them and we can share!
How many people does it take to create a web part?
two, one to write the code, another to figure out the permissions problem in production!
How many times does it take to create a Shared Service Provider?
3, one time to screw it up without knowing it, twice to do it because sharepoint won't do right the second time and
the third after you have blown away everything and started over!
What did the server admin say to the sharepoint web developer?
Why can't we just do this with static html?
what did the sharepoint 2003 environment tell the sharepoint 2007 environment?
Don't worry, reboot will still fix everything.
What did the sharepoint admin do to fix an "Unexpected Error has occured"
Delete sharepoint and start again!
What did one w3wp process say to the other?
Hey, can I borrow one of your SPSite's? You have plenty!
One day a user called the helpdesk, no one answered. Being that he was in the helpdesk office he walked down and asked the admin why they weren't answering.
She simply stated, they quit when they heard we were implementing sharepoint!
A consultant was asked to build an estimate for a SharePoint two layer approval workflow with SharePoint Designer.
The consultant never replied. When asked "why", he simply stated, "Impossible".
Updating the data from XML to Sharepoint List
With the use of Sharepoint List Webservice i am going to populate the xml data into the list. for this you need to create a list and also the columns. with nodes in the XML.
In this i m a going to hard the Webservice Url, but you can add the app.config and can adda new key and value . which it reference in the code using Cofiguration Settings.by inheriting the System.Configuration.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Net;
using System.IO;
namespace XMLtoSPList
{
class Program
{
static void Main(string[] args)
{
try
{
ReferenceToWebService.Lists ListsService = new ReferenceToWebService.Lists();
ListsService.Credentials = new NetworkCredential("XXXX", "YYYYYY", "ZZZZZZ");
//ListsService.Credentials = System.Net.CredentialCache.DefaultCredentials;
string _listservURL = string.Empty;
Console.WriteLine("Enter the SiteCollection Url :", _listservURL);
_listservURL = Console.ReadLine();
ListsService.Url = "http://servername/_vti_bin/lists.asmx";
//ListsService.Url = "http://myserver:6580/Docs/_vti_bin/lists.asmx";
XmlTextReader textReader = new XmlTextReader("C:\\myxml.XML");
textReader.Read();
XmlDocument doc = new XmlDocument();
XmlElement batch = doc.CreateElement("Batch");
batch.SetAttribute("OnError", "Continue");
batch.SetAttribute("ListVersion", "1");
XmlDocument doc1 = new XmlDocument();
doc1.Load("C:\\Duplicate Vendor Additions.XML");
int i = 1;
try
{
ListsService.GetList("RECORDS");
System.Xml.XmlNode ndListView = ListsService.GetListAndView("RECORDS", "");
XmlNode node1 = ndListView.ChildNodes[1];
XmlNode node2 = node1.ChildNodes[1];
XmlNodeList node3 = node2.ChildNodes;
int count = 0;
string strListID = ndListView.ChildNodes[0].Attributes["Name"].Value;
foreach (XmlNode nd in doc1.DocumentElement.SelectNodes("RECORD"))
{
try
{
string Duplicates = nd.ChildNodes[0].InnerText;
batch.InnerXml = "" +
"" + i.ToString() + " " +
"" + nd.ChildNodes[0].InnerText.Trim() + " " +
"" + nd.ChildNodes[1].InnerText.Trim() + " " +
"" + nd.ChildNodes[2].InnerText.Trim() + " " +
"" + nd.ChildNodes[3].InnerText.Trim() + " " +
"" + nd.ChildNodes[4].InnerText.Trim() + " " +
"" + nd.ChildNodes[5].InnerText.Trim() + " " +
"" + nd.ChildNodes[6].InnerText.Trim() + " " +
"";
}
catch (Exception ex)
{
Trace(DateTime.Now.ToString() + " A record with " );
Trace(nd.InnerXml);
Trace("is not inserted.");
}
//ListsService.UpdateListItems(strListID, batch);
Console.WriteLine(nd.ChildNodes[0].InnerText);
i++;
}
}
catch(Exception ex)
{
Trace(DateTime.Now.ToString()+"---No List Found.");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.WriteLine("Done");
string exit = string.Empty;
Console.WriteLine("Press X to exit"+exit);
if (exit == "x")
{
exit = "exit";
exit = Console.ReadLine();
}
Console.Read();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.Net;
using System.IO;
namespace XMLtoSPList
{
class Program
{
static void Main(string[] args)
{
try
{
ReferenceToWebService.Lists ListsService = new ReferenceToWebService.Lists();
ListsService.Credentials = new NetworkCredential("XXXX", "YYYYYY", "ZZZZZZ");
//ListsService.Credentials = System.Net.CredentialCache.DefaultCredentials;
string _listservURL = string.Empty;
Console.WriteLine("Enter the SiteCollection Url :", _listservURL);
_listservURL = Console.ReadLine();
ListsService.Url = "http://servername/_vti_bin/lists.asmx";
//ListsService.Url = "http://myserver:6580/Docs/_vti_bin/lists.asmx";
XmlTextReader textReader = new XmlTextReader("C:\\myxml.XML");
textReader.Read();
XmlDocument doc = new XmlDocument();
XmlElement batch = doc.CreateElement("Batch");
batch.SetAttribute("OnError", "Continue");
batch.SetAttribute("ListVersion", "1");
XmlDocument doc1 = new XmlDocument();
doc1.Load("C:\\Duplicate Vendor Additions.XML");
int i = 1;
try
{
ListsService.GetList("RECORDS");
System.Xml.XmlNode ndListView = ListsService.GetListAndView("RECORDS", "");
XmlNode node1 = ndListView.ChildNodes[1];
XmlNode node2 = node1.ChildNodes[1];
XmlNodeList node3 = node2.ChildNodes;
int count = 0;
string strListID = ndListView.ChildNodes[0].Attributes["Name"].Value;
foreach (XmlNode nd in doc1.DocumentElement.SelectNodes("RECORD"))
{
try
{
string Duplicates = nd.ChildNodes[0].InnerText;
batch.InnerXml = "
"
"
"
"
"
"
"
"
"";
}
catch (Exception ex)
{
Trace(DateTime.Now.ToString() + " A record with " );
Trace(nd.InnerXml);
Trace("is not inserted.");
}
//ListsService.UpdateListItems(strListID, batch);
Console.WriteLine(nd.ChildNodes[0].InnerText);
i++;
}
}
catch(Exception ex)
{
Trace(DateTime.Now.ToString()+"---No List Found.");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Console.WriteLine(ex.StackTrace);
}
Console.WriteLine("Done");
string exit = string.Empty;
Console.WriteLine("Press X to exit"+exit);
if (exit == "x")
{
exit = "exit";
exit = Console.ReadLine();
}
Console.Read();
}
}
}
Hiding Sharepoint Controls in the List
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
public partial class hellol : System.Web.UI.UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected override void CreateChildControls()
{
foreach (Control ctrl in this.Page.Controls)
{
CheckControl(ctrl);
}
base.CreateChildControls();
}
private void CheckControl(Control ParentControl)
{
try
{
foreach (Control childControl in ParentControl.Controls)
{
if (childControl.ToString().ToUpper() == "Microsoft.SharePoint.WebControls.ActionsMenu".ToUpper())
{
ActionsMenu Menu = (ActionsMenu)childControl;
Menu.Visible = false;
break;
}
CheckControl(childControl);
}
foreach (Control childControl in ParentControl.Controls)
{
if (childControl.ToString().ToUpper() == "Microsoft.SharePoint.WebControls.SettingsMenu".ToUpper())
{
SettingsMenu Menu = (SettingsMenu)childControl;
Menu.Visible = false;
}
if (childControl.ToString().ToUpper() == "Microsoft.SharePoint.WebControls.NewMenu".ToUpper())
{
NewMenu Menu = (NewMenu)childControl;
Menu.Visible = false;
}
CheckControl(childControl);
}
}
catch { }
}
}
Working with BDC picker Control in SharePoint Programatically
By this you can use the customized BDC picker entity. by developing the BDC picker control. The event Load will fetch the data and also connect to the instance which is ther ein the Respetive Shared service related to the current webapplication.
BDCEntityPickerID = new Microsoft.SharePoint.Portal.WebControls.ItemPicker();
BDCEntityPickerID.ID = "BDCEntityPickerID";
BDCEntityPickerID.AllowTypeIn = true;
BDCEntityPickerID.AllowEmpty = false;
BDCEntityPickerID.AutoPostBack = true;
BDCEntityPickerID.MultiSelect = false;
BDCEntityPickerID.Load += new EventHandler(BDCEntityPickerID_Load);
Controls.Add(BDCEntityPickerID);
protected void BDCEntityPickerID_Load(object sender, EventArgs e)
{
// Set extended data
BDCEntityPickerID.ExtendedData = GetExtendedData("MyInstance", "Tablename", "ColumnName_picker");
// Set other properties
}
protected Portal.ItemPickerExtendedData GetExtendedData(string lobInstanceName, string entityName, string titleFieldName)
{
// Create a new ExtendedData object
Portal.ItemPickerExtendedData data = new Portal.ItemPickerExtendedData();
// Get the LOB Instance
LobSystemInstance lob = ApplicationRegistry.GetLobSystemInstanceByName(lobInstanceName);
data.SystemInstanceId = lob.Id;
// Get the entity
Entity entity = lob.GetEntities()[entityName];
data.EntityId = entity.Id;
// Set the primary column id (the id of the "Title" field)
FieldCollection fields = entity.GetSpecificFinderView().Fields;
List secondaryColumnIds = new List();
foreach (Field field in fields)
{
if (string.Equals(field.Name, titleFieldName, StringComparison.OrdinalIgnoreCase))
{
data.PrimaryColumnId = field.TypeDescriptor.Id;
}
else
{
secondaryColumnIds.Add(field.TypeDescriptor.Id);
}
}
data.SecondaryColumnsIds = secondaryColumnIds.ToArray();
return data;
}
BDCEntityPickerID = new Microsoft.SharePoint.Portal.WebControls.ItemPicker();
BDCEntityPickerID.ID = "BDCEntityPickerID";
BDCEntityPickerID.AllowTypeIn = true;
BDCEntityPickerID.AllowEmpty = false;
BDCEntityPickerID.AutoPostBack = true;
BDCEntityPickerID.MultiSelect = false;
BDCEntityPickerID.Load += new EventHandler(BDCEntityPickerID_Load);
Controls.Add(BDCEntityPickerID);
protected void BDCEntityPickerID_Load(object sender, EventArgs e)
{
// Set extended data
BDCEntityPickerID.ExtendedData = GetExtendedData("MyInstance", "Tablename", "ColumnName_picker");
// Set other properties
}
protected Portal.ItemPickerExtendedData GetExtendedData(string lobInstanceName, string entityName, string titleFieldName)
{
// Create a new ExtendedData object
Portal.ItemPickerExtendedData data = new Portal.ItemPickerExtendedData();
// Get the LOB Instance
LobSystemInstance lob = ApplicationRegistry.GetLobSystemInstanceByName(lobInstanceName);
data.SystemInstanceId = lob.Id;
// Get the entity
Entity entity = lob.GetEntities()[entityName];
data.EntityId = entity.Id;
// Set the primary column id (the id of the "Title" field)
FieldCollection fields = entity.GetSpecificFinderView().Fields;
List
foreach (Field field in fields)
{
if (string.Equals(field.Name, titleFieldName, StringComparison.OrdinalIgnoreCase))
{
data.PrimaryColumnId = field.TypeDescriptor.Id;
}
else
{
secondaryColumnIds.Add(field.TypeDescriptor.Id);
}
}
data.SecondaryColumnsIds = secondaryColumnIds.ToArray();
return data;
}
Tuesday, May 18, 2010
Creating Custom Field Control
In this example we are creating a custom field type which concatenates two text fields (first and last name).
Create a new usercontrol file (customfieldcontrol.ascx). In this usercontrol, add a SharePoint:RenderingTemplate control, and insert whatever you want for your control template.
Secondly, create a new class file (customfieldcontrol.cs), which will take the role of codebehind file of the usercontrol. In this class, which will inherit from Microsoft.SharePoint.WebControls.BaseFieldControl, we will override some of the properties and methods to implement our own logic.
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
namespace CustomControl
{
public class customfieldcontrol : BaseFieldControl
{
protected TextBox txtFirstName;
protected TextBox txtLastName;
protected override string DefaultTemplateName
{
get { return "CustomFieldRendering"; }
}
public override object Value
{
get
{
EnsureChildControls();
return txtFirstName.Text + "%" + txtLastName.Text;
}
set
{
try
{
EnsureChildControls();
txtFirstName.Text = value.ToString().Split('%')[0];
txtLastName.Text = value.ToString().Split('%')[1];
}
catch { }
}
}
public override void Focus()
{
EnsureChildControls();
txtFirstName.Focus();
}
protected override void CreateChildControls()
{
if (Field == null) return;
base.CreateChildControls();
//Don't render the textbox if we are just displaying the field
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.Display) return;
txtFirstName = (TextBox)TemplateContainer.FindControl("txtFirstName");
txtLastName = (TextBox)TemplateContainer.FindControl("txtLastName");
if (txtFirstName == null) throw new NullReferenceException("txtFirstName is null");
if (txtLastName == null) throw new NullReferenceException("txtLastName is null");
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.New)
{
txtFirstName.Text = "";
txtLastName.Text = "";
}
}
}
}Actually, what this code does is:Define the ID of the renderingtemplate control in our usercontrol.Set the return value to the value we want it to return :), in this case this will be something like Firstname%Lastname.Make sure that when you edit an item, the proper values are filled in into the textboxes again.
Next thing to do is to create the Field type class (CustomField.cs) itself. In this class, which derives of one of the base control types from SharePoint (SPFieldText, SPFieldChoice, ...), we will define which control has to be used as template, and which value has to be returned when displaying a list item.
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
namespace CustomControl
{
public class CustomField : SPFieldText
{
public CustomField(SPFieldCollection fields, string fieldName)
: base(fields, fieldName)
{ }
public CustomField(SPFieldCollection fields, string typeName, string displayName)
: base(fields, typeName, displayName)
{ }
public override BaseFieldControl FieldRenderingControl
{
get
{
BaseFieldControl fieldControl = new customfieldcontrol();
fieldControl.FieldName = this.InternalName;
return fieldControl;
}
}
public override string GetValidatedString(object value)
{
return value.ToString().Split('%')[1].ToUpper() + " " + value.ToString().Split('%')[0];
}
}
}Main thing of this code is the GetValidatedString() function. This function defines what is to be displayed when you display an item (in a list view for example).In our case, which in our case will be something like LASTNAME Firstname.
Last file to create is the XML File (fldtypes_custom.xml), which will add the custom field type to SharePoint.
CustomField
Text
Custom Name Field
Custom Name Text Field
TRUE
TRUE
TRUE
TRUE
TRUE
TRUE
TRUE
CustomControl.CustomField, CustomControl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx
nvarchar
So far so good with creating the files :) Now, all we have to do is put the right files in the right places ...Compile your project (or at least both .cs classes) and make sure they are strong named.Then, install them in the GAC (%windir%\assembly)Next, copy the .ascx file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\CONTROLTEMPLATESAnd the last file to copy: copy the .xml file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\XML
That's it. Maybe do an IISRESET, and you can use your newly created Custom Field Type!
As taken from Nick's SharePoint Blog. Another good practical example is:
http://www.kcdholdings.com/blog/?p=56
Create a new usercontrol file (customfieldcontrol.ascx). In this usercontrol, add a SharePoint:RenderingTemplate control, and insert whatever you want for your control template.
Secondly, create a new class file (customfieldcontrol.cs), which will take the role of codebehind file of the usercontrol. In this class, which will inherit from Microsoft.SharePoint.WebControls.BaseFieldControl, we will override some of the properties and methods to implement our own logic.
using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
namespace CustomControl
{
public class customfieldcontrol : BaseFieldControl
{
protected TextBox txtFirstName;
protected TextBox txtLastName;
protected override string DefaultTemplateName
{
get { return "CustomFieldRendering"; }
}
public override object Value
{
get
{
EnsureChildControls();
return txtFirstName.Text + "%" + txtLastName.Text;
}
set
{
try
{
EnsureChildControls();
txtFirstName.Text = value.ToString().Split('%')[0];
txtLastName.Text = value.ToString().Split('%')[1];
}
catch { }
}
}
public override void Focus()
{
EnsureChildControls();
txtFirstName.Focus();
}
protected override void CreateChildControls()
{
if (Field == null) return;
base.CreateChildControls();
//Don't render the textbox if we are just displaying the field
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.Display) return;
txtFirstName = (TextBox)TemplateContainer.FindControl("txtFirstName");
txtLastName = (TextBox)TemplateContainer.FindControl("txtLastName");
if (txtFirstName == null) throw new NullReferenceException("txtFirstName is null");
if (txtLastName == null) throw new NullReferenceException("txtLastName is null");
if (ControlMode == Microsoft.SharePoint.WebControls.SPControlMode.New)
{
txtFirstName.Text = "";
txtLastName.Text = "";
}
}
}
}Actually, what this code does is:Define the ID of the renderingtemplate control in our usercontrol.Set the return value to the value we want it to return :), in this case this will be something like Firstname%Lastname.Make sure that when you edit an item, the proper values are filled in into the textboxes again.
Next thing to do is to create the Field type class (CustomField.cs) itself. In this class, which derives of one of the base control types from SharePoint (SPFieldText, SPFieldChoice, ...), we will define which control has to be used as template, and which value has to be returned when displaying a list item.
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
namespace CustomControl
{
public class CustomField : SPFieldText
{
public CustomField(SPFieldCollection fields, string fieldName)
: base(fields, fieldName)
{ }
public CustomField(SPFieldCollection fields, string typeName, string displayName)
: base(fields, typeName, displayName)
{ }
public override BaseFieldControl FieldRenderingControl
{
get
{
BaseFieldControl fieldControl = new customfieldcontrol();
fieldControl.FieldName = this.InternalName;
return fieldControl;
}
}
public override string GetValidatedString(object value)
{
return value.ToString().Split('%')[1].ToUpper() + " " + value.ToString().Split('%')[0];
}
}
}Main thing of this code is the GetValidatedString() function. This function defines what is to be displayed when you display an item (in a list view for example).In our case, which in our case will be something like LASTNAME Firstname.
Last file to create is the XML File (fldtypes_custom.xml), which will add the custom field type to SharePoint.
CustomField
Text
Custom Name Field
Custom Name Text Field
TRUE
TRUE
TRUE
TRUE
TRUE
TRUE
TRUE
CustomControl.CustomField, CustomControl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=xxxxxxxxxxxxxxxx
nvarchar
So far so good with creating the files :) Now, all we have to do is put the right files in the right places ...Compile your project (or at least both .cs classes) and make sure they are strong named.Then, install them in the GAC (%windir%\assembly)Next, copy the .ascx file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\CONTROLTEMPLATESAnd the last file to copy: copy the .xml file to C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\TEMPLATE\XML
That's it. Maybe do an IISRESET, and you can use your newly created Custom Field Type!
As taken from Nick's SharePoint Blog. Another good practical example is:
http://www.kcdholdings.com/blog/?p=56
Feature Stapling Part-2
VIEW COMMENTS
Welcome to part 2 of my Introduction to SharePoint Feature Stapling. In part 1 I explained the process of creating a feature stapler and associating it with a site definition. In this small post, I’ll be providing some insight into the feature stapling lifecycle and also providing some potential solutions to some of the downsides of the feature stapling process.
Feature Stapling Lifecycle
The actual lifecycle of the feature stapling process is not documented actually documented anywhere. The following information has been solely gathered based on my testing and experimenting with the process.
If we step back and look at a site definition file we know that the GLOBAL#0 site template is applied to all site definitions. Many of the Microsoft provided site definitions enable functionality through the use of the feature system. If you open up the STS site definition ONET.XML file, you will see two sections near the bottom called SiteFeatures and WebFeatures:
You will notice that in many of the Windows SharePoint Services site definition files the ListTemplates section is not populated with anything; they use list definition features instead. As you can see, the Team Site site definition points to a feature called TeamCollab. This feature makes list definitions available to the web that is being created.
So what does this all mean when it comes to feature association? The important thing to remember here is that any feature receivers you develop and associate to a site definition will get executed before any of the lists on that site have been provisioned. However, anything provisioned via the Global Site Definition will be available to your feature receiver.
This is not a problem if you simply want to create new lists, libraries, etc. However, if you are attempting to manipulate any lists that are part of the site definition you are associating with you will find yourself looking at a System.ArgumentException stating “Value does not fall within the expected ranged.”
The following image shows what happens when I create a Team Site that has my custom feature receiver associated to it:
Solution
We have already determined that feature receivers make it extremely easy for a developer to extend and customize out of the box site definitions without touching the files. But we run into a road block when we attempt to customize the lists and libraries that are part of that site definition.
One way I have used to get around this is to simply delay the customizations until after the site has completely provisioned.
The following is an example using the ThreadPool.QueueUserWorkItem method:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb web = (SPWeb)properties.Feature.Parent)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(RunProcess), web.Url);
}
}
private void RunProcess(object state)
{
Thread.Sleep(5000);
string url = (string)state;
using (SPSite site = new SPSite(url))
{
using (SPWeb web = site.OpenWeb())
{
// at this point, the site should be provisioned
// and we will now have access to all lists on it
SPList list = web.Lists["Shared Documents"];
list.Description = "Updated from Feature Receiver";
list.Update();
}
}
}
Why are we running on a different thread? Well, this allows the site provisioning process to complete and then we come back in a few seconds later to customize it as needed. Of course, the sample above is not 100% perfect. What happens if it takes 10 seconds to provision a site – well the method above would fail out.
A more elegant way would probably be to check the SPWeb.Provisioned property which is False until after the provisioning process has completed; but you get the general idea.
Summary
Hopefully this two part series has given you the necessary information needed to get started using SharePoint Feature Stapling and what potential issues to watch out for. There is many resources out on the Internet that cover other aspects of Feature Stapling, but I’ll list a few here for your reference:
MSDN: Feature Stapling
MSDN: Feature Event Receiver
http://blogs.msdn.com/cjohnson/archive/2006/11/01/feature-stapling-in-wss-v3.aspx
http://www.sharepointnutsandbolts.com/2007/05/feature-stapling.html
Welcome to part 2 of my Introduction to SharePoint Feature Stapling. In part 1 I explained the process of creating a feature stapler and associating it with a site definition. In this small post, I’ll be providing some insight into the feature stapling lifecycle and also providing some potential solutions to some of the downsides of the feature stapling process.
Feature Stapling Lifecycle
The actual lifecycle of the feature stapling process is not documented actually documented anywhere. The following information has been solely gathered based on my testing and experimenting with the process.
If we step back and look at a site definition file we know that the GLOBAL#0 site template is applied to all site definitions. Many of the Microsoft provided site definitions enable functionality through the use of the feature system. If you open up the STS site definition ONET.XML file, you will see two sections near the bottom called SiteFeatures and WebFeatures:
You will notice that in many of the Windows SharePoint Services site definition files the ListTemplates section is not populated with anything; they use list definition features instead. As you can see, the Team Site site definition points to a feature called TeamCollab. This feature makes list definitions available to the web that is being created.
So what does this all mean when it comes to feature association? The important thing to remember here is that any feature receivers you develop and associate to a site definition will get executed before any of the lists on that site have been provisioned. However, anything provisioned via the Global Site Definition will be available to your feature receiver.
This is not a problem if you simply want to create new lists, libraries, etc. However, if you are attempting to manipulate any lists that are part of the site definition you are associating with you will find yourself looking at a System.ArgumentException stating “Value does not fall within the expected ranged.”
The following image shows what happens when I create a Team Site that has my custom feature receiver associated to it:
Solution
We have already determined that feature receivers make it extremely easy for a developer to extend and customize out of the box site definitions without touching the files. But we run into a road block when we attempt to customize the lists and libraries that are part of that site definition.
One way I have used to get around this is to simply delay the customizations until after the site has completely provisioned.
The following is an example using the ThreadPool.QueueUserWorkItem method:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb web = (SPWeb)properties.Feature.Parent)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(RunProcess), web.Url);
}
}
private void RunProcess(object state)
{
Thread.Sleep(5000);
string url = (string)state;
using (SPSite site = new SPSite(url))
{
using (SPWeb web = site.OpenWeb())
{
// at this point, the site should be provisioned
// and we will now have access to all lists on it
SPList list = web.Lists["Shared Documents"];
list.Description = "Updated from Feature Receiver";
list.Update();
}
}
}
Why are we running on a different thread? Well, this allows the site provisioning process to complete and then we come back in a few seconds later to customize it as needed. Of course, the sample above is not 100% perfect. What happens if it takes 10 seconds to provision a site – well the method above would fail out.
A more elegant way would probably be to check the SPWeb.Provisioned property which is False until after the provisioning process has completed; but you get the general idea.
Summary
Hopefully this two part series has given you the necessary information needed to get started using SharePoint Feature Stapling and what potential issues to watch out for. There is many resources out on the Internet that cover other aspects of Feature Stapling, but I’ll list a few here for your reference:
MSDN: Feature Stapling
MSDN: Feature Event Receiver
http://blogs.msdn.com/cjohnson/archive/2006/11/01/feature-stapling-in-wss-v3.aspx
http://www.sharepointnutsandbolts.com/2007/05/feature-stapling.html
Subscribe to:
Posts (Atom)