MCT Summit 2009!

Awesome news!  I have been asked to present at each of the MCT Summits in 2009!  I will be discussing the courseware library, where it has come from, where it is and where it is going!

 I plan to demo my CourseBuilder tool that we use to generate all our courses and dynamic courses!  The MCT Summit schedule is here:

 http://www.mctsummit2009.com/content/info.asp?Ccpsubsiteid=108&infoid=13

 The first stop is the Czech Republic, then back to my home town Seattle, then off to Asia!   I am looking forward to meeting all my fellow peers and educate everyone on how to be successful with the courseware library!

 Chris

SharePoint 2007 Document Encryption

Since releasing the new Advanced SharePoint Development course, I have been working on various items to add to it!  One of them is using Enterprise Library with SharePoint Event Handlers to implment document encryption!  Here is the lab!

Module #15: SharePoint Event Handlers Lab #3

 

 

Course:           Advanced SharePoint Development

Estimated Time to Complete:  45 minutes

Objectives:

·        Create an Event Handler feature that encrypts documents

Operating Notes:  none

Deliverables:

·        None

 

Overview:         SharePoint has exposed several events that we can tie into with our own code.  Let’s see how to do this!

Exercise 1 – Create a new SharePoint Event Handler

Purpose:         Create and register an event handler for SharePoint events

Result:           
A new event handler

Task 1 – Create a new Visual Studio Class Library

  1. Open Visual Studio, select New->Project
  2. Select Class Library from the project templates
  3. Name the project EncryptDocumentEventReceiver
  4. For location, c:asp
  5. Add a reference to
    • Microsoft.SharePoint.dll
    • Microsoft.Practices.EnterpriseLibrary.Common
    • Microsoft.Practices.EnterpriseLibrary.Security
    • Microsoft.Practices.EnterpriseLibrary.Security.Cryptography
  6. Add a using statement to
    • Micorosft.SharePoint
    • Microsoft.Practices.EnterpriseLibrary.Common;
    • Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    • Microsoft.Practices.EnterpriseLibrary.Security;
    • Microsoft.Practices.EnterpriseLibrary.Security.Configuration;
    • Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;
  7. Rename class1 to EncryptDocument
  8. Make EncryptDocument inherit from SPItemEventReceiver
  9. Add the following methods:

private void Encrypt(SPItemEventProperties properties)

        {

            //get the file, encrypt it

            SPFile file = properties.ListItem.File;

            byte[] bytes = file.OpenBinary();

 

            //encrypt the file

            IConfigurationSource source = new SystemConfigurationSource();

            SymmetricCryptoProviderFactory factory = new SymmetricCryptoProviderFactory(source);

            ISymmetricCryptoProvider provider = factory.CreateDefault();

 

            byte[] encryptedByteArray = provider.Encrypt(bytes);

            string encryptedText = Convert.ToBase64String(encryptedByteArray);

 

            file.SaveBinary(encryptedByteArray);

            file.Update();    

        }

 

        private void Decrypt(SPItemEventProperties properties)

        {

            //get the file, encrypt it

            SPFile file = properties.ListItem.File;

            byte[] bytes = file.OpenBinary();

 

            //encrypt the file

            IConfigurationSource source = new SystemConfigurationSource();

            SymmetricCryptoProviderFactory factory = new SymmetricCryptoProviderFactory(source);

            ISymmetricCryptoProvider provider = factory.CreateDefault();

 

            byte[] decryptedByteArray = provider.Decrypt(bytes);

            string decryptedText = Convert.ToBase64String(decryptedByteArray);

 

            file.SaveBinary(decryptedByteArray);

            file.Update();           

        }

 

        public override void ItemCheckedOut(SPItemEventProperties properties)

        {

            Decrypt(properties);

 

            base.ItemCheckedOut(properties);

        }

 

        public override void ItemCheckedIn(SPItemEv
entProperties properties)

        {

            Encrypt(properties);

 

            base.ItemCheckedIn(properties);

        }

       

        public override void ItemAdded(SPItemEventProperties properties)

        {

            Encrypt(properties);

 

            base.ItemAdded(properties);

        }       

 

  1. Right Click the project, select Properties
  2. Select the Signing tab
  3. Click “Sign the assembly”
  4. Select <New…>, type EncryptDocumentEventReceiver.snk
  5. Uncheck “Password…”
  6. Build the project, Press Ctrl-Shift-B
  7. Copy the C:ASPEncryptDocumentEventReceiverEncryptDocumentEventReceiverinDebugEncryptDocumentEventReceiver.dll to the c:windowsassembly directory (this installs the assembly in the gac)

