Wednesday, 11 April 2012

User Controls and Server Controls in SharePoint

User Controls

A user control is a control that is associated with a .ASCX extension and was originally intended for a developer to re-use within a single project.  ASP.NET developers know it is really easy to create a new user control, drag and drop some controls onto a visual designer, put some logic in the control’s code-behind, and re-use the control within a single project.  This is because the .ASCX file associated with the control enables you to create markup for your control:
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Control Language="C#" 
        AutoEventWireup="true" 
        CodeBehind="EchoControl.ascx.cs" 
        Inherits="ControlsDemo.ControlTemplates.ControlsDemo.EchoControl" %>


Enter some text:
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Button" />
<asp:Label ID="Label1" runat="server" Visible="false"></asp:Label>
Because you can add markup for your control, you get the nice WYSIWYG designers for your control.  This allows you to drag items from the toolbox, such as a button, a label, and a text box. 
image
Another nice feature of user controls is that you can quickly add event handlers for your control.  For instance, I double-click the button to add some code-behind, and Visual Studio pops up the code editor to allow me to add some code.
using System;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ControlsDemo.ControlTemplates.ControlsDemo
{
    public partial class EchoControl : UserControl
    {     
        protected void Button1_Click(object sender, EventArgs e)
        {
            Label1.Text = "You entered: " + 
                TextBox1.Text + " at " + 
                System.DateTime.Now.ToLongTimeString();
            Label1.Visible = true;
        }
    }
}
Notice that our code-behind derives from System.Web.UI.UserControl.  For existing ASP.NET developers, you will be happy to see that it’s the same old UserControl class that’s been there since ASP.NET was introduced.  By using the .ASCX, Visual Studio 2010 provides the same WYSIWYG, drag-and-drop features that you have with ASP.NET development.  In your SharePoint 2010 project, add a new User Control to your project, add the markup to the .ASCX file, and put some code in the code-behind.  The project structure will look like this:
image
When the solution is compiled, the code (the .cs classes) are compiled into an assembly that is deployed to the GAC.  The ASCX file points to our assembly, which SharePoint deploys to the global assembly cache.  SharePoint deploys your .ASCX file to a special location: 
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\CONTROLTEMPLATES
If you open that directory, you will see lots of out-of-box controls, such as Welcome.ascx, the control that is registered in the v4.master master page in SharePoint 2010.  Once the control is deployed to the ControlTemplates directory structure, an end user can then use the control in their master page or page.  For instance, we’ll use SharePoint Designer 2010 to edit a master page to use our control.  At the top of the file, register the control:
<%@ Register TagPrefix="demo" TagName="EchoControl"  
src="~/_controltemplates/ControlsDemo/EchoControl.ascx" %>
You can see where to do that in this screen shot:
image
Once our control is registered, we use it in our page, and the visual design is used in SharePoint Designer 2010 to give a WYSIWYG rendering to the end user.
image
We save the master page and then look at the final product:
image
User controls are a great way to add functionality to a SharePoint site for end users without requiring a web part.  You might have noticed that Visual Studio 2010 includes a new project item template called “Visual Web Part”.  This project simply creates a .ASCX control that is loaded by your web part.

 

Server Controls

A server control is a compiled control that renders on the server.  Where user controls derive from System.Web.UI.UserControl, a server control (also known as a custom control) typically derives from System.Web.UI.WebControl.  The main difference is that server controls do not have a corresponding .ASCX control.  For some scenarios, this can be highly beneficial because the page parser does not need to parse the .ASCX control.
Creating a server control is very easy.  In Visual Studio 2010, add a new ASP.NET Server Control item to your project from the Web group.
image
The generated template is just a suggestion, you can edit the class to suit your needs.  Here is a useful control for SharePoint developers that simply shows the name of the server that is currently processing the request.
using System;
using System.Web.UI.WebControls;
using System.Web.UI;

