18
Hands-On Lab Open XML Programming Lab version: 1.0.0 Last updated: 2/23/2011

Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Embed Size (px)

Citation preview

Page 1: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Hands-On Lab

Open XML Programming

Lab version: 1.0.0

Last updated: 2/23/2011

Page 2: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

CONTENTS

OVERVIEW ................................................................................................................................................... 3 Starting Materials 4

EXERCISE 1: AUTOMATING THE FINALIZATION OF AN OPEN XML DOCUMENT .............................. 4 Task 1 – Review the DocumentFinalization project .............................................................................. 4

Task 2 – Create and Register the event receiver .................................................................................. 5

Task 3 – Open and Save the file in SharePoint ...................................................................................... 8

Task 4 – Mark the document as finalized ........................................................................................... 11

Exercise 1 Verification ......................................................................................................................... 14

SUMMARY .................................................................................................................................................. 16

APPENDIX .................................................................................................................................................. 18 No Items 18

Page 3: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Overview

In this lab exercise, you will build a small add-in for Word 2010. You will make use of the data-binding

capabilities of WPF combined with the SharePoint Client API. You will make use of new C#/VB language

features to make calls into the object model easier.

Objectives

In this lab you will:

Learn to manipulate an OpenXML document using the Open XML SDK

Learn to build a SharePoint 2010 List Event Handler

System Requirements

This lab assumes that you have SharePoint Server installed in a test environment. For guidance on how

to setup SharePoint Server see http://msdn.microsoft.com/en-us/library/ee554869(office.14).aspx.

Note that any URL referred to in this lab must be adjusted for use with your local setup. You must have

the following items to complete this lab:

Microsoft® Windows® Vista SP1 or Microsoft® Windows Server 2008 (64-bit)

Microsoft® SharePoint Server 2010 (64-bit)

Microsoft® Office Professional Plus 2010 (32-bit or 64-bit)

Microsoft® Visual Studio 2010

Setup

You must perform the following steps to prepare your computer for this lab. This consists primarily of

creating a SharePoint site collection at http://intranet.contoso.com/sites/OpenXML and installing the

code snippets for this lab.

1. Run the command file Setup.bat located at

C:\Office2010DeveloperTrainingKit\Labs\OpenXML\Source\.

Exercises

This Hands-On Lab is comprised of one exercise with the following tasks:

Page 4: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

1. Review the DocumentFinalization project

2. Create and register the event receiver

3. Open and Save the file in SharePoint

4. Mark the document as finalized

Estimated time to complete this lab: 45 minutes.

Starting Materials

This Hands-On Lab includes the following starting materials.

Visual Studio solutions. The lab provides the following Visual Studio solutions that you can use

as starting point for the exercises. The lab instructions assume that you installed the training kit

to the default location, C:\Office2010DeveloperTrainingKit\.

◦ C:\Office2010DeveloperTrainingKit\Labs\OpenXML\Source\[language]\Starter\Docu

mentFinalization.sln: Use the Open XML SDK to update the finalization state of a

document when its list property of Published State is set to Published.

Note: Inside the lab’s Source folder, you will find a Solution folder containing an end solution

with the completed lab exercise.

Exercise 1: Automating the Finalization

of an Open XML Document

In this exercise you will create a SharePoint event handler that will automatically mark an Open XML

document as finalized when its status has changed to completed. This is a common practice in the final

steps of a workflow or other process that is intended to move the document through a specific lifecycle.

Task 1 – Review the DocumentFinalization project

In this task, open the DocumentFinalization project that already contains a content type, site column

and document library definition. Become familiar with the structure of the solution provided as a

starting point.

1. Open Visual Studio 2010 and open the project at

C:\Office2010DeveloperTrainingKit\Labs\OpenXML\Source\[language]\Starter\DocumentFin

alization.sln

2. Review the definition of the Publication content type

a. In the Solution Explorer, open the Elements.xml file in the Publication folder

Page 5: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

3. Review the definition of the PublicationLibrary list template

a. In the Solution Explorer, open the Schema.xml file

b. Review the markup and see the ContentType node containing the reference to the

Publication content type

Task 2 – Create and Register the event receiver

In this task, you will create a new event receiver and add markup to the content type to associate the

event handler you created to the existing Publication content type.

1. Add a new PublicationEventReceiver class to the Publication content type

a. Right click the Publication item in the Solution Explorer and click Add -> Class

b. Name the class PublicationEventReceiver.vb(in case of VB) &