Task 2 – Extend the web.config file

  1. Open Enterprise Library console
  2. Click the open button, browse to the c:inetpubwwwrootwssvirtualdirectories100web.config file
  3. Click Open
  4. Right click the “C:inetpub…” node, select New->Cryptography Application Block
  5. Right click the Symmetric Provider node, select New->Symmetric Algorithm Provider
  6. Select TripleDESCryptoServiceProvider, Click Ok
  7. In the Cryptographic key wizard, Click Next
  8. Click Generate
  9. Click Next
  10. Name the key “EncryptIt.key”, Click Save
  11. Click Next
  12. Select Machine mode, Click Finish
  13. Click the Cryptography Application Block node
  14. For DefaultSymmetricCryptoProvider, select TripleDESCryptoServiceProvider

Task 3 – Create a console application to register the event handler

  1. In Visual Studio, click Add->New->Project
  2. Select a Windows Console Application
  3. Modify the Main method to this:


static void Main(string[] args)

        {

            try

            {

                SPSite site =
new SPSite("http://localhost:100");

                SPWeb web = site.OpenWeb();

 

                SPEventReceiverDefinitionCollection receivers = web.EventReceivers;               

                SPEventReceiverDefinition newRecevier = receivers.Add();

                newRecevier.Name = "EncryptDocumentItemAdded";

                newRecevier.Assembly = "EncryptDocumentEventReceiver, Version=1.0.0.0, Culture=neutral,PublicKeyToken=3041621ef2536dab";

                newRecevier.Class = "EncryptDocumentEventReceiver.EncryptDocument";

                newRecevier.Type = SPEventReceiverType.ItemAdded;

                newRecevier.Update();

 

                newRecevier = receivers.Add();

                newRecevier.Name = "EncryptDocumentItemCheckedOut";

                newRecevier.Assembly = "EncryptDocumentEventReceiver, Version=1.0.0.0, Culture=neutral,PublicKeyToken=3041621ef2536dab";

                newRecevier.Class = "EncryptDocumentEventReceiver.EncryptDocument";

                newRecevier.Type = SPEventReceiverType.ItemCheckedOut;

                newRecevier.Update();

 

                newRecevier = receivers.Add();

                newRecevier.Name = "EncryptDocumentItemCheckedIn";

                newRecevier.Assembly = "EncryptDocumentEventReceiver, Version=1.0.0.0, Culture=neutral,PublicKeyToken=3041621ef2536dab";

                newRecevier.Class = "EncryptDocumentEventReceiver.EncryptDocument";

                newRecevier.Type = SPEventReceiverType.ItemCheckedIn;

                newRecevier.Update();               

            }

            catch (Exception ex)

            {

                Console.Write(ex.Message);

            }

        }

 

 

  1. Compile the project (Ctrl-Shift-B)
  2. Run the Console Project
  3. Reset IIS
  4. Open the http://local
    host:100
    site
  5. Create a text document, upload it to the document library
  6. Open the document, notice it is encrypted
  7. Check out the document
  8. Open the document, it is now decrypted!

 

Custom SharePoint Designer Workflow Activity For Document Encryption!

Module #17: Custom Activities Lab #3

 

 

Course:           Advanced SharePoint Development

Estimated Time to Complete:  60 minutes

Objectives:

·        Create a custom workflow activity for SharePoint Designer

Operating Notes:  

·        None

Deliverables:

·        None

 

Overview:         Let’s create our own custom workflow using SharePoint Designer

Exercise 1 – Create a Custom Activity

Purpose:         Create a custom activity to be used by SharePoint Designer

Result:           
Custom Activity