namespace ControlsDemo
{
    [ToolboxData("<{0}:ServerNameControl runat=server></{0}:ServerNameControl>")]
    public class ServerNameControl : WebControl
    {
        protected override void CreateChildControls()
        {
            Label l = new Label();
            l.Text = System.Environment.MachineName;
            Controls.Add(l);   
        }
    }
}
This can be useful for troubleshooting inconsistent behavior among web front end servers in a load-balanced farm.  When Visual Studio builds the project, the class is compiled into our assembly and deployed to the GAC.  Once the control is registered in the GAC, we can use it in our master page similar to our previous example.  The syntax is different, because before we could point the Src attribute to the .ASCX file, this time we need to register the control and import the namespace.
<%@ Register 
    TagPrefix="demo2" 
    Namespace="ControlsDemo" 
    Assembly="ControlsDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=01374ea14aa626aa" %>
<%@ Import Namespace="ControlsDemo" %>
Once we register the control, we can now use it in our page.
<demo:ServerNameControl runat="server" id="serverNameControl"/>
Only this time, instead of seeing the nice WYSIWYG UI in SharePoint Designer 2010, we see an error message, “The type is not registered as safe.”
image
WTF?!?!
To understand what’s going on, you need to understand how the page is processed:
When a page with a user control is requested, the following occurs:
  • The page parser parses the .ascx file specified in the Src attribute in the @ Register directive and generates a class that derives from the System.Web.UI.UserControl class.
  • The parser then dynamically compiles the class into an assembly.
  • If you are using Visual Studio, then at design time only, Visual Studio creates a code behind file for the user control, and the file is precompiled by the designer itself.
  • Finally, the class for the user control, which is generated through the process of dynamic code generation and compilation, includes the code for the code behind file (.ascx.cs) as well as the code written inside the .ascx file.