PublicationEventReceiver.vb(in case of C#) and click Add

2. Add the markup to the content type Elements.xml file to connect the content type with the

event handler

a. In the Solution Explorer, open the Elements.xml file in the Publication folder

b. At the end of the file, immediately following the close FieldRefs node, add the

following markup

Note: The line breaks in the bold lines below exist to make the line fit on the printed

page. When placing them into Visual Studio 2010, make sure there are no line feeds

and the entire value is on one line.

XML

<XmlDocuments>

<XmlDocument NamespaceURI="http://schemas.microsoft.com/

sharepoint/events">

<spe:Receivers xmlns:spe="http://schemas.microsoft.com/sharepoint/

events">

<Receiver>

<Name>Publication Item Added</Name>

<Type>ItemAdded</Type>

<SequenceNumber>1</SequenceNumber>

<Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>

<Class>DocumentFinalization.Publication.

PublicationEventReceiver</Class>

<Data />

<Filter />

</Receiver>

<Receiver>

<Name>Publication Item Updated</Name>

Page 6: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

<Type>ItemUpdated</Type>

<SequenceNumber>1</SequenceNumber>

<Assembly>$SharePoint.Project.AssemblyFullName$</Assembly>

<Class>DocumentFinalization.Publication.

PublicationEventReceiver</Class>

<Data />

<Filter />

</Receiver>

</spe:Receivers>

</XmlDocument>

</XmlDocuments>

3. Implement the SPItemEventReceiver class

a. Add the following using statements to the new PublicationEventReceiver.vb(in case

of VB) & PublicationEventReceiver.vb(in case of C#)

C#

using Microsoft.SharePoint;

Visual Basic

Imports Microsoft.SharePoint

b. Update the class definition so PublicationEventReceiver derives from

SPItemEventReceiver and that the class is public

C#

public class PublicationEventReceiver

: SPItemEventReceiver

{

Visual Basic

Public Class PublicationEventReceiver

Inherits SPItemEventReceiver

4. Add a TryFinalizeDocument method to call the finalization code if the PublicationStatus of the

document is Published

a. Add a PublicationStatus static field to the PublicationEventReceiver class

C#

public class PublicationEventReceiver

: SPItemEventReceiver

{

static Guid PublicationStatus =

new Guid("{31B7D719-0D60-470B-B637-D71507CA20B5}");

Page 7: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Visual Basic

Public Class PublicationEventReceiver

Inherits SPItemEventReceiver

Private Shared PublicationStatus As New Guid("{31B7D719-0D60-

470B-B637-D71507CA20B5}")

b. Create a new method TryFinalizeDocument

C#

void TryFinalizeDocument(SPItemEventProperties properties)

{

}

Visual Basic

Private Sub TryFinalizeDocument(ByVal properties As

SPItemEventProperties)

End Sub

c. Use the properties.ListItem object to check the value of the PublicationStatus field

in the TryFinalizeDocument method

C#

string status = (string)properties.ListItem[PublicationStatus];

if (status == "Published")

FinalizeDocument(properties.ListItem);

Visual Basic

Dim status As String = CStr(properties.ListItem(PublicationStatus))

If status = "Published" Then

FinalizeDocument(properties.ListItem)

End If

d. Override the ItemAdded and ItemUpdated methods and have them call

TryFinalizeDocument

C#

public override void ItemAdded(SPItemEventProperties properties)

{

TryFinalizeDocument(properties);

}

public override void ItemUpdated(SPItemEventProperties properties)

{

TryFinalizeDocument(properties);

}

Page 8: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Visual Basic

Public Overrides Sub ItemAdded(ByVal properties As

SPItemEventProperties)

TryFinalizeDocument(properties)

End Sub

Public Overrides Sub ItemUpdated(ByVal properties As

SPItemEventProperties)

TryFinalizeDocument(properties)

End Sub

Task 3 – Open and Save the file in SharePoint

In this task, you will add code to the event handler that opens a file in SharePoint and manipulates its

contents.

1. Add a reference to the Open XML SDK and add the necessary namespaces to the event receiver

a. In the Solution Explorer, right click DocumentFinalization and choose Add

Reference

b. Locate DocumentFormat.OpenXml in the .NET tab, select it, and click OK

c. Add the following using statements to PublicationEventReceiver.vb(in case of VB) &

PublicationEventReceiver.vb(in case of C#)

C#

using System.Xml;

using System.Xml.Linq;

using DocumentFormat.OpenXml.Packaging;

using System.IO;

Visual Basic

Imports System.Xml

Imports System.Xml.Linq

Imports DocumentFormat.OpenXml.Packaging

Imports System.IO

d. Add two OpenXML namespaces to the PublicationEventReceiver as static fields

Note: The line breaks in the bold lines below exist to make the line fit on the printed

page. When placing them into Visual Studio 2010, make sure there are no line feeds

and the entire value is on one line.

C#

public class PublicationEventReceiver

: SPItemEventReceiver

Page 9: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

{

static Guid PublicationStatus =

new Guid("{31B7D719-0D60-470B-B637-D71507CA20B5}");

static XNamespace XMLNS_CP =

"http://schemas.openxmlformats.org/officeDocument

/2006/custom-properties";

static XNamespace XMLNS_VT =

"http://schemas.openxmlformats.org/officeDocument

/2006/docPropsVTypes";

Visual Basic

Public Class PublicationEventReceiver

Inherits SPItemEventReceiver

Private Shared PublicationStatus As New Guid("{31B7D719-0D60-

470B-B637-D71507CA20B5}")

Private Shared XMLNS_CP As XNamespace =

"http://schemas.openxmlformats.org/officeDocument /2006/custom-

properties"

Private Shared XMLNS_VT As XNamespace =

"http://schemas.openxmlformats.org/officeDocument /2006/docPropsVTypes"

2. Implement the FinalizeDocument method

a. Create a new FinalizeDocument method

C#

void FinalizeDocument(SPListItem item)

{

}

Visual Basic

Private Sub FinalizeDocument(ByVal item As SPListItem)

End Sub

b. Use the following code in the FinalizeDocument method to guarantee our changes

to the document don’t cause infinite loops

C#

try

{

EventFiringEnabled = false;

}

finally

{

EventFiringEnabled = false;

}

Page 10: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Visual Basic

Try

EventFiringEnabled = False

Finally

EventFiringEnabled = False

End Try

3. Locate the updated file and load it using the Open XML SDK

a. Inside the try block following the EventFiringEnable line, create a new

MemoryStream to hold the file

b. Use the stream.Write and the item.File property to load the file into the stream

c. Load the stream using the WordprocessingDocument and call the MarkAsFinal

method

d. Use the SPFile object’s SaveBinary method to save the changes back to SharePoint

C#

EventFiringEnabled = false;

using (MemoryStream stream = new MemoryStream())

{

stream.Write(item.File.OpenBinary(), 0, (int)item.File.Length);

using (WordprocessingDocument document =

WordprocessingDocument.Open(stream, true))

MarkAsFinal(document);

item.File.SaveBinary(stream);

}

Visual Basic

EventFiringEnabled = False

Using stream As New MemoryStream()

stream.Write(item.File.OpenBinary(), 0,

CInt(Fix(item.File.Length)))

Using document As WordprocessingDocument =

WordprocessingDocument.Open(stream, True)

MarkAsFinal(document)

End Using

item.File.SaveBinary(stream)

End Using

Page 11: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Task 4 – Mark the document as finalized

In this task, you will use the Open XML SDK to access the _MarkAsFinal property in the document and

set it to true. If it does not exist, you will create it.

1. Implement the MarkAsFinal method that will use the WordprocessingdDocument object to

access the custom file properties and set the _MarkAsFinal property to true

a. Create a new MarkAsFinal method

C#

static void MarkAsFinal(WordprocessingDocument document)

{

}

Visual Basic

Shared Sub MarkAsFinal(ByVal document As WordprocessingDocument)

End Sub

b. Steps b-e build up the code in the MarkAsFinal method. Use the document

parameter to retrieve the CustomFilePropertiesPart object

C#

CustomFilePropertiesPart propertiesPart =

document.GetPartsOfType<CustomFilePropertiesPart>().First();

Visual Basic

Dim propertiesPart As CustomFilePropertiesPart =

document.GetPartsOfType(Of CustomFilePropertiesPart)().First()

c. Load the contents of the part into an XDocument

C#

XDocument properties = null;

using (XmlReader reader = XmlReader.Create(propertiesPart.GetStream()))

properties = XDocument.Load(reader);

Visual Basic

Dim properties As XDocument = Nothing

Using reader As XmlReader = XmlReader.Create(propertiesPart.GetStream())

properties = XDocument.Load(reader)

End Using

d. Call the SetPropertyValue method to set the _MarkAsFinal property to true

C#

Page 12: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

SetPropertyValue(properties, "_MarkAsFinal", true);

Visual Basic

SetPropertyValue(properties, "_MarkAsFinal", True)

e. Write the contents of the XDocument back into the CustomFilePropertiesPart

C#

using (XmlWriter writer = XmlWriter.Create(

propertiesPart.GetStream(FileMode.Create,

FileAccess.ReadWrite)))

properties.WriteTo(writer);

Visual Basic

Using writer As XmlWriter =

XmlWriter.Create(propertiesPart.GetStream(FileMode.Create,

FileAccess.ReadWrite))

properties.WriteTo(writer)

End Using

2. Use XLinq to find the _MarkAsFinal property. If it exists, set it to true. If not create it and set it

to true.

a. Create a new SetPropertyValue method

C#

static void SetPropertyValue(XDocument properties,

string propertyName, bool value)

{

}

Visual Basic

Shared Sub SetPropertyValue(ByVal properties As XDocument, ByVal

propertyName As String, ByVal value As Boolean)

End Sub

b. Steps b-d build up the code in the SetPropertyValue method. Use the properties

parameter to find the property with a specific name

C#

XElement property = properties.Descendants(XMLNS_CP + "property")

.FirstOrDefault(xe => xe.Attribute("name").Value == propertyName);

Visual Basic

Page 13: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Dim [property] As XElement = properties.Descendants(XMLNS_CP &

"property").FirstOrDefault(Function(xe) xe.Attribute("name").Value =

propertyName)

c. If the property found is null, create a new property. To find the id of the new

property find the max current property id and add 1

C#

if (property == null)

{

int maxPropertyId = properties.Descendants(XMLNS_CP + "property")

.Select(xe => Int32.Parse(xe.Attribute("pid").Value)).Max();

property = new XElement(XMLNS_CP + "property",

new XAttribute("fmtid",

"{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"),

new XAttribute("pid", maxPropertyId + 1),

new XAttribute("name", "_MarkAsFinal"));

properties.Root.Add(property);

}

Visual Basic

If property Is Nothing Then

Dim maxPropertyId As Integer = properties.Descendants(XMLNS_CP &

"property").Select(Function(xe)

Int32.Parse(xe.Attribute("pid").Value)).Max()

property = New XElement(XMLNS_CP & "property", New

XAttribute("fmtid", "{D5CDD505-2E9C-101B-9397-08002B2CF9AE}"),

New XAttribute("pid", maxPropertyId + 1), New XAttribute("name",

"_MarkAsFinal"))

properties.Root.Add(property)

End If

d. Whether the property was found initially or added, set its value to true

C#

property.SetElementValue(XMLNS_VT + "bool", value);

Visual Basic

property.SetElementValue(XMLNS_VT & "bool", value)

Page 14: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

3. Deploy the solution by right clicking DocumentFinalization in the Solution Explorer and clicking

Deploy

Exercise 1 Verification

In order to verify that you have correctly performed all steps of exercise 1, proceed as follows:

Test the Event Handler

Test your event handler you will need to create a new document library in the SharePoint site based on

the Publication Library template. Now add a document to the document library and set its Publication

Status to Published. This will cause the content type event handler to execute and mark the document

as finalized.

1. Create a new document library named Shared Documents using the Publication Library

template

a. In Internet Explorer navigate to http://intranet.contoso.com/sites/OpenXML

b. Click Site Actions and View All Site Content link on the left hand side navigation menu

c. At the top of the page click the Create button

Figure 1

Create Share Documents Library

d. In the Create dialog, filter by Library and choose the Publication Library option

e. Enter a name of Shared Documents and click Create

2. Add a new document to the Shared Documents document library

Page 15: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

a. In the Documents ribbon click the New Document button

Figure 2

Create New Document

b. When Word 2010 loads save the document to the new Shared Document library

c. Close Word 2010

d. Back in Internet Explorer, refresh the page

e. Click the drop down menu on the new document and select Edit Properties

Figure 3

Editing Item Properties

f. Change the Publish Status to Published and click Save

Page 16: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Figure 4

Change the Publication Status

g. Click the drop down menu on the new document and select Edit in Microsoft Word

h. Once the document is loaded verify it has been finalized

Figure 5

Finalized Word Document

Summary

Page 17: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

In this exercise you used the Open XML SDK and a SharePoint content type event receiver to automate

the process of finalizing a docx file. By performing this automation the need to synchronize a status

value in SharePoint with the finalization state of the document was eliminated automating a process

that was previously manual.

Page 18: Open XML Programming Lab - az12722.vo.msecnd.netaz12722.vo.msecnd.net/.../labs/openxmllab3-0-0/Lab.pdf · Add the markup to the content type Elements.xml ... immediately following

Appendix

No Items

No Appendix content