Post on 08-Feb-2018
transcript
Hands-On Lab
Open XML Programming
Lab version: 1.0.0
Last updated: 2/23/2011
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
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:
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
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>
<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}");
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);
}
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
{
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;
}
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
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#
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
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)
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
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
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
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.
Appendix
No Items
No Appendix content