[via http://support.microsoft.com/kb/893667]
The page parser will parse the page and determine if the page uses code-behind or includes in-line script.  I have blogged about the impact of marking your controls as safe for pages here and here, which gives some insight to the problem.  The reason that our user control example worked is because it was deployed to the ControlTemplates directory, an action that only a farm administrator would have privileges to do.  Thus, any control in the ControlTemplates directory structure is marked as safe out of the box:
<SafeControl Src="~/_controltemplates/*"
                   IncludeSubFolders="True"
                   Safe="True"
                   AllowRemoteDesigner="True"
                   SafeAgainstScript="True" />
The server control does not have a corresponding .ASCX file, so we need to explicitly mark it as safe.   Visual Studio 2010 makes this very easy.  Add a new Module to your project and give it a name.
image
Click the module in the Solution Explorer pane, and edit the Safe Controls property.  Add a new safe control, taking care to add the right namespace.  You can use an asterisk for the typename if any type in the namespace is safe, or you can use the class name of a specific class that is safe as I did here:
image
You can delete the sample text file that is generated.  Now, when we look at the web.config file, we see a SafeControl entry for our control:
<SafeControl Assembly="ControlsDemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=01374ea14aa626aa"
                   Namespace="ControlsDemo"
                   TypeName="ServerNameControl"
                   Safe="True"
                   SafeAgainstScript="False" />
Now, when we use the control in SharePoint Designer 2010, we have the markup correct but see nothing in the WYSIWYG view:
image
If we view the page in the browser, we can see the effect of the control being rendered (highlighted in yellow to show you where the server name is rendered).
image
You can do some amazing things with ASP.NET controls, and you can bring many of your existing controls forward so that end users can take advantage of them in their pages and master pages.

Monday, 9 April 2012

HOWTO: Create an Event Handler for SharePoint(MOSS 2007)

As I see this question popping up on many forums, I thought it would be time to write a tutorial about it, even though there are already quite a few of them handling the subject.
Prerequisites:
How-to Create an Event Handler by making use of a feature:
To start with : what exactly is an event handler for SharePoint? It’s a piece of code that is triggered when something (an event!) happens. When that happens, our event handler can replace what is supposed to happen with our own code. How do we build that in Visual Studio (using WSP Builder)?
First of all, we will be creating a WSP Builder Project called MyEventHandler:
image
Once the project is created, we will right-click the project and select add new item. In the left column, select WSPBuilder and select Event Handler in the template list. In the name field I chose to call it DemoEventHandler.
image
You’ll get a new screen where you can define the scope of the feature. You can leave it at Web
image
After this step your project will have three additional files added to it and a few folders:
image
feature.xml: the CAML based declaration of your feature.
elements.xml: the CAML based declaration of the element(s) in your feature, which is your event handler in this case.
DemoEventHandler.cs : the code that will be overriding the existing SharePoint Event Handlers.
Let’s take a look at our feature.xml code:
<?xml version=
1.0 encoding=utf-8?>
<Feature Id=
875e92bb-782c-40b4-a5a9-f55423df667e
Title=
DemoEventHandler
Description=
Description for DemoEventHandler
Version=
12.0.0.0
Hidden=
FALSE
Scope=
Web
DefaultResourceFile=
core
xmlns=
http://schemas.microsoft.com/sharepoint/>
<ElementManifests
>
<ElementManifest Location=
elements.xml/>
</ElementManifests
>
</Feature>
What this file does is identify the feature for SharePoint (Id), give it a title and description (which will be shown on the feature activation site), define a scope (where Web means site, where Site means Site Collection and then there is Web Application and Farm as possible scopes.
Another important part of the feature is the <ElementManifests> area. That area defines all the items that make part of the feature while the manifests themselves describe that specific part. As it is here the case with the event handler:
<?xml version=
1.0 encoding=utf-8 ?>
<Elements xmlns=
http://schemas.microsoft.com/sharepoint/>
<Receivers ListTemplateId=
100>
<Receiver
>
<Name>
AddingEventHandler</Name>
<Type>
ItemAdding</Type>
<SequenceNumber>
10000</SequenceNumber>
<Assembly>
MyEventHandler, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ca176e059473d6b1</Assembly>
<Class>
MyEventHandler.DemoEventHandler</Class>
<Data></Data
>
<Filter></Filter
>
</Receiver
>
</Receivers
>
</Elements>
What is important for us? First of all the ListTemplateId. The ListTemplateId defines to which List Types the Event Handler will be targeting. The table here below shows which list types there are available in SharePoint 2007:

IDName
100Generic list
101Document library
102Survey
103Links list
104Announcements list
105Contacts list
106Events list
107Tasks list
108Discussion board
109Picture library
110Data sources
111Site template gallery
112User Information list
113Web Part gallery
114List template gallery
115XML Form library
116Master pages gallery
117No-Code Workflows
118Custom Workflow Process
119Wiki Page library
120Custom grid for a list
130Data Connection library
140Workflow History
150Gantt Tasks list
200Meeting Series list
201Meeting Agenda list
202Meeting Attendees list
204Meeting Decisions list
207Meeting Objectives list
210Meeting text box
211Meeting Things To Bring list
212Meeting Workspace Pages list
300Portal Sites list
301Blog Posts list
302Blog Comments list
303Blog Categories list
1100Issue tracking
1200Administrator tasks list
2002Personal document library
2003Private document library

Once we have defined which list we are going to target we will define that we are overriding an ItemAdding event. ItemAdding means that the event will be fired right before the item is added to the list. This allows us to modify the item before it is saved to the list. The other parameters aren’t that important at the moment, apart from the Assembly and Class that will be linking to the assembly that contains the code of your event handler.
Possible events that you can override:
ItemAdded
ItemAdding
ItemAttachmentAdded
ItemAttachmentAdding
ItemAttachmentDeleted
ItemAttachmentDeleting
ItemCheckedIn
ItemCheckedOut
ItemCheckingIn
ItemCheckingOut
ItemDeleted
ItemDeleting
ItemFileConverted
ItemFileMoved
ItemFileMoving
ItemUncheckedOut
ItemUncheckingOut
ItemUpdated
ItemUpdating
Ok, so we checked out the feature.xml and the elements.xml, but there is also the DemoEventHandler.cs file. That contains the actual code of our event handler:
using
System;
using
System.Collections.Generic;
using
System.Text;
using
Microsoft.SharePoint;
namespace
MyEventHandler
{
class DemoEventHandler : SPItemEventReceiver
{
public override void ItemAdded(SPItemEventProperties properties)
{
base.ItemAdded(properties);
}
public override void ItemAdding(SPItemEventProperties properties)
{
base.ItemAdding(properties);
}
public override void ItemUpdated(SPItemEventProperties properties)
{
base.ItemUpdated(properties);
}
public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);
}
}
}
If you deploy it like this your event handler will run, but it will just call the base class and nothing special will happen. Let’s change the ItemAdding Event (as it is already defined in our CAML to be deployed). We will change the itemadding event so that it will check, when an item is being added, by making sure the CheckValue column does not contain the string “dontadd”. If it does contain dontadd, an error message is displayed and the item is NOT added to the list. To do this, we modify the ItemAdding Event to this:
public override void ItemAdding(SPItemEventProperties properties)
{
if (properties.AfterProperties["CheckValue"].ToString() == “dontadd”)
{
properties.ErrorMessage = string.Format(“The CheckValue column equals dontadd -> item will not be added.”);
properties.Status = SPEventReceiverStatus.CancelWithError;
properties.Cancel = true;
}
}
A little extra explanation. The AfterProperties contain the NEW values of an item. The BeforeProperties contain the OLD values of an item in case of an update. For an ItemAdding event the BeforeProperties are empty. What we do here is check the CheckValue properties value. If it contains “dontadd” we show the error message and by making use of properties.Status = SPEventReceiverStatus.CancelWithError we cancel the base.ItemAdding(properties) call. By adding properties.Cancel = true we cancel the Itemadding event.
Ok, so now we built this, but how do we get this working on our SharePoint site? With WSPBuilder that is quite easy. Rightclick on your project, select WSPBuilder / Build WSP. This will create a solution file to be deployed on your SharePoint farm. Once that is done, select WSPBuilder / Deploy and the solution will be installed and deployed to your farm.
image
Ok, one thing to note here is that the event handler will be targeting all lists. This means that every list that does not contain the CheckValue column will no longer work. But checking if the column exists is something that you should be able to do yourself. Once it is deployed to your SharePoint farm, create a new Custom List and Add the column CheckValue of type text. Then go to Site Settings, Site Features (NOT Site Collection Features as the scope was Web) and activate our newly deployed feature:
image
Ok, now we can test it by adding a new item with CheckValue equal to dontadd.
image
If you did everything according to plan, this is the information you should be receiving when you click ok:
image
Happy Coding!
In addition I added a few other interesting bits regarding Event Handlers
How-to Register an Event Handler through C# code:
The following code allows you to register an event handler by making use of code. RunWithElevatedPrivileges isn’t always necessary, but I added it to it so that you know that you can’t run the code in an application page as a user who doesn’t have the necessary rights.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
impersonateweb.AllowUnsafeUpdates = true;
_spListAanwezige.EventReceivers.Add(SPEventReceiverType.ItemAdded, “Namespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=61942ef99a051977″, “Namespace.EventClass”);
_ impersonateweb.AllowUnsafeUpdates = false;
});
How-to see if your event handler is deployed properly to the list:
Out of the box SharePoint doesn’t display if your event handler is correctly hooked to a list. I make use of SharePoint Inspector(http://www.codeplex.com/spi) to check out my SharePoint Farm. To see if something is hooked to your list go to the following structure in your SharePoint Inspector to check out which events are registered to your list:
image

Developing a SharePoint 2007 Feature...

I have worked with SharePoint for a while now, mostly mostly writing code for integration scenarios, where data needs to be "pulled" or "pushed" into SharePoint involving other enterprise software applications.
SharePoint 2007 Features are basically a mechanism to extend SharePoint in any way you need. Mike Ammerlaan wrote a brief and concise technical article describing features: 
I will try to describe how to develop a SharePoint 2007 Feature from zero. In this case our feature will handle the event that SharePoint usually handles when a file gets added to a Document Library. When a user uploads a new document to a Document Library, we want to run some custom code. In our example we will simply be creating a text file on the desktop containing data from the file that fired such event. Obviously you would want to make it something meaningful, like pass that data to an external workflow application or do womething with that document, but this is just an example.

1. Setting up our project
Launch Visual Studio 2005 and create a new Class Library project.
File > New Project > Class Library
SharePoint Features
Name it SharePointEventHandler and let Visual Studio create the project files for you in the Solution Explorer.:
Add a reference to the SharePoint Services API assembly. Right-click in your solutions explorer on the reference folder and select Add reference
SharePoint Features
The list of available .NET assemblies shows up
SharePoint Features
Scroll almost all the way to the bottom and select Windows SharePoint (r) Services, Version 12.0.0.0
Go back to the Solution Explorer and rename you class1.cs file to ItemEventreceiver.cs
SharePoint Features


2. Writing our class with our custom code
We will be using the WSS API and we will be writing a text file, so we need to write these two directives
using System.IO;
using Microsoft.SharePoint;
Rename your class name to ItemEventReceiver and inherit from SPItemEventReceiver as shown below:
SharePoint Features
Declare a StreamWriter object:
SharePoint Features

Now we will write the method we want to override so we can run our own custom code. In this case, the event we want to trap is the ItemAdded event (after someone adds an item).
SharePoint Features
The ItemAdded method is the one that will be called and the properties parameter contains detailed information about the file that fired this event.
Our intent is that a text file is written to our desktop and we will write to it with data coming from the Properties parameter.
Finish your class as shown below.

ItemEventReceiver.cs code

using System;
using System.Collections.Generic;
using System.Text;

using System.IO;
using Microsoft.SharePoint;

namespace SharePointEventHandler
{
  public class ItemEventReceiver : SPItemEventReceiver
  {
    private StreamWriter SW;

    public override void ItemAdded(SPItemEventProperties properties)
    {
      base.ItemAdded(properties);
     
      try
      {
        //Set this path below to suit your needs...
        SW=File.CreateText(@"[...]\Desktop\eventoutput.txt");

        SW.WriteLine("CurrentUserId: "  + properties.CurrentUserId.ToString());
        SW.WriteLine("BeforeUrl: "         + properties.BeforeUrl.ToString());
        SW.WriteLine("SiteId: "              + properties.SiteId.ToString());
        SW.WriteLine("ListId: "               + properties.ListId.ToString());
        SW.WriteLine("ListItem: "           + properties.ListItem.ToString());
        SW.WriteLine("ListTitle: "            + properties.ListTitle.ToString());
        SW.WriteLine("ReceiverData: "   + properties.ReceiverData.ToString());
        SW.WriteLine("WebUrl: "           + properties.ToString());

        SW.Close();
       }
   
       catch (Exception ex)
       {
         properties.Cancel = true;
         properties.ErrorMessage = ex.Message;
         throw ex;
       }

       finally
       {
         this.SW.Dispose();
        }
      }
    }
 }
* Note that the catch block contains two lines that will have no effect, because this would happen after the file was added, so we cannot cancel it anymore nor display an error message. These two lines would be used if we were trapping the ItemAdding event, which fires (asynchroneously) before the item is added.

3. Signing and Installing our assembly into the GAC
The main piece of our feature is our class and once compiled, it needs to be installed in the GAC. In order for it to be able to be installed in the GAC, it also needs to be strong named. Several steps to take, but in VS2005 it is actually hardly any effort at all.
In your Solutions Epxlorer, double click on Properties (My Project in VB) and then select Signing. From the combobox, select New.
SharePoint Features
This will launch a dialog as shown below
SharePoint Features
Type in SharePointEventHandler for your Key File name and uncheck the protection feature. Click OK.
This automatically signs our assembly when we compile. What we still need to do is register our assembly into the GAC and we do that with Post-build events. In the same page, on the left hand, look for Build Events (In VB it is under Build and then there is a button called events)
In the text area type (exactly as you see it):
"C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe" -i "$(TargetPath)"

SharePoint Features
Click on OK and then build your solution. In your Output window you should see the progress of the build and if correct, you should see a line that says: "Assembly successfully added to the GAC".
Now, browse to C:\Windows\Assembly and look for a dll called SharePointEventHandler. Once found, right-click on it and check its properties.
SharePoint Features
Remember or copy the Public Key Token to a text file, because we will need this later.

4. Define our resource files
SharePoint Features require not just a compiled dll, but also a set of corresponding files. These files are stored in the "12" HIVE  on the SharePoint server. The file structure already exists and we will simply be adding files that are used by our feature to it.
Create a folder structure as shown below in your Solutions Explorer:
SharePoint Features
In this SharePointEventHandler folder create the following two blank xml files:
SharePoint Features
Open the feature.xml file and replace any code with the following:
<Feature
   Id=""
   Title="SharePoint EventHandler Feature"
   Description="This feature will blah blah blah [..]."  
   Scope="Web"
   Hidden="FALSE"
   AlwaysForceInstall="TRUE"
   ImageUrl="components.gif" xmlns="http://schemas.microsoft.com/sharepoint/">

   <ElementManifests>
      <ElementManifest Location="elements.xml" />
   </ElementManifests>
</Feature>

We will need to fill in a valid GUID for the Id (left intentionally blank).
In VS2005, click on Tools > Create GUID
SharePoint Features
Click on Copy to copy the string and place it in the Id attribute value in your feature.xml file, leaving out the curly brackets!

feature.xml code

<Feature
   Id="50BB0F5F-9FDD-4af8-8F05-F852DE735E30"
   Title="SharePoint EventHandler Feature"
   Description="This feature will blah blah blah [..]."  
   Scope="Web"
   Hidden="FALSE"
   AlwaysForceInstall="TRUE"
   ImageUrl="components.gif"
   xmlns="http://schemas.microsoft.com/sharepoint/">

   <ElementManifests>
      <ElementManifest Location="elements.xml" />
   </ElementManifests>
</Feature>
* I used an image (ImageUrl) that already existed for the icon that displays in the feature list in SharePoint. If you want to use your own, simply include the image in the IMAGES foler and point to it.
Now, open the elements.xml file and replace any code with the following

elements.xml code

<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  <Receivers ListTemplateId="101">
    <Receiver>
      <Name>SharePointEventHandler</Name>
      <Type>ItemAdded</Type>
      <SequenceNumber>1000</SequenceNumber>
      <Assembly>
        SharePointEventHandler,
        Version=1.0.0.0,
        Culture=Neutral,
        PublicKeyToken=c5138f819b90316d
      </Assembly>
      <Class>SharePointEventHandler.ItemEventReceiver</Class>
      <Data />
    </Receiver>
  </Receivers>
</Elements>
* Note that the details for the Assembly tag came from the properties window that I asked you to write down or remember in the previous step! Also, the Class name refers to the namespace.classname name used in your class.
** Note that we specify the ListTemplateId to be 101 for a Document Library. You can specify another value, therefore pointing to other lists such as an Announcements list, Tasks list, etc. Here is a way to see all the other Id's.

5. Installing the SharePoint Feature
We will now need to move the folders and their files over to the "12" Hive and register the feature with SharePoint. Again we will make us of VS2005 Post-build utility.
In your Solutions Explorer, double-click on Project and click on the Build Events SideTab. In your event text box, you should have one single line of code, which we wrote in our previous steps.
SharePoint Features
below that line, add the following code:
cd "$(ProjectDir)"
xcopy "12" "%CommonProgramFiles%\Microsoft Shared\web server extensions\12\" /ys

cd "%CommonProgramFiles%\Microsoft Shared\web server extensions\12\BIN"
stsadm -o installfeature -name SharePointEventHandler -force

iisreset 
Your code should look like this:
SharePoint Features
Basically what we are doing is compiling our code with a strong name, installing it into the GAC, then we copy the folderstructure into the 12 Hive, then we install our feature and finally reset IIS.
Before you build, ensure that SharePoint is working and navigate to the Site Features page. (Home> Site Settings > Site Features)
SharePoint Features
Now, in Visual Studio 2005, build your solution (this may take a few seconds...). Ensure you have the Output (View > Output)  window open when you compile so you can monitor step-by-step what is happening in the background and if you have any errors.
Once the build is successful, refresh yoru browser window and it should look like this:

SharePoint Features
Click on Activate to activate your feature and you are ready to go!

6. Testing our feature
Ok, let's test our feature... Open up a browser and go to your home page in SharePoint.
SharePoint Features
create a new Document Library by clicking on Documents (left hand side) and then select Create.
Now, select Document Library.
SharePoint Features
Type in a name, for instance, Feature Site Test and select Word Document as the document type (or any other type...).
SharePoint Features
And there is your Document Library.
SharePoint Features
Now, click on New and because we selected the Document type to be Word, it will launch Microsoft Word. Type in anything in this document and close. It will prompt you to save it.
SharePoint Features
Select Yes and give it any name and Save.
This will add the document to the Document Library and it this event is trapped by SharePoint that now redirects it to our custom code, which creates a text file for us on the desktop (shown below on the desktop).
SharePoint Features
When we open the text file, we will see it contains specific data about the document that fired this event.
SharePoint Features

Enjoy!