SharePoint Development from a Documentation Perspective

Andrew May

July, 2004

  • Andrew May's WebLog

    OneNote Import Managed Assembly: The Quick Rundown (2 of 2)

    • 2 Comments

    In part one, we discussed how to use the OneNote managed class assembly to import content into OneNote. Now let’s actually look at the XML the Page class generates for the SimpleImporter.Import method.

    Looking at the XML

    If you want to preview what the XML that’s passed to the SimpleImport.Import method will look like before you run the Commit method, call the Page.ToString method. This is the method that actually serializes the page and its contents to XML prior to importing. Just remember that once you’ve committed a page, none of the object on that page will be included in the generated import XML, unless they’ve subsequently been modified in some way.

    Also remember that the Commit method generates import XML with both <EnsurePage> and <PlaceObjects> elements for that page. Specifying an <EnsurePage> element for a page guarantees that the page exists before OneNote attempts to import objects onto it. So if your application includes a scenario where you only want to import objects onto a page if the page already exists, you’ll need to modify this method, or use another means.

    So let’s a quick look at the code sample Donovan gives over on his blog (I think he’ll forgive me if I rewrite it in VB). This sample creates a new page, title “General”, with one object on that page: an outline containing the text “Hello world!”

    Sub TrivialImportVB()

       Dim p As New Page("General")

       Dim outline As New OutlineObject

       outline.AddContent(New HtmlContent("Hello <i>world</i>!"))

       p.AddObject(outline)

       p.Commit()

       p.NavigateTo()

    End Sub

    And here’s the resulting XML that gets passed to the SimpleImport.Import method. Notice that the necessary GUIDs are there, and the HTML has even been cleaned up so that OneNote accepts it with no problem. How’s that for service?

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

    <Import xmlns="http://schemas.microsoft.com/office/onenote/01/2004/import">

          <EnsurePage path="General" guid="{e5bf863a-7070-4058-a0f5-

    343e4a45dc05}" date="2004-07-23T09:52:17.0963010-07:00" />

          <PlaceObjects pagePath="General" pageGuid="{e5bf863a-7070-4058-a0f5-

          343e4a45dc05}">

                <Object guid="{a5af80e4-8105-4109-b3ac-538851e9e3fa}">

                      <Position x="36" y="36" />

                      <Outline>

                                  <Html><Data><![CDATA[<html><body>Hello

    <i>world</>!</body></html>]]></Data></Html>

                      </Outline>

                </Object>

          </PlaceObjects>

    </Import>

    Object Model Diagrams

    And what’s an object model without an object model map? Anyone who’s read this blog has probably realized how fond I am of presenting technical information graphically (which I’m sure has nothing to do with my being the programmer-writer for PowerPoint and Publisher.) So here are some diagrams of how the classes fit together. But first, some caveats:

    The following diagrams show only the public members of each class. None of the abstract classes are diagramed, and I’ve left any inheritance information off the diagrams, although I’ve listed any members that a class inherits in the individual classes themselves. For example, ImageObject, InkObject, and OutlineObject all inherit the Height, Position, and Width properties from the abstract class PageObject, which is not diagrammed.

    I mainly want to show how the various object relate to one another. For the most part, if a member gets or sets a data type, I haven’t bothered showing that in the diagram. In addition, for the sake of clarity, I’ve left off the following information for basic methods that most classes here have:

    ·         The Clone method returns the type of object from which you call it.

    ·         The Equals method takes a System.Object as a parameter.

    ·         The GetHashCode method returns a System.Int32 suitable for use in hashing algorithms and data structures like a hash table.

    Trust me, I’ve got much more detailed diagrams of the internal workings of each class tacked up around my office, and those will most likely make it into the finished article, which discusses the class source code. But these should give you a good at-a-glance idea of how things flow.

     

    Figure 1. Page object (and legend)

     

    Figure 2. ImageObject, InkObject, and OutlineObject

     

    Figure 3. HtmlContent, ImageContent, and InkContent

  • Andrew May's WebLog

    OneNote Import Managed Assembly: The Quick Rundown (1 of 2)

    • 4 Comments

    If you haven’t already seen this, get over to Donovan Lange’s blog. Donovan, Omar, and David have put together an abstracted managed assembly that provides an object model for the SimpleImport functionality OneNote added for SP1. That’s right; you don’t even have to create the XML for the import yourself. The OneNote guys have you covered.

    I’m currently putting together an article that highlights this class library and all the functionality it provides. I’ve been pouring over the code for the last week or so, and I think I’ve finally got it. (The assembly itself is written in C#. Did I mention I’m about as fluent in C# as in ancient Armenian?) I have to say, this is some very well-thought-out work.

    The OneNote guys have included detailed technical documentation in the download itself, but I thought it might be worth taking a few minutes and putting together a high-level overview of how the classes work. So if you just want to get up and running, and aren’t too concerned about how the assembly does what it does so well, then read on.

    I’m going to assume you have a passing familiarity with the OneNote SimpleImport class and the xml schema it uses. (If you don’t, follow the links and then come back. I’ll wait.)

    They’ve really made the class library easy to use. Here’s all you need to do:

    Create a new Page object

    Not much to say here. Once you’ve created the page, you can set its attributes using various properties such as Date, PreviousPage, RTL, SectionPath, and Title. The PreviousPage property sets the value of the ‘InsertAfter’ XML attribute; the others are pretty self-explanatory.

    Create the content you want to add to your new page

    There are three types of objects you can add to a page: ImageObject, InkObject, or OutlineObject objects. All page objects share common properties, such as Height, Width, and Position.

    Note While the OutlineObject inherits the Height property from its base class for consistency, outlines cannot have an explicitly specified height. Therefore, accessing or modifying the Height property of an OutlineObject will result in an error.

    Each ImageObject and InkObject contains data representing the actual image or ink content you want to add to the page. You get and set this data by using the ImageData and InkData properties, respectively.

    You use these properties to get or set a BinaryData or FileData object. The BinaryData class represents raw binary data in memory. When you add an ImageObject or InkObject object containing BinaryData to a page, the OneNote Import Managed Assembly ensures this data is properly base-64 encoded. The FileData class represents data that is stored in an external file, and is marshaled to OneNote as a file path.

    For the most part, you’ll really only need to create BinaryData and FileData objects directly when you want to update existing image or ink objects. The ImageObject and InkObject each provide convenience constructors that create the appropriate data object, when passed a System.IO.FileInfo object or binary array of bytes as a method parameter.

    OutlineObject objects are slightly more complex because outlines can be comprised of ImageContent, InkContent and HtmlContent objects. Add content to an OutlineObject using the AddContent method. Outline content objects are displayed within the outline in the same order in which they are added to the OutlineObject object.

    The ImageContent and InkContent classes are very similar to the ImageObject and InkObject classes. Again, the actual image or ink content is represented by either a BinaryData or FileData object. This object is also created based on the specified argument passed to the ImageContent or InkContent constructor, and you can subsequently access it using the ImageData or InkData property, respectively. Note that neither the ImageContent or InkContent classes contain properties for setting their position and size on the page, as these properties are set for the outline as a whole.

    The HtmlContent object also contains data within the HtmlData property, except it’s data is represented as either a FileData or StringData object. The StringData object represent string data as a System.String. Constructors on the HtmlContent object enable you to create a new HtmlContent object based off of pre-existing HTML in a string object or a FileInfo object containing the path to an HTML file.

    Add objects to the page

    Add the objects you’ve created to the Page object using the AddObject method. You can add as many as you want, in any order. How the objects are arranged on the page depends on the coordinates specified in the Position child object for each ImageObject, InkObject, or OutlineObject.

    Import the page

    Now that you’ve got your page set up with all your content, it’s time to import it into OneNote. You do this using the Page.Commit method. This method does several vital things, including:

    ·         Creates the XML document to be used for the OneNote SimpleImport class.

    ·         Specifies the correct OneNote namespace, based on whether the OneNote SP1 Preview or SP1 release version is installed on the current machine. (Now, how thoughtful is that?)

    ·         Adds an <EnsurePage> element for the page, using the Page object properties you’ve set.

    ·         If your page contains objects, then the method also creates a <PlaceObjects> element to insert, edit, or delete those objects as specified.

    ·         Serializes the page and all its contents to XML, and adds them to the XML import document. In the course of this, it also does some minor checking of any HTML content to format it property for OneNote.

    ·         Validates the XML it created, to make sure OneNote accepts it.

    ·         Calls the SimpleImporter class and imports the content into OneNote.

    Pretty slick, no?

    Here’s some things to keep in mind:

    Generating GUIDs

    The OneNote classes internally generate the necessary GUIDs that OneNote needs to identify each object and page. You cannot access a page or object’s GUID from outside the OneNote class assembly. The GUIDs do appear in the XML passed to the SimpleImporter.Import method, of course.

    On a sidenote, Donovan tells me he intends to change this. Originally, the intent was to hide the GUIDs for the benefit of new users. But it turns out that many scenerios require control over the Page and PageObject GUIDs. If you do need access to these GUIDs, here’s two strategies to consider:

    ·         Override the class, and make the GUID properties publicly accessible.

    ·         Serialize and persist the Page object between sessions, and then deserialize it as necessary.

    Re-Importing Objects

    Page objects keep track of whether they have been committed (or in other words, imported) and, additionally, keep track of modifications that require an update (that is, another import). So, after you commit a Page for the first time, if you then immediately call the Commit method again, none of the original objects would be re-imported. However, suppose that, after you commit a page, you then added new objects to that page, or changed the content or properties of an existing object on the page. In that case those new or modified objects will be re-imported the next time you execute the Commit method.

    The OneNote SimpleImport API does not permit you to change a page’s date, title, insertAfter, or RTL attributes once you’ve imported the page. Because of this, once you’ve called the Commit method for a Page object, the following Page properties become read-only and throw an exception if you try and set them: Date, PreviousPage, RTL, and Title.

    Deleting Objects

    You can delete an object from a page using the Page.DeleteObject method. Much like the Page.AddObject method, the deletion does not in fact occur until you execute  the Commit method; only then is it deleted within OneNote and removed as a child of the Page object.

    Next time, I'll include an example and we'll take a look at the XML actually produced.

  • Andrew May's WebLog

    Visio Update and PIA Issues

    • 0 Comments

    I received a question from a user the other day in regards to the samples contained in the Visio Managed Code Tutorial that shipped as part of the Visio 2003 SDK. Seems the user couldn’t compile the samples because Visual Studio couldn’t find the Microsoft.Office.Interop.Visio assembly. I suggested the user check and see if the Visio PIAs were actually installed, because they don’t always install by default (more on that later).

    Turns out there may be more to it than that. The Visio test team did some research, and it seems that one of the Visio Update patches actually disables the Visio Interop PIA. Here’s what the test team found:

    Installing the Microsoft Office Visio 2003 Update: KB831925 causes all the Tutorial samples to fail compiling. When you open the Tutorial samples in Visual Studio, Visual Studio fails to find the Visio Interop PIA. To fix this problem, open Visio 2003, and from the Help menu, choose Detect and Repair.

    Note: Just starting the Visio application does not launch a repair operation in this case.

    So even if you know you installed the PIAs previously, it might be a good idea to repair them via the method above if you’ve downloaded the update.

    (My thanks to Curt on the Visio test team for running this problem down. Great work, Curt.)

    This issue will be written up in the Knowledge Base, but since the user asked the question here, I figured I’d go ahead and answer it here.

    Here’s how Visio PIA installation usually works:

    If you install Visio on a computer that does not have Visual Studio 2003 (version 7.1) or the .Net Framework 1.1 installed, then Visio doesn’t install the PIAs. If Visual Studio or the .NET Framework is already present on your computer when you install Visio, then the Visio PIAs are installed by default.

    Do the following to have Visio explicitly install the PIAs:

    ·         From the Start menu, click Settings, click Control Panel, then Add or Remove Programs.

    ·         In the program list, select Microsoft Office Visio 2003, and click the Change button. Click Add or Remove Features, and then click Next.

    ·         Expand the Microsoft Office Visio icon and select .NET Programmability Support, and then click Update. You may want to try uninstalling this and then reinstalling to force it to install.

    One way to check to see if the PIAs are installed is to navigate to your windows directory in explorer, e.g.

    c:\windows\assembly

    c:\winnt\assembly\

    and see if you see the Visio PIAs for Visio version 11 in the list of assemblies. There are three PIAs for Visio. The primary one is Microsoft.Office.Interop.Visio.

    Note If you install an add-in when the Visio PIAs are not installed, you must re-install the add-in after you install the Interop PIA (in other words, just installing the PIAs is not enough to fix the add-in.)

Page 1 of 1 (3 items)