Task 1 – Create a Project

  1. Open Visual Studio
  2. Select the File->New->Project
  3. Select Visual C#
  4. For template, select Workflow project type.
  5. Select the Workflow Activity Library template.
  6. For Location, type C:asp
  7. For Name, type CustomActivities
  8. Click OK
  9. Rename Activity1.cs to EncryptDocument.cs
  10. Right click the project, select Add Reference
  11. Add the following references:
    • C:program filescommon filesmicrosoft sharedweb server extenstionsisapiMicrosoft.SharePoint.dll
    • C:program filescommon filesmicrosoft sharedweb server extenstionsisapiMicrosoft.SharePoint.WorkflowActions.dll
    • C:Program FilesMicrosoft Enterprise Library 3.1 – May 2007BinMicrosoft.Practices.EnterpriseLibrary.Common.dll
    • C:Program FilesMicrosoft Enterprise Library 3.1 – May 2007BinMicrosoft.Practices.EnterpriseLibrary.Security.Cryptography.dll
  12. Right click the EncryptDocument shape, select View Code
  13. Add the following using statements for the Workflow code:
    • using Microsoft.SharePoint;
    • using Microsoft.SharePoint.Workflow;
    • using Microsoft.SharePoint.WorkflowActions;
  14. Since we are going to use Enterprise library to do our encryption, add the following using statements:
    • using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
    • using Microsoft.Practices.EnterpriseLibrary.Security;
    • using Microsoft.Practices.EnterpriseLibrary.Security.Cryptography;
  15. Add the following Execute method:


protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

        {

            SPSite site = (SPSite)__Context.Site;

            SPWeb web = (SPWeb)__Context.Web;

            this.ListId.Trim();

            this.ListId.ToLower();

            Guid listGUID = new Guid(this.ListId);

            SPList list = web.Lists[listGUID];

            SPListItem item = list.GetItemById(this.ListItem);

 

            SPFile file = item.File;

            byte[] bytes = file.OpenBinary();

 

            //encrypt the file

            IConfigurationSource source = new SystemConfigurationSource();

            SymmetricCryptoProviderFactory factory = new SymmetricCryptoProviderFactory(source);

            ISymmetricCryptoProvider provider = factory.CreateDefault();

 

            byte[] encryptedByteArray = provider.Encrypt(bytes);           

            file.SaveBinary(encryptedByteArray);

            file.Update();

 

            return ActivityExecutionStatus.Closed;

        }       

 

  1. Add the following property, this will provide access to the workflow context back to our code:


public static DependencyProperty __ContextProperty = System.Workflow.ComponentModel.DependencyProperty.Register("__Context", typeof(WorkflowContext), typeof(EncryptDocument));

 

        [Description("Workflow Context")]

        [Category("Context")]

        [ValidationOption(ValidationOption.Required)]

        [Browsable(true)]

        [DesignerSerializationVisib
ility(DesignerSerializationVisibility.Visible)]

        public WorkflowContext __Context

        {

            get

            {

                return ((WorkflowContext)(base.GetValue(EncryptDocument.__ContextProperty)));

            }

            set

            {

                base.SetValue(EncryptDocument.__ContextProperty, value);

            }

        }

 

  1. Add the following ListId property:


public static DependencyProperty ListIdProperty = System.Workflow.ComponentModel.DependencyProperty.Register("ListId", typeof(string), typeof(EncryptDocument));

 

        [Description("This is the description which appears in the Property Browser")]

        [Category("This is the category which will be displayed in the Property Browser")]

        [ValidationOption(ValidationOption.Required)]

        [Browsable(true)]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

        public string ListId

        {

            get

            {

                return ((string)(base.GetValue(EncryptDocument.ListIdProperty)));

            }

            set

            {

                base.SetValue(EncryptDocument.ListIdProperty, value);

            }

        }

 

  1. Add the following ListItem property:


public static DependencyProperty ListItemProperty = System.Workflow.ComponentModel.DependencyProperty.Register("ListItem", typeof(int), typeof(EncryptDocument));

 

        [Description("This is the description which appears in the Property Browser")]

        [Category("This is the category which will be dis
played in the Property Browser")]

        [ValidationOption(ValidationOption.Required)]

        [Browsable(true)]

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]

        public int ListItem

        {

            get

            {

                return ((int)(base.GetValue(EncryptDocument.ListItemProperty)));

            }

            set

            {

                base.SetValue(EncryptDocument.ListItemProperty, value);

            }

        }

 

 

  1. Add another Activity, name this one DecryptDocument
  2. Add the same using statements (steps 13,14) and the same properties (steps 16,17,18)
  3. Add the following Execute method:


protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

        {

            SPSite site = (SPSite)__Context.Site;

            SPWeb web = (SPWeb)__Context.Web;

            this.ListId.Trim();

            this.ListId.ToLower();

            Guid listGUID = new Guid(this.ListId);

            SPList list = web.Lists[listGUID];

            SPListItem item = list.GetItemById(this.ListItem);

 

            SPFile file = item.File;

            byte[] bytes = file.OpenBinary();

 

            //encrypt the file

            IConfigurationSource source = new SystemConfigurationSource();

            SymmetricCryptoProviderFactory factory = new SymmetricCryptoProviderFactory(source);

            ISymmetricCryptoProvider provider = factory.CreateDefault();

 

            byte[] encryptedByteArray = provider.Decrypt(bytes);

            file.SaveBinary(
encryptedByteArray);

            file.Update();

 

            return ActivityExecutionStatus.Closed;

        }

 

  1.  

 

Task 2 – Strong Name the assembly

  1. In the Solution Explorer, Right Click on Properties
  2. Click the Signing tab
  3. Check the checkbox, Sign the Assembly
  4. Select the New option from the Drop down below
  5. For Filename, type DocumentEncryption
  6. Uncheck the “Protect my key file with a password” option
  7. Compile the project

Task 3 – Copy to the GAC

  1. Copy the EncryptDocument.dll to the C:windowsassembly directory
  2. Copy the Enterprise Library dlls to the GAC as well
    • C:Program FilesMicrosoft Enterprise Library 3.1 – May 2007BinMicrosoft.Practices.EnterpriseLibrary.Common.dll
    • C:Program FilesMicrosoft Enterprise Library 3.1 – May 2007BinMicrosoft.Practices.EnterpriseLibrary.Security.Cryptography.dll

Task 4 – Modify the web.config file

  1. Open web.config file in the C:inetpubwwwrootwssvirtualdirectories100 directory
  2. Add the following element to the System.Workflow.ComponentModel.WorkflowCompiler element:


<authorizedType

   Assembly="CustomActivities,Version=1.0.0.0,Culture=neutral,PublicKeyToken=[YOUR PUBLICKEYTOKEN]"

    Namespace="CustomActivities"

    TypeName="*"

    Authorized="True" />

 

  1. Save and close the web.config file
  2. Open Enterprise Library Configuration tool (shortcut on the desktop)
  3. From EntLib, open the web.config file
  4. Right click the “C:inetpub…” node, select New->Cryptography Application Block
  5. Right Click the Symmetric Providers node, select New->Symmetric algorithm provider
  6. Select DESCryptoServiceProvider
  7. Click Ok
  8. In the Cryptographic Key Wizard dialog, Click Next
  9. Click Generate
  10. Click Next
  11. Save the key file to the c:inetpubwwwrootwssvirtualdirectories100 directory, call it EncryptIt
  12. Click Save
  13. Click Next
  14. Select Machine Mode
  15. Click Finish
  16. Click the Cryptography Application Block node
  17. For DefaultSymmetricCryptoProvider, select the DESCryptoServiceProvider
  18. Save the web.config file

Task 5 – Create an ACTIONS file

  1. Create a file in C:Program FilesCommon FilesMicrosoft Sharedweb server extensions12TEMPLATE1033Workflow called ENCRYPT.ACTIONS
  2. Copy the following to the file:


<?xml version="1.0" encoding="utf-8"?>

<WorkflowInfo Language="en-us">

  <Actions>

<Action

    Name="Encrypt a document/item"

    ClassName="CustomActivities.EncryptDocument"

    Assembly="CustomActivities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[PUBLICKEYTOKEN]"

    AppliesTo="all"

    Category="Encryption">

    <RuleDesigner Sentence="Encrypt %1 Item">

              <FieldBind Field="ListId,ListItem,ItemProperties" Text="this list" Id="1" DesignerType="UpdateListItem" />

         </RuleDesigner>

         <Parameters>

              <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />

              <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />

              <Parameter Name="ListItem" Type="System.Int32, mscorlib" Direction="In" />

              <Parameter Name="ItemProperties" Type="System.Collections.Hashtable, mscorlib" Direction="In" />

         </Parameters>

</Action>

<Action

    Name="Decrypt a document/item"

    ClassName="CustomActivities.DecryptDocument"

    Assembly="CustomActivities, Version=1.0.0.0, Culture=neutral, PublicKeyToken=[PUBLICKEYTOKEN]"

    AppliesTo="all"

    Category="Encryption">

    <RuleDesigner Sentence="Decrypt %1 Item">

              <FieldBind Field="ListId,ListItem,ItemProperties" Text="this list" Id="1" DesignerType="UpdateListItem" />

         </RuleDesigner>

         <Parameters>

              <Parameter Name="__Context" Type="Microsoft.SharePoint.WorkflowActions.WorkflowContext" Direction="In" />

              <Parameter Name="ListId" Type="System.String, mscorlib" Direction="In" />

              <Parameter Name="ListItem&
quot; Type="System.Int32, mscorlib" Direction="In" />

              <Parameter Name="ItemProperties" Type="System.Collections.Hashtable, mscorlib" Direction="In" />

         </Parameters>

</Action>

  </Actions>

</WorkflowInfo>

 

Task 6 – Create a workflow to use the Encryption action

  1. Reset IIS
  2. Open SharePoint Designer 2007
  3. Open your site (http://loclhost:100)
  4. Select File->New->Workflow menu command.
  5. For Name, type “Encrypt It”, select Shared Documents from the dropdown
  6. Click Next
  7. Click Actions, select the More Actions
  8. Click the dropdown for the Select a Category and choose “Encryption”
  9. In the Choose an Action box, select the “Encrypt a document/item” activity
  10. Click Add.
  11. Click on “this” option in the Action
  12. From the Choose List Item dialog box, select the “Current Item” option
  13. Click OK
  14. Click Finish

Task 7 – Run the workflow

  1. Add an item to the document library
  2. Right click the JavaScript dropdown, select workflows
  3. Click Encrypt It

Task 8 – Try to open the document

  1. Click the document, Word should fail to open it…it is encrypted!!!

Task 9 – Create a workflow to use the Decryption action

  1. In SharePoint Designer 2007, select File->New->Workflow menu command.
  2. For Name, type “Decrypt It”, select Shared Documents from the dropdown
  3. Click Next
  4. Click Actions, select the More Actions
  5. Click the dropdown for the Select a Category and choose “Encryption”
  6. In the Choose an Action box, select the “Decrypt a document/item” activity
  7. Click Add.
  8. Click on “this” option in the Action
  9. From the Choose List Item dialog box, select the “Current Item” option
  10. Click OK
  11. Click Finish

Task 10 – Run the workflow

  1. Add an item to the document library
  2. Right click the JavaScript dropdown, select workflows
  3. Click Decrypt It

Task 11 – Try to open the document

  1. Click the document, Word will open…it is decrypted!!!

Utilize Active Directory Provider in ASP.NET 2.0

You can use the System.Web.Security.ActiveDirectoryMembershipProvider class to do Membership against active directory!!!

However, you have to setup a special connection string to point to a domain controller and to run as a user to query LDAP.

I’ll be working with this a little bit later and will likely post the code for this project somewhere…

Here is more info on how to do this:

http://msdn2.microsoft.com/en-us/library/system.web.security.activedirectorymembershipprovider.aspx

How to Setup the Web Site Configuration WebSite outside VS.NET 2005

Here’s how to do it:

  • Copy all files in the C:WindowsMicrosoft.NETFrameworkv2.0.50727ASP.NETWebAdminFiles to a directory inside C:inetpubwwwroot (likely called Admin) – IGNORE the one that is in the inetpubwwwrootaspnet_webadmin…that is a bad copy!!!
  • Go into IIS, make the directory a web application, set it’s asp.net version to 2.0
  • The default.aspx page that normally loads expects the queryString variables of applicationPhysicalPath and applicationURL (as the web application is modifiying membership/roles/profile via the providers and the updating the web.config file of the web application you are pointing it at)!!!
  • You can set this statically in the default.aspx page and have it not care about the queryString variables
  • Then you would want to lock down the web with IIS authentication

Look for details on my codegen tool!

Every student and friend has seen my codegen tool, but few have got to use it.  I will be posting details of the tool here and reference the website when I implement a more 2.0 friendly codegen stack inside of it.  Look out CodeSmith!!

Coolest new things about BizTalk 2006

By far, the coolest things about BizTalk 2006 are:

  • Flat File Schema generator…wow…that thing is awesome!
  • Application containers in the BizTalk Admin Console…good job MS!
  • Bigger window to code custom C# code in orchestrations…woohoo!

There are a few others, but dang…those are some biggies!