Professional Documents
Culture Documents
Event Handlers – C#
Event Handlers – C#
Table of Contents
Event Handlers – C# ..................................................................................................................... 1
Exercise 1 Asynchronous Event Handler ......................................................................................................................2
Exercise 2 Validation Event Handler........................................................................................................................... 14
Exercise 3 Feature Receiver ........................................................................................................................................ 21
Event Handlers – C#
Event Handlers – C#
Objectives After completing this lab, you will be better able to:
Create a custom Content Type and use it in a custom list
Write a code to process both asynchronous and synchronous Item events
Write a code to execute when you activate a Feature
Page 1 of 24
Event Handlers – C#
Exercise 1
Asynchronous Event Handler
Scenario
In this exercise, you will create an asynchronous event handler that executes when you add an item to a list. After
you add a new item to a list, your code will create a record in a SQL Server 2008 database that you will create. In
this scenario, you will use a custom list to track packages for shipping.
Page 2 of 24
Event Handlers – C#
Tasks Detailed Steps
k. In the Content Type Settings dialog that appears after clicking Add, change the
Base Content Type to Item.
l. Place a check next to the Add with Event Receiver and click OK. Visual Studio
adds three new files, two code files and one XML file, under a folder called
ShippingType.
Page 3 of 24
Event Handlers – C#
Tasks Detailed Steps
o. Replace the existing FieldRef commented block between the opening and closing
FieldRefs element tags with the following XML:
<FieldRef ID="{48B36503-65D4-4f0c-B73C-AB328217A34B}"
Name="ShipID" />
<FieldRef ID="{46dc1532-6304-4a1b-8d8e-eb124e35cae8}"
Name="ShipTo" />
<FieldRef ID="{12F81C62-EEDF-4b2d-B485-EAD0701E1C5E}"
Name="ShipStreet" />
<FieldRef ID="{93639B35-6338-4f18-B1D8-EC7AE0244C3A}"
Name="ShipCity" />
<FieldRef ID="{EBA1A352-E9B1-436f-8749-12816266921F}"
Name="ShipState" />
<FieldRef ID="{D01366B6-04A0-4ca4-B0E2-59E557BF685B}"
Name="ShipPostalCode" />
<FieldRef ID="{E316F9E6-1B25-4a03-898B-FF7BC9812F51}"
Name="ShipTracking" />
p. Next, replace the existing commented Field block with the following XML:
<Field ID="{48B36503-65D4-4f0c-B73C-AB328217A34B}"
Type="Text"
Name="ShipID"
DisplayName="Ship ID"
StaticName="ShipID"
Hidden="FALSE" Required="TRUE"
Sealed="FALSE" />
<Field ID="{46dc1532-6304-4a1b-8d8e-eb124e35cae8}"
Type="Text"
Page 4 of 24
Event Handlers – C#
Tasks Detailed Steps
Name="ShipTo"
DisplayName="Ship To"
StaticName="ShipTo"
Hidden="FALSE" Required="TRUE"
Sealed="FALSE" />
<Field ID="{12F81C62-EEDF-4b2d-B485-EAD0701E1C5E}"
Type="Text"
Name="ShipStreet"
DisplayName="Street"
StaticName="ShipStreet"
Hidden="FALSE" Required="TRUE"
Sealed="FALSE" />
<Field ID="{93639B35-6338-4f18-B1D8-EC7AE0244C3A}"
Type="Text"
Name="ShipCity"
DisplayName="City"
StaticName="ShipCity"
Hidden="FALSE" Required="TRUE"
Sealed="FALSE" />
<Field ID="{EBA1A352-E9B1-436f-8749-12816266921F}"
Type="Text"
Name="ShipState"
DisplayName="State"
StaticName="ShipState"
Hidden="FALSE" Required="TRUE"
Sealed="FALSE" />
<Field ID="{D01366B6-04A0-4ca4-B0E2-59E557BF685B}"
Type="Text"
Name="ShipPostalCode"
DisplayName="Postal Code"
StaticName="ShipPostalCode"
Hidden="FALSE" Required="TRUE"
Sealed="FALSE" />
<Field ID="{E316F9E6-1B25-4a03-898B-FF7BC9812F51}"
Type="Choice"
Name="ShipTracking"
DisplayName="Tracking"
StaticName="ShipTracking"
Hidden="FALSE" Required="TRUE"
Sealed="FALSE">
<CHOICES>
<CHOICE>Delivered</CHOICE>
<CHOICE>In-transit</CHOICE>
<CHOICE>Shipped</CHOICE>
<CHOICE>Waiting for Payment</CHOICE>
</CHOICES>
Page 5 of 24
Event Handlers – C#
Tasks Detailed Steps
</Field>
q. Select File | Save ShippingType\ShippingType.xml to save your work.
r. Select File | Close to close the ShippingType.xml file
s. In the Solution Explorer, right-click on the Shipping project and select Add
Reference.
t. In the Add Reference dialog, under the .NET tab, scroll down and select
System.Data and click OK.
u. In the Solution Explorer, right-click on the ItemEventReceiver.cs file under the
ShippingType folder and select Open.
v. At the top of the source file, under existing using statements, add the following
code:
using System.Data;
using System.Data.SqlClient;
w. Scroll down in the source file until you find the following block of commented
code:
//public override void ItemAdded(SPItemEventProperties
properties)
//{
//}
x. Uncomment the code and add the following code as the method body:
const string connectionString =
"Server=localhost;Database=Packages;Trusted_Connection=Tru
e";
const string baseSQL = "INSERT INTO Tracking " +
"(PackageID, PackageTitle, PackageStatus) VALUES" +
"(@PackageID, @PackageTitle, @PackageStatus);";
try
{
// Retrieve data from properties
string packageID =
properties.ListItem["ShipID"].ToString();
string packageTitle =
properties.ListItem.Title;
string packageStatus =
properties.ListItem["ShipTracking"].ToString();
Page 6 of 24
Event Handlers – C#
Tasks Detailed Steps
cmd.Parameters.Add(prm);
prm = new SqlParameter("@PackageTitle",
SqlDbType.NVarChar);
prm.Direction = ParameterDirection.Input;
prm.Value = packageTitle;
cmd.Parameters.Add(prm);
prm = new SqlParameter("@PackageStatus",
SqlDbType.NVarChar);
prm.Direction = ParameterDirection.Input;
prm.Value = packageStatus;
cmd.Parameters.Add(prm);
con.Open();
int retVal = cmd.ExecuteNonQuery();
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Note: The code you just added is mostly standard ADO.NET code that uses connection
and command objects to add a new record to the database. At the beginning of the
procedure, it accesses the passed in SPItemEventProperties object to read column
data related to the new item added to the list. Title is a standard, built-in field so you
can access it directly as a property of the ListItem. However, the other two properties
are custom, hence the different syntax. The code stores the data in local variables and
then passes it to the command object via SqlParameters. You’ll note that the code uses
SqlParameters to help against SQL injection attacks. You could (and should) do
additional validation against the data provided via the SPItemEventProperties.
y. Select File | Save ShippingType\ItemEventReceiver.cs to save your work.
z. Select File | Close to close the ItemEventReceiver.cs file.
aa. Select Build | Build Solution.
bb. Select Build | Deploy Solution. Watch the Visual Studio status bar for
information about the deploy process. Wait for the Deploy succeeded message as
in the image below.
Note: As part of the deploy process, the VSeWSS templates take care of installing your
assembly into the Global Assembly Cache. In addition, it deploys all of the supporting
files to the correct locations in your SharePoint installation. Because it resets your IIS
Page 7 of 24
Event Handlers – C#
Tasks Detailed Steps
application pool, it might take a bit longer to load up your SharePoint site after you
do your deployment.
cc. Select Start | Explorer to start the Windows Explorer.
dd. Navigate to C:\SPHOLS\Labs\Lab03_EventHandler.
ee. Double-click on the CreateDB.cmd file. Verify there were no errors. This script
creates a simple database called Packages with a table called Tracking that you
will use to enter shipping information.
ff. Close Windows Explorer.
gg. Select Start | All Programs | Internet Explorer.
hh. Once the SharePoint home page appears, select the Create command from the
Site Actions menu.
ii. On the Create page, click the Custom List link in the Custom Lists gallery.
Page 8 of 24
Event Handlers – C#
Tasks Detailed Steps
Create.
ll. Select the List Settings command from the Settings menu of the newly created
Shipping list.
mm. On the Customize Shipping page, select the Advanced settings link
under the General Settings gallery.
nn. On the List Advanced Settings page, set the Allow management of content
types? option to Yes.
Page 9 of 24
Event Handlers – C#
Tasks Detailed Steps
oo. Once you’ve set the option, click OK to commit your change.
pp. Back on the Customize Shipping page select the Add from existing site content
types link in the Content Types gallery.
qq. In the list of Available Site Content Types, select the ShippingType content
type and then click the Add > button.
Page 10 of 24
Event Handlers – C#
Tasks Detailed Steps
uu. Select the Shipping list link in the site’s breadcrumb list to return to the list.
Page 11 of 24
Event Handlers – C#
Tasks Detailed Steps
ww. On the New Item page, fill in the form with data from the table below and click
OK to add the new item.
Column Data
Title Super Widgets
Ship ID X12345
Ship To Jacqui Smith
Street 123 Main Street
City Redmond
State WA
Postal Code 98205
Tracking Shipped
xx. Switch to Visual Studio.
yy. Select View | Server Explorer.
zz. In the Server Explorer window, right-click on the Data Connections node and
select Add Connection.
aaa. In the Choose Data Source dialog, choose Microsoft SQL Server from the Data
source list and click Continue.
bbb. In the Server name field, enter localhost.
ccc. From the Select or enter a database name combo-box, select Packages.
ddd. Click Test Connection to verify. Dismiss any positive confirmation
dialog that appears. If the connection fails, verify your input.
eee. Click OK to complete creating the connection.
fff. Expand the spvm.Packages.dbo node until you can see the Tracking table under
the Tables folder.
Page 12 of 24
Event Handlers – C#
Tasks Detailed Steps
ggg. Right-click on the Tracking table and select Show Table Data. Verify that the
data you entered into the SharePoint list shows up as a record in the table.
hhh. Select Window | Close All Documents.
iii. Close the Server Explorer window.
jjj. Close Internet Explorer.
kkk. Leave Visual Studio running and continue to the next section.
Page 13 of 24
Event Handlers – C#
Exercise 2
Validation Event Handler
Scenario
In this exercise, you’ll enhance the code you’ve already written to validate data provided against another list. You
will first create a second list to track invoices. You will then modify the event handler code to use the data from this
second list to determine if the code should add a record to the SQL Server 2008Tracking table.
Page 14 of 24
Event Handlers – C#
Tasks Detailed Steps
DisplayName="Status"
StaticName="PaymentStatus"
Hidden="FALSE" Required="TRUE"
Sealed="FALSE">
<CHOICES>
<CHOICE>Billed</CHOICE>
<CHOICE>Paid</CHOICE>
</CHOICES>
</Field>
i. Select File | Save PaymentType\PaymentType.xml to save your work.
j. Select File | Close to close the PaymentType.xml file
k. In the Solution Explorer, right-click on the ItemEventReceiver.cs file under the
ShippingType folder and select Open.
l. Scroll down in the source file until you find the following block of commented
code:
//public override void ItemAdding(SPItemEventProperties
properties)
//{
//}
m. Uncomment the code and add the following code as the method body:
try
{
bool okToShip = false;
SPList invoices = null;
string packageID =
properties.AfterProperties["ShipID"].ToString();
if (invoices != null)
{
SPQuery q = new SPQuery();
q.ViewFields = "<FieldRef Name='PaymentStatus'/>";
q.Query =
string.Format("<Where><Eq><FieldRef Name='ShipID'/>"
+
"<Value Type='Text'>{0}</Value></Eq></Where>",
packageID);
Page 15 of 24
Event Handlers – C#
Tasks Detailed Steps
SPListItemCollection list = invoices.GetItems(q);
string paymentStatus = null;
if (list.Count == 1)
{
paymentStatus = list[0]["PaymentStatus"].ToString();
}
properties.Cancel = (!okToShip);
if (!okToShip)
{
properties.ErrorMessage = "Invoice has not been
paid.";
}
}
Note: The code first uses the AfterProperties collection to get the ShipID value. You’ll
note since this is a Before event, the item has not been created and added to the
database, thus you can’t use ListItem object to the ShipID. Next the code opens the
web to grabs a reference to the Invoices list.
Assuming the Invoices list exists, the code creates a SPQuery object to search for a
valid invoice. First, the code restricts list of fields returned by using the ViewFields
property. Next, it creates a filter clause so that it can find the correct invoice. The
assumption is that each invoice will have a ShipID that matches the Package’s ID
(which the code already retrieved). The code assigns the filter clause to the Query
property of the SPQuery object and then executes the query by calling the GetItems
method on the Invoices list object.
The code checks to see that the list returned a single item. If this is true, the code
retrieves the PaymentStatus. If the PaymentStatus is not empty and it has a value of
Paid, then the code marks the Boolean flag okToShip as True. The code uses this flag
to determine if it should add cancel the event, which in turn would prevent the code in
the ItemAdded event from running.
n. Select File | Save ShippingType\ItemEventReceiver.vb to save your work.
o. Select File | Close to close the ItemEventReceiver.cs file.
p. Select View | Server Explorer.
q. If necessary, expand the spvm.Packages.dbo node until you can see the
Page 16 of 24
Event Handlers – C#
Tasks Detailed Steps
Tracking table under the Tables folder.
r. Right-click on the Tracking table and select Show Table Data.
s. Select the row indicator for the only row in the table.
t. Right-click and select Delete to remove the row.
u. Click Yes when asked to confirm the row deletion.
v. Select Start | All Programs | Internet Explorer.
w. Once the Team Site home page appears, click the Shipping link.
Page 17 of 24
Event Handlers – C#
Tasks Detailed Steps
oo. On the Customize Invoices page, select the Advanced settings link under the
General Settings gallery.
pp. On the List Advanced Settings page, set the Allow management of content
types option to Yes.
qq. Once you’ve set the option, click OK to commit your change.
rr. Back on the Customize Invoices page select the Add from existing site content
types link in the Content Types gallery.
ss. In the list of Available Site Content Types, select the PaymentType content
type and then click the Add > button.
tt. Click OK to save your change.
uu. Back on the Customize Invoices page select the Change new button order and
default content type link in the Content Types gallery.
vv. Remove check for the Visible option for the Item content type and click OK.
ww. Now you need to recreate the Shipping list. Select the Create command from the
Site Actions menu.
xx. On the Create page, click the Custom List link in the Custom Lists gallery.
yy. On the New page, enter Shipping in the Name field.
zz. Enter List to track packages being shipped in the Description field and click
Create.
aaa. Select the List Settings command from the Settings menu of the newly created
Shipping list.
bbb. On the Customize Shipping page, select the Advanced settings link under
the General Settings gallery.
ccc. On the List Advanced Settings page, set the Allow management of content
types option to Yes.
ddd. Once you’ve set the option, click OK to commit your change.
eee. Back on the Customize Shipping page select the Add from existing site content
types link in the Content Types gallery.
fff. In the list of Available Site Content Types, select the ShippingType content
type and then click the Add > button.
ggg. Click OK to save your change.
hhh. Back on the Customize Shipping page select the Change new button order
and default content type link in the Content Types gallery.
iii. Remove check for the Visible option for the Item content type and click OK.
jjj. Click the Home tab link to return to the home page.
kkk. Select the Invoices list link in the Quick Launch list.
lll. Create an Invoice item using the data in the table below:
Column Data
Title Super Widgets
Invoice ID I98765
Ship ID X12345
Status Billed
mmm. Click the Shipping link in the Quick Launch list.
nnn. Create a Shipping item using the data in the table below.
Column Data
Title Super Widgets
Page 18 of 24
Event Handlers – C#
Tasks Detailed Steps
Ship ID X12345
Ship To Jacqui Smith
Street 123 Main Street
City Redmond
State WA
Postal Code 98205
Tracking Shipped
Note: You should receive an error as shown in the image below. The error may
include call stack information if you have this enabled on your SharePoint site.
ooo. Click the Back button on your browser to return to the data you entered.
ppp. Switch to Visual Studio.
qqq. If necessary, select View | Server Explorer.
rrr. Under the Data Connections node, expand the spvm.Packages.dbo node until
you can see the Tracking table under the Tables folder.
sss. Right-click on the Tracking table and select Show Table Data. No records
should appear.
ttt. Return to Internet Explorer. You should see your data (the active tab should be
Shipping – New Item).
uuu. Right-click on the SharePoint link in the upper left corner of the page and
select Open in New Tab.
Page 19 of 24
Event Handlers – C#
Tasks Detailed Steps
Page 20 of 24
Event Handlers – C#
Exercise 3
Feature Receiver
Scenario
In the first two exercises, you wrote code that SharePoint executed in response to Item events. In this section, you
will write code that SharePoint executes when you install a Feature. Specifically, you will create a class that inherits
from SPFeatureReceiver. You will then write code that adds an external hyperlink to the Quick Launch menu when
you activate the Feature.
Page 21 of 24
Event Handlers – C#
Tasks Detailed Steps
events, you only need to put code into the members that you are interested.
l. Comment out the following line of code in the FeatureDeactivating,
FeatureInstalled, and FeatureUninstalling methods:
throw new Exception("The method or operation is not
implemented.");
m. In the FeatureActivated procedure, replace the existing code with the following
code:
try
{
const string title = "WSS Dev Center";
const string url =
"http://msdn.microsoft.com/en-
us/sharepoint/default.aspx";
SPWeb featureWeb =
(SPWeb)properties.Feature.Parent;
SPNavigationNodeCollection qlNodes =
featureWeb.Navigation.QuickLaunch;
SPNavigationNode newLink =
new SPNavigationNode(title, url, true);
qlNodes.AddAsFirst(newLink);
featureWeb.Update();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Note: Because you are scoping this feature to a SharePoint web, you can use the
properties instance to access the SPWeb object. Using this instance, the code gets the
list of existing links or nodes on the Quick Launch menu. The code then enumerates
the list seeing if a link with the same title already exists. If the code finds an existing
link, it exits. Otherwise, it continues and creates a new link, in the form of a
Page 22 of 24
Event Handlers – C#
Tasks Detailed Steps
SPNavigationNode instnace, and adds it to the node collection. Finally, the code calls
Update on the web object to ensure the changes are committed.
n. Select File | Save Links\LinkReceiver.cs to save your work.
o. Select File | Close.
p. Select View | Other Windows | WSP View.
q. In the WSP View window, expand the Shipping node. This window makes it
easy to add new and remove existing features as well as to reorder how VSeWSS
installs them.
r. On the WSP View toolbar, click the Create new feature button.
s. In the WSP View, click on the newly added Feature1 node and then click it again
to open edit mode and change the name to LinksFeature. Note if you’ve not
changed your keyboard bindings, you can press F2 to enter edit mode.
t. Expand the LinksFeature folder.
u. Under the LinksFeature folder, double-click feature.xml.
v. Replace the existing Feature element with the following XML:
<Feature Id="0db7b642-2f16-4d41-b16e-c4153b91d59b"
Title="LinksFeature"
Scope="Web"
Version="1.0.0.0"
Hidden="FALSE"
DefaultResourceFile="core"
xmlns="http://schemas.microsoft.com/sharepoint/"
ReceiverAssembly="Shipping,
Version=1.0.0.0,
Culture=neutral,
PublicKeyToken={Replace}"
ReceiverClass="Shipping.Links.LinksReceiver"
/>
Page 23 of 24
Event Handlers – C#
Tasks Detailed Steps
w. In the previous XML, you need to provide a valid public key token. Select Start |
Explorer.
x. Navigate to the Global Assembly Cache at C:\Windows\Assembly.
y. In the right pane, scroll until you can select the Shipping assembly.
Page 24 of 24