By dworthley on
7/1/2008 4:42 PM
Well, let's get into the details of creating a metaPost provider. You'll see in a few minutes that it's actually pretty easy.
If you've followed the steps in the previous post, then you have a Visual Studio project created and you're ready to start writing/changing some code.
IPublishable
Open the source code for your provider and you'll see that the code contains the following sections:

These were highlighted in the last post. If you expand the IPublishable Members section of the code, you'll see:
In order to implement a metaPost provider, you'll need to implement a few public properties (we'll cover those in a second) as well as procedures for things like getting posts as well as adding, editing and deleting posts. Finally, we may need to write some implementation for a few procedures related to working with categories. Let's start with the Public Properties, but before we briefly explain each property, let's talk about the MetaPostServices object. To make it as easy as possible to implement your provider, we've offloaded as much functionality as possible to a MetaPostServices helper object that contains shared methods for most of the public properties. This means that when you write your implementation for most of the properties, you can just offload the implementation to the shared methods of the MetaPostServices object. Of course, if you want to override this functionality, you're free to write your own custom code.
Implementation of Properties
- ProviderKey - Used to return the FriendlyName of your module. To retrieve this friendly name, simply pass in the Module Definition FriendlyName into the GetFriendlyNameFromModuleDefinition procedure as follows:
return MetaPostServices.GetFriendlyNameFromModuleDefinition("Announcements");
- ManifestFilePath - This is the path to the manifest file11 used by Windows Live Writer to determine the features of the Windows Live Writer that your module can use. See the following URL for information regarding what Content can be placed in a WLW manifest file1: http://msdn2.microsoft.com/en-us/library/bb463260.aspx. For the announcements provider, this property is set as follows:
get { return "/DesktopModules/itcMetaPost/manifests/wlwAnnouncements.xml"; }
- LocalizationFilePath - Returns the path to the localization file for the provider.
get { return "/DesktopModules/itcMetaPost/App_LocalResources/itcMetaPostAnnouncements"; }
- ImageUploadPath - This is the path to the location where the images files will be stored, and by images, we're referring to the images included in a post. Windows Live Writer will use the MetaWeblog API to save these images to the server.
return MetaPostServices.GetProviderImageUploadPath(ProviderKey);
- AttachmentUploadPath - Same as the ImageUploadPath only for files that are attached to the post. Note that in the current version of Windows Live Writer, this can only be done through the use of a custom Insert addin.
return MetaPostServices.GetProviderAttachmentUploadPath(ProviderKey);
- SettingsUserControlPath - Not currently used
That's it for the properties and you can see that in most cases, we'll just be making a few minor changes to the code. Also, a quick word here about the localization file and the manifest file1. It's best to start with the files for the provider you've chosen and change the file as needed. Copies of the localization files as well as the manifest files can be found in the SDK. Note also that if you chose to ship your provider with your module, then these two files will need to be included in dnn file for your module. You'll want to make sure the paths entered in the properties is consistent with the final destination of each file after they are installed. If you want your provider to be shipped with metaPost, we'll need a copy of the source code and/or the dll for your provider along with the manifest file1 and localization file.
Implementation of Methods
There, that wasn't so bad. Now, let's take a look at the methods that you may need to implement in order to allow metaPost to read and write content to your module.
However, before we take a look at the individual methods, let's take a quick look at some of the parameters you'll find in the methods listed below as well as some of the common properties of the item object you may find useful (the item object is one of the properties described below):
Common Method Parameters
- moduleLevelId - This is used to track different information depending on the module. For some modules, like the Text/HTML module, this may be the actual ModuleID, but for others, it may be a module specific ID. With the blog module provider, for example, the moduleLevelId is used to track the BlogId.
- itemId - The itemId is used to track the individual items that can be published. For the FAQs module, this would be the ID of an individual FAQ entry. For an articles module, this may be an articleId. For some modules, this string parameter may track more than one type of ID. See the News Articles provider for an example where articleIDs and pageIds are both tracked through the itemId field. The type of ID being tracked is differentiated by the string "aid" being prepended to the ID.
- userInfo - This is the actual DotNetNuke UserInfo object that's passed from the metaPost infrastructure into the IPublishable interface. This is where creating a metaPost provider can save you a lot of time over writing your own MetaWeblog API.
- portalSettings - This is the DotNetNuke PortalSettings object related to the portal to which the user is connecting to insert, update or delete data.
- providerKey - This is the unique key used to identify the metaPost providers. It will be equal to the Friendly name of your module. And by friendly name, we mean the name that will appear in the dropdown list of available modules in your portal.
- requestType - This parameter is used with the GetRecentItems method below to specify whether the GetRecentMethods procedure is being called to show a list of recent entries or to show a list of available parent items. The same procedure is used for both operations and since the code is often the same for both requests, we included the two in one procedure and differentiated the types of calls based on this parameter.
- item - This is the core of the IPublishable interface. The item represents the object being published and this struct contains all of the properties needed by the metaPost infrastructure to communicate with publishing clients when publishing content. You may want to take a few minutes to view this object using an object browser in Visual Studio.
- itemType - Where it's appropriate, we pass the itemType in as a property of the item object. However, some methods don't take an item object as a parameter. This is the case with the GetItem and DeleteItem methods. With these methods, an itemType parameter is passed to let you know whether you're dealing with a page or a post. The IPublishable interface is designed to support both concepts which are available in Windows Live Writer if the manifest file1 used for your provider supports these features. You'll recall that the manifest file1 is an xml configuration file used by Windows Live Writer to specify which features of Live Writer are needed by your module. A good example of a provider which uses the page feature of Windows Live Writer is the Ventrian News Articles provider. With this provider, you can use Windows Live Writer to manage both pages and posts.
In addition, you'll find it helpful to be familiar with the properties of the item object. We'll start with the properties that convey information to the NewItem and EditItem procedures which you may find useful in writing the implementation.
Useful Item Properties
- Item.Publish - Determines whether the user chose to publish the entry or just save as a draft.
- Item.ItemType - Used to determine if the item is a post or a page.
- Item.ItemId - Used to track the ItemId of the entry. This is important for the EditItem method.
- Item.StyleDetectionPost - Used to track whether the post is being created as a result of the style detection process used by Windows Live Writer.
- Item.StyleId - For some modules, style detection is more difficult since some modules don't support creating new content. This is the case with the Text/HTML module which only supports editing existing Text/HTML modules and does not support adding new modules. In these cases, users are able to pass in a special parameter to the posting URL through the QueryString, the sid parameter (short for style ID). In the case of the Text/HTML provider, the style id passed in is the ModuleID of the Text/HTML module being used for style detection.
Additional Item Properties
Item.AllowComments - This property is useful if you have enabled the comments policy option in the manifest file1 by setting the value of supportsCommentPolicy to Yes. If set to Yes, then this property will contain a value of 0, 1 or 2 depending on whether the user chose none, open, or closed respectively. Closed (2) means that existing comments are shown, but no new comments are allowed. - Item.AllowTrackbacksOrPings - Same as AllowComments; however, only two values are allowed: allow (1) and deny(0).
- Item.AuthorId - Option. Used to track a unique identifier for the module of the entry.
- Item.Categories - A string array of categories associated with the entry.
- Item.Content - The actual content of the entry. It should be noted that in some cases, this will contain the summary. This is the case if extended entries are allowed (split posts), and this is determined by value stored in supportsExtendedEntries in the Windows Live Writer manifest file1.
- Item.DateCreated - The created date in UTC of the entry.
- Item.ExtendedContent - Content passed from Windows Live Writer when supportsExtendedEntries is set to Yes in the manifest file1.
- Item.ItemPassword - The password required to view the entry when supportsPassword is set to Yes in the Windows Live Writer manifest file1.
- Item.Keywords - The keywords passed from Windows Live Writer when supportsKeywords is set to Yes.
- Item.Link - The URL to where the entry can be viewed. In many cases, this is the same as the permalink, but it can also be the URL to a page which lists recent entries.
- Item.ModuleTitle - The title of the module which contains the post. For most providers, this property is ignored and is never set.
- Item.PageOrder - This property contains the PageOrder when paging is allowed by the client. In Windows Live Writer, users are allowed to enter the PageOrder for pages when supportsPageOrder is set to Yes in the manifest file1.
- Item.ParentId - This property contains the ID of the page's parent if this feature is supported by the publishing client. This value can be managed through Windows Live Writer if the value of supportsPageParent in the manifest file1 is set to Yes.
- Item.Permalink - The permanent URL for the entry.
- Item.PingUrls - A String array of trackback URLs may be passed by some clients. Windows Live Writer allows passing trackback URLs when supportsTrackbacks is set to Yes in the manifest file1.
- Item.Publish - Set to true or false depending on whether the item should be published (true) or saved as a draft (false)
- Item.SeoFriendlyTitle - Often referred to as the SLUG, the SeoFriendlyTitle is used to keep track of a SLUG associated with the entry. In Windows Live Writer, this is enabled or disabled through the supportsSlug tag in the manifest file1.
- Item.StartDate - In Windows Live Writer, users are able to specify a custom date based on the value of the supportsCustomDate tag in the manifest file1.
- Item.Summary - The summary is only visible in Windows Live Writer if the supportsExcerpt tag is set to Yes. We encourage provider developers to set supportsExcerpt to No and to encourage their users to make use of the split post feature which saves the content in either the Content field, or the ExtendedContent field. Note that when split post is used, the content is actually stored in the ExtendedContent field and the Content contains the summary.
- Item.Title - The title of the entry.
Get Methods
The first set of methods are the get methods.
- GetModulesForUser - This method is called by Windows Live Writer and other clients during account creation. The purpose of this method is to return a list of the modules to which the currently logged on user has access. For some modules, there may be only one item to return, since there may be only one module instance that is permitted per portal. This is the case, for example, with the Text/HTML provider. The Text/HTML provider allows a user to access any of the Text/HTML modules in a portal to which they have edit access. In this case, GetModulesForUser simply returns the name of the portal. However, for most other modules, there may be one or more instances of the module that the user may want to use. If this is the case, then the user needs will be shown a dropdown list during account creation which will allow them to pick the instance they want to use for that account. An example might be the News Articles module. There may be several instances of the News Articles module in a portal and when this is the case, the user is presented with a dropdown list during the creation of, say, a Windows Live Writer account which shows the list of all instances of News Articles in the portal that the currently logged on user has the privileges to use. For modules which rely on the simply DotNetNuke edit permissions, this implementation is easy:
return MetaPostServices.GetModuleInfo(providerKey, userInfo.UserID, portalSettings.PortalId);
For modules that use custom security settings, custom code needs to be written. If custom code is written, what needs to be returned form this method is an array of ModuleInfoStruct objects. You can look this up in an object browser, but it's a simple struct with just 3 properties: ModuleId, ModuleName and Url, where Url is the URL where the user will be redirected after inserting or editing an entry (Unless overridden by using MetaPostServices.SetTempInstallUrl2 which takes a string parameter for the URL).
- GetRecentItems - Get recent items is called from clients like Windows Live Writer for a couple of reasons: to show a list of the recent entries for opening and editing the item and to show a list of items for assigning a parent item (available only in modules which support parent child relationships between items). The parameters use by GetRecentItems are described in the Parameters section, but one parameter, numberOfItems, is not included in this list. numberOfItems is used when GetRecentItems is called from interfaces such as the Open dialog in Windows Live Writer. In this interface, the user can choose the number of items they want to see. It's a good idea to honor this so you provide the user with a way to retrieve as many or as few items as they wish.
Useful Services - A useful service when implementing this method is MetaPostServices.GetModuleIdByTabModuleId which takes a TabModuleId and returns a ModuleId. For many providers, such as the metaPost provider for the DNN FAQs module, will use the TabModuleId as the moduleLevelId. For the FAQs module, this is an important choice since a particular module may be shown on many tabs; and if we use the TabModuleId, then we'll need access to the ModuleId for performing updates or retrieving data.
- GetItem - GetItem is the first method which uses the itemId parameter as well as the itemType parameter. See the parameters section for more details regarding these to parameters. The purpose of this module is to retrieve an actual item from your module, normally for editing inside of the offline client.
Add, Edit and Delete Methods
The following methods allow you to add, edit and delete content in your module.
- NewItem - This method contains an item parameter as well as an itemType parameter along with the usual userInfo and portalSettings parameters. Together, this provides you with the information you need in order to determine what needs to be done to create a new entry based on the item passed in. If your provider supports both posts and pages, then the itemType will help you add the necessary code to distinguish between adding posts and pages. A great example of this is the News Articles module.
Required Services - There are two required services that need to be called from within the NewItem method. If you use an existing provider, these will already be in the method. If not, then you'll want to start your method with the following call:
C# List<string> images = MetaPostServices.GetImageListFromItem(ref item);
VB Dim images As List(Of String) = MetaPostServices.GetImageListFromItem(item)
and end your method with the following related call:
C# MetaPostServices.SaveItemImages(newItemId, images, ProviderKey, portalSettings, userInfo.UserID);
VB MetaPostServices.SaveItemImages(newItemId, images, ProviderKey, portalSettings, userInfo.UserID)
where newItemId is the new ID of the item just created.
- EditItem - EditItem is called by the publishing client when an existing item is being re-published. With Windows Live Writer, this will occur any time after the entry has been published for the first time or an initial draft has been saved on the server. A few of the properties described in the properties section are useful in writing the implementation for this procedure. The Publish property and the ItemType property will let tell you whether the entry should be saved as a draft or published as well as whether the entry is a post or a page that needs to be associated with a parent post. Also, as noted in the properties section, you'll need to decide on how the manifest file1 is configured. This will determine the features allowed in Windows Live Writer. An important feature is determined by the supportsExtendedEntries tag in the manifest file1. This tag determines whether content providers will be able to use the split post feature to manage easily add a summary to the post. supportsExtendedEntries is preferred over setting supportsExcerpt to Yes, since values entered in the Excerpt in Windows Live Writer are text only.
Required Services - Same as NewItem above
- DeleteItem - Delete item is usually fairly easy to implement. The itemId is passed into this procedure along with the normal userInfo and portalSettings. DeleteItem also has a itemType parameter which can be used to determine whether the post is a page or a post, depending on whether or not pages are supported in your client. Again, in Windows Live Writer, page support is determined by the supportsPages tag in the manifest file1.
Category Related Methods
- GetCategories - GetCategories returns an array of ItemCategoryInfo objects. Not all the properties of the ItemCategoryInfo objects need to be set. The fields of the ItemCategoryInfo object are: CatogoryId (int), CategoryName(string), Description (string), HtmlUrl(string), ParentId(int) and RssUrl(string). Note that the ParentId property allows for hierarchical categories, but if you're using Windows Live Writer as the publishing client, note that supportsHierarchicalCategories and supportsCategories need to be set to Yes. Note also that if you want to allow users to enter more than one category, then supportsMultipleCategories needs to be set to Yes in the manifest file. Finally, for metaPost to work properly, you'll need to set supportsCategoriesInline to Yes, since metaPost currently only supports the ability to set categories inline.
- NewCategory - This feature is only available if supportsNewCategories or supportsNewCategoriesInline are set in the manifest file for Windows Live Writer. It is used to add new categories from within Windows Live Writer. As of the time of writing this initial draft of the SDK no metaPost provider makes use of this feature.
- SetItemCategories - SetItemCategories was also added to support changes in Windows Live Writer regarding how hierarchical categories are managed. In releases of Windows Live Writer up to an include an of the 12.** releases, Windows Live Writer passed the categories inline through a string array of category names. The Windows Live Writer team realized that this didn't always work with hierarchical categories, since it was not uncommon for two categories to have the same name within a hierarchy. SetItemCategories takes an ItemId, an array of ItemCategory structs, a UserInfo object and a PortalSettings object. The ItemCategory struct contains two string properties for CategoryId and CategoryName as well as a bool property called IsPrimary which can be used to specify a single category that has been marked as the primary category.
- GetItemCategories - GetItemCategories was also added to support changes in Windows Live Writer regarding how hierarchical categories are managed. If your provider will make use of hierarchical categories, then you'll need to implement GetItemCategories, which takes an ItemId, a UserInfo object and a PortalSettings object and returns an array of ItemCategory structs.
In addition to supporting IPublishable, metaPost also supports two other interfaces: ILinkable and IWrappable. ILinkable can be implemented to provide support for built in Trackback and Pingback features available in the metaPost publishing engine and IWrappable can be implemented to provide support for headers and footers which your module may support. Note that the custom footer supported by IWrappable is in addition to a footer that can be added by the metaPost infrastructure to any provider. IWrappable is intended to be implemented when a footer that is maintained by a custom module needs to be included in the content of a post.
We'll be creating a demonstration video to show how to implement a sample provider, but until then, feel to contact us regarding any issues you face while creating your metaPost provider. Our goal is to make it as easy as possible for you to add offline editing support to your module.
Thanks for using metaPost!
1
An example manifest file.
The manifest file is used to specify which options should be available in Windows Live Writer for your provider. You'll need to include a manifest file with your provider and the path to the manifest file should be specified in the ManifestFilePath public property. See the Public Properties section for more details.
<?xml version="1.0" encoding="utf-8" ?>
<manifest xmlns="http://schemas.microsoft.com/wlw/manifest/weblog">
<options>
<clientType>WordPress</clientType>
<supportsMultipleCategories>Yes</supportsMultipleCategories>
<supportsCategories>Yes</supportsCategories>
<supportsCustomDate>Yes</supportsCustomDate>
<supportsKeywords>No</supportsKeywords>
<supportsTrackbacks>No</supportsTrackbacks>
<supportsEmbeds>No</supportsEmbeds>
<supportsAuthor>No</supportsAuthor>
<supportsExcerpt>Yes</supportsExcerpt>
<supportsPassword>No</supportsPassword>
<supportsPages>Yes</supportsPages>
<supportsPageParent>Yes</supportsPageParent>
<supportsPageOrder>Yes</supportsPageOrder>
<supportsExtendedEntries>Yes</supportsExtendedEntries>
<supportsCommentPolicy>No</supportsCommentPolicy>
<supportsPingPolicy>No</supportsPingPolicy>
<supportsPostAsDraft>Yes</supportsPostAsDraft>
<supportsFileUpload>Yes</supportsFileUpload>
<supportsSlug>No</supportsSlug>
<supportsHierarchicalCategories>Yes</supportsHierarchicalCategories>
<supportsCategoriesInline>Yes</supportsCategoriesInline>
<supportsNewCategories>No</supportsNewCategories>
<supportsNewCategoriesInline>No</supportsNewCategoriesInline>
</options>
</manifest>
2
See the NewItem and EditItem methods in the Text/HTML provider for an example of using SetTempInstallUrl for an example of redirecting to a custom URL after an insert or an update