asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search





Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Programming for the Palm Part 2 - The Synchronization Process
By Robert Chartier
Rating: 4.2 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Introduction


    This article will show how to establish a connection with the Palm synchronization process in order to upload the Palm Blog application data to various upload destinations.

    If you recall in the first part, I indicated that we will have three main methods for uploading data, WebLogApi, Ftp, and Http. For simplicity sake, I will only cover the WebLogApi method in this article. You can easily adapt my solution to suit your needs for the other two methods, or even add your own methods to the project.

    The synchronization process is fairly simple to understand. You have the Palm itself, which is connected to your PC or Laptop via a cable. On the computer you have the HotSync Manager running (it should be located in your system tray), and you have "Conduits", which are essentially plug-ins for the Manager which allow us to control the synchronization process for our specific application.

    In part one, I explained the "Creator ID", a unique ID representing our application and databases. During the synchronization process the HotSync Manager needs to determine which conduit it needs to call in order to handle the incoming data. This decision is based on the Creator ID. Since we used the Creator ID of "PBlg" in our application, we know that whenever the HotSync Manager encounters that specific ID, it will attempt to call our conduit.

    When creating any conduit we need to download and install the Conduit Developer Kit. This can be downloaded from the Palm Site (http://www.palmos.com/dev/tech/conduits/). I have downloaded and will be using CDK 4.0.3 for Windows. Also download and install the Palm COM Installer Update. It ships a few bug fixes and such for COM Conduits, which we will be creating. You may want to take time to browse the documentation that ships with the CDK, there is a lot of very useful information available.

    Step 1: Setting up VS .NET

    In Visual Studio .NET (VS .NET), create a new C# Windows application named "PBlgConduit". I decided to use a Windows application because we can use the default Form to show the status of the data synchronization and uploading. You can optionally add a Progress Bar and/or Label to the default form to programmatically indicate the status to the user. In order to keep this article simple and code sections short, I will not update any UI elements.

    In order for our Conduit to communicate with the HotSync Manager, we need to import two libraries from the CDK. These are both located at %install%\CDK403\Common\Bin where %install% is the path you chose to install the CDK to. For example, mine is located at c:\CDK403\Common\Bin\. Add a reference to both "ComDirect.dll" and "ComStandard.dll" in your project. VS .NET should take care of the COM Interop for you.

    The last thing you need to do is make sure that this project builds to the "Palm\" (the installation folder for all of the Palm files) folder. This is needed for debugging correctly.

    Now that we have the bare requirements for the VS .NET setup, we will create more specific classes and projects to handle our data, including a special project will help import Palm databases into our managed environment.

    Step 2: Creating the Data Tier and Getting Ready To Upload

    In this step we will create a few classes (essentially our Data Tier) to hold the UDTs that we created in the first article; we will also create a reusable project that will allow us to easily import Palm databases into this data tier, and finally we will hook into an existing project to handle the WebLogAPI details.

    In the default project within VS .NET create a new class named "DataTier.cs". We will use this to hold all three of the data tier classes. Figure 1 below is the final output of all three of these classes. Notice that each class has a few properties associated with the Palm database itself. It is important to note the actual order of the properties in each class because we rely on these when we move on to importing the data from the synchronization process.

    Figure 1 List of BlogEntry, BlogSetting, sTypes Types

    using System;

     

    namespace PBlgConduit.DataTier {

           ///<summary>

           /// Used to be the managed representation of the BlogEntry UDT from the Palm Database

           /// Type BlogEntry

           ///           subject as String 'subject of the entry

           ///           dDate as String  'date of the entry

           ///           entry as String  'the actuall full text entry

           ///           settingsName as String 'matching settings name

           ///           End Type

           ///</summary>

           publicclass BlogEntry {

                  /*app specific attributes*/

                  string key;

                  string subject;

                  string dDate;

                  string entry;

                  string settingsName;

                  publicstring Key{get{return key;}set{key=value;}}

                  publicstring Subject{get{return subject;}set{subject=value;}}

                  publicstring DDate{get{return dDate;}set{dDate=value;}}

                  publicstring Entry{get{return entry;}set{entry=value;}}

                  publicstring SettingsName{get{return settingsName;}set{settingsName=value;}}

                  /*Palm DB Specific attributes for each record*/

                  private PDStandardLib.ERecordAttributes eAttributes;

                  privateint nIndex;

                  privateint nCategory;

                  privateobject vUniqueId;

                  privatebyte[] raw;

                  publicbyte[] Raw{get{return raw;}set{raw=value;}}

                  public PDStandardLib.ERecordAttributes EAttributes{get{return eAttributes;}set{eAttributes=value;}}

                  publicint Index{get{return nIndex;}set{nIndex=value;}}

                  publicint Category{get{return nCategory;}set{nCategory=value;}}

                  publicobject UniqueId{get{return vUniqueId;}set{vUniqueId=value;}}

     

                  public BlogEntry() {

                  }

                  public BlogEntry(string Subject, string DDate, string Entry, string SettingsName) {

                         subject=Subject;

                         dDate=DDate;

                         entry=Entry;

                         settingsName=SettingsName;

                  }

           }

           ///<summary>

           /// Used to represent the managed version of the BlogSetting UDT

           /// Type BlogSetting

           ///           Name as String  'name of the setting, key

           ///           isDefault as Integer 'if this is the default setting

           ///           sType as Integer    'type of setting it is

           ///           username as String 'username to use during auth

           ///           password as String 'password to use during auth

           ///           port as Integer 'what port is the remote service running on

           ///           domain as String 'what domain/ip is the remote server

           ///           path as String 'file path to the save location

           ///           filename as String 'ftp file name,

           ///           'http variable post name For xml upload

           ///           'or url end point

           ///           End Type

           ///</summary>

           publicclass BlogSetting {

                  string key;

                  string name;

                  int isDefault;

                  string sType;

                  string username;

                  string password;

                  int port;

                  string domain;

                  string path;

                  string filename;

                  publicstring Key{get{return key;}set{key=value;}}

                  publicstring Name{get{return name;}set{name=value;}}

                  publicint IsDefault{get{return isDefault;}set{isDefault=value;}}

                  publicstring SType{get{return sType;}set{sType=value;}}

                  publicstring Username{get{return username;}set{username=value;}}

                  publicstring Password{get{return password;}set{password=value;}}

                  publicint Port{get{return port;}set{port=value;}}

                  publicstring Domain{get{return domain;}set{domain=value;}}

                  publicstring Path{get{return path;}set{path=value;}}

                  publicstring Filename{get{return filename;}set{filename=value;}}

     

                  /*Palm DB Specific attributes for each record*/

                  private PDStandardLib.ERecordAttributes eAttributes;

                  privateint nIndex;

                  privateint nCategory;

                  privateobject vUniqueId;

                  privatebyte[] raw;

                  publicbyte[] Raw{get{return raw;}set{raw=value;}}

                  public PDStandardLib.ERecordAttributes EAttributes{get{return eAttributes;}set{eAttributes=value;}}

                  publicint Index{get{return nIndex;}set{nIndex=value;}}

                  publicint Category{get{return nCategory;}set{nCategory=value;}}

                  publicobject UniqueId{get{return vUniqueId;}set{vUniqueId=value;}}

     

                  public BlogSetting() {

                  }

     

                 

                  public BlogSetting(string Name,int IsDefault,string SType,string Username,string Password,int Port,string Domain,string Path,string Filename) {

                         name=Name;

                         isDefault=IsDefault;

                         sType=SType;

                         username=Username;

                         password=Password;

                         port=Port;

                         domain=Domain;

                         path=Path;

                         filename=Filename;

                  }

           }

    }

    Next we will add a new C# Class Library project to the solution named "PalmDBImporter", which will contain a simple class that will allow us to easily import the Palm databases into our data tier classes above. The sole reason why I want to create this as a new project is so that we can reuse this project in future solutions, since it will be a generic Palm database importer. Make sure you add a project reference in the PBlgConduit solution to the new project. Figure 2 below shows the code listing for this class.

    Figure 2: Palm Database Importer

    using System;

     

    namespace PalmDBImporter {

           ///<summary>

           /// Class used to import the byte[] from the Palm Synch process and bind it to a Class, based on NULL \0 values and reflection

           ///</summary>

           publicclass Importer {

                  ///<summary>

                  /// called with an instantiated class and the byte[] of data.  It will attempt to move the data into the class based on its public properties.

                  ///</summary>

                  ///<param name="Class"></param>

                  ///<param name="data"></param>

                  ///<returns></returns>

                  publicstaticbool BindToClass(object Class, byte[] data) {

                         try {

                               //get a list of all the available properties

                               System.Reflection.PropertyInfo[] props = Class.GetType().GetProperties();

                               int pCounter=0;

                               int bCounter=0;

                               //create a temp buffer to hold current data

                               byte[] propData = newbyte[data.Length];

                               //if we actually have any public properties

                               if(props!=null && props.Length>0) {

                                      //grab the current property

                                      System.Reflection.PropertyInfo currentProp = props[pCounter];

                                      //iterate over the entire length of the data

                                      for(int x=0;x<data.Length;x++) {

                                             //if it is a null value, then we hit a field terminator

                                             if(data[x]==0) {

                                                    //grab the bytes from the data into our temp buffer

                                                    byte[] newData = newbyte[bCounter];

                                                    newData = GetBytes(propData, 0, bCounter);

                                                    //convert the bytes to a string

                                                    string val = System.Text.ASCIIEncoding.ASCII.GetString(newData);

                                                    //set the value into the property

                                                    try {

                                                           //we are only gonna handle 3 data types right now

                                                           //boolean, string and numbers

                                                           string propType=currentProp.PropertyType.FullName.ToLower().Replace("system.","");

                                                           object[] propValue=GetValue(propType, val);

                                                           Class.GetType().InvokeMember(currentProp.Name, System.Reflection.BindingFlags.SetProperty, null, Class, propValue);

                                                    }catch(Exception exc) {

                                                           string f = exc.ToString();

                                                           //do nothing

                                                    }

                                                    pCounter++;

                                                    //if we have any more properties, lets continue

                                                    if(pCounter<props.Length) {

                                                           currentProp = props[pCounter];

                                                           propData = newbyte[data.Length];

                                                           bCounter=0;

                                                    } else {

                                                           break;

                                                    }

                                             } else {

                                                    //shove the current value into the temp buffer

                                                    propData[bCounter]=data[x];                                  

                                                    bCounter++;

                                             }

                                      }

                               }

                               returntrue;

                         }catch(Exception e) {

                               returnfalse;

                         }

                  }

                  ///<summary>

                  /// Fix up the string to match HTML output for Weblogs

                  ///</summary>

                  ///<param name="str"></param>

                  ///<returns></returns>

                  publicstaticstring FixString(string str) {

                         str = str.Replace("\r\n", "<br />");

                         str = str.Replace("\r", "<br />");

                         str = str.Replace("\n", "<br />");

                         return str;

                  }

                  publicstaticobject[] GetValue(string propType, string val) {

                         object[] propValue=newobject[]{null};

                         try {

                               #region switch block for all data types

                               switch(propType) {

                                      case "boolean":

                                      case "bool":

                                             propValue[0] = System.Boolean.Parse(val);

                                             break;

                                      case "float":

                                             propValue[0] = float.Parse(val);

                                             break;

                                      case "decimal":

                                             propValue[0] = decimal.Parse(val);

                                             break;

                                      case "double":

                                             propValue[0] = double.Parse(val);

                                             break;

                                      case "int16":

                                             propValue[0] = int.Parse(val);

                                             break;

                                      case "int32":

                                             propValue[0] = int.Parse(val);

                                             break;

                                      case "int64":

                                             propValue[0] = long.Parse(val);

                                             break;

                                      case "single":

                                             propValue[0] = short.Parse(val);

                                             break;

                                      case "long":

                                             propValue[0] = long.Parse(val);

                                             break;

                                      case "short":

                                             propValue[0] = short.Parse(val);

                                             break;

                                      case "uint":

                                             propValue[0] = uint.Parse(val);

                                             break;

                                      case "uint16":

                                             propValue[0] = uint.Parse(val);

                                             break;

                                      case "uint32":

                                             propValue[0] = ulong.Parse(val);

                                             break;

                                      case "uint64":

                                             propValue[0] = ulong.Parse(val);

                                             break;

                                      case "ulong":

                                             propValue[0] = ulong.Parse(val);

                                             break;

                                      case "ushort":

                                             propValue[0] = ushort.Parse(val);

                                             break;

                                      default:

                                             propValue[0]=FixString(val);

                                             break;

                               }

                               #endregion

                         }catch{}

                         return propValue;

                  }

                  ///<summary>

                  /// used to get a range of bytes out of an existing byte[] block

                  ///</summary>

                  ///<param name="data"></param>

                  ///<param name="start"></param>

                  ///<param name="count"></param>

                  ///<returns></returns>

                  publicstaticbyte[] GetBytes(byte[] data, int start, int count) {

                         byte[] b = newbyte[count];

                         int ctr=0;

                         //copy over the bytes

                         for(int x=start;x<count;x++) {

                               b[ctr]=data[x];

                               ctr++;

                         }

                         return b;

                  }

           }

    }

    Essentially what we are dong in this block of code is looping over all of the data coming back for each record. In the example of a "blogdb" record, it is an "Entry" UDT that is being stored. The byte[] for each entry is fixed, thus we can rely on the null terminated string values to represent each field in each record. When we reach the null value, we know that the field is finished. We take that value and plug it into the current property.

    Notice that this does force the properties in our class to match, in order, the properties in the UDT. As long as this is done, database importing should go smoothly.

    Take time to review the code and pay close attention to the comments. If you are unsure about reflection you can read up on it in my past article on reflection at http://www.15seconds.com/issue/020618.htm.

    We now have a way to represent the data coming from the Palm device and a way to transform the native data (byte[]) into our fully managed code. In the next step I will show you how to register our conduit with the Conduit Configuration tool included in the CDK and how to test out our conduit during the synchronization process.

    Step 3: Registering our Conduit & Testing the Conduit

    Within the CDK there is a tool named "CondCfg.exe" that we need to examine. Find it within the "CDK403\Common\Bin" folder and execute it. You will see a list of existing install conduits including their CreatorIDs and a Name description option. Let's go ahead and add a new conduit for our application. Figure 3 below lists all of the items you must set in the "Conduit Information" screen.

    Figure 3: New Conduit Information

    Make sure you first choose "Component" as the Conduit Type and then point the "COM Client" to your version of VS .NET to the devenv.exe executable. This will force the HotSync Manager to open VS .NET,so we can choose our solution to load, allowing us to debug the conduit synchronization process. The HotSync Manager will stay idle until we close VS .NET. Of course this will stop the entire synchronization process, so later we will change it to our compiled application, the output of the PBlgConduit WinForm application.

    Next we need to wire up the incoming data to our data tier. I chose to put this code in my Form1_Load() event handler and also create a new class "PalmBlogWorker.cs". Together they will be responsible for iterating over all of the incoming databases, records, and fields and loading the appropriate managed object, and eventually posting the data to the correct site. Figure 4 shows the full PalmBlogWorker.cs class.

    Figure 4: PalmBlogWorker.cs class

    using System;

    using System.Runtime.InteropServices;  //need to import .net's InteropServices namespace

     

     

    namespace PBlgConduit {

           publicclass PalmBlogWorker {

     

                  /*Settings properties*/

                  PDStandardLib.PDRecordAdapter blogSettings;

                  //represents the query for our database

                  PDDirectLib.PDDatabaseQuery settingsQuery = new PDDirectLib.PDDatabaseQuery();

                  //all of the stored settings on the palm

                  System.Collections.ArrayList settings = new System.Collections.ArrayList();

                  public System.Collections.ArrayList Settings{get{return settings;}}

                  int dirtyCountSettings=0;

                  publicint DirtyCountSettings{get{return dirtyCountSettings;}}

                  int archiveCountSettings=0;

                  publicint ArchiveCountSettings{get{return archiveCountSettings;}}

                  int deleteCountSettings=0;

                  publicint DeleteCountSettings{get{return deleteCountSettings;}}

                  int secretCountSettings=0;

                  publicint SecretCountSettings{get{return secretCountSettings;}}

     

                  /*Entries properties*/

                  PDStandardLib.PDRecordAdapter blogrecord;

                  //entries database

                  PDDirectLib.PDDatabaseQuery query = new PDDirectLib.PDDatabaseQuery();

                  //entries collection

                  System.Collections.ArrayList entries = new System.Collections.ArrayList();

                  public System.Collections.ArrayList Entries{get{return entries;}}

                  int dirtyCount=0;

                  publicint DirtyCount{get{return dirtyCount;}}

                  int archiveCount=0;

                  publicint ArchiveCount{get{return archiveCount;}}

                  int deleteCount=0;

                  publicint DeleteCount{get{return deleteCount;}}

                  int secretCount=0;

                  publicint SecretCount{get{return secretCount;}}

     

                  ///<summary>

                  /// open all the settings entries in the database and import them

                  ///</summary>

                  privatevoid ImportSettings() {

                         int nIndex=0;

                         object vUniqueId=null;

                         int nCategory=0;

                         PDStandardLib.ERecordAttributes eAttributes=PDStandardLib.ERecordAttributes.eDirty;

                         object vData=null;

                         long nCount=0;

                        

                         blogSettings.IterationIndex = 0;

                         try {

                               //attempt to read an the first item out of our database

                               vData = blogSettings.ReadNext(out nIndex,out vUniqueId,out nCategory,out eAttributes);

                         }catch(Exception exc) {

                               exc.ToString();

                         }

                         try {               

                               //loop for each settings item

                               while(!(blogSettings.EOF)) {

                                      if(vData!=null) {                              

                                             //create a place holder class for the new settings

                                             PBlgConduit.DataTier.BlogSetting setting = new PBlgConduit.DataTier.BlogSetting();

                                             //using our importer bind the byte[] to our settings class

                                             PalmDBImporter.Importer.BindToClass(setting, (byte[])vData);                                   

                                             //set the miscel properties

                                             setting.EAttributes=eAttributes;

                                             setting.Index=nIndex;

                                             setting.UniqueId=vUniqueId;

                                             setting.Category=nCategory;

                                             //increment the miscel counters -not really needed

                                             //but nice to have if you plan on expanding the app more

                                             if(eAttributes==PDStandardLib.ERecordAttributes.eDirty)              dirtyCountSettings++;

                                             if(eAttributes==PDStandardLib.ERecordAttributes.eArchive) archiveCountSettings++;

                                             if(eAttributes==PDStandardLib.ERecordAttributes.eDelete)       deleteCountSettings++;

                                             if(eAttributes==PDStandardLib.ERecordAttributes.eSecret)       secretCountSettings++;

                                             setting.Raw=(byte[])vData;

                                             //add the current settings to our collection

                                             settings.Add(setting);

                                             nCount++;

                                      }

                                      //Read the next record

                                      vData = blogSettings.ReadNext(out nIndex,out vUniqueId,out nCategory,out eAttributes);

     

                               }

                         }catch(Exception){}       

                  }

     

                  ///<summary>

                  /// open all the blog entries in the database and import them

                  ///</summary>

                  privatevoid ImportEntries() {

                         int nIndex=0;

                         object vUniqueId=null;

                         int nCategory=0;                 

                         PDStandardLib.ERecordAttributes eAttributes=PDStandardLib.ERecordAttributes.eDirty;

                         object vData=null;

                         long nCount=0;

                        

                         blogrecord.IterationIndex = 0;

                         try {

                               //read the first record, if any

                               vData = blogrecord.ReadNext(out nIndex,out vUniqueId,out nCategory,out eAttributes);

                         }catch(Exception exc) {

                               exc.ToString();

                         }

                         try {               

                               //loop for each record

                               while(!(blogrecord.EOF)) {

                                      if(vData!=null) {                                     

                                             //create the entry placeholder

                                             PBlgConduit.DataTier.BlogEntry entry = new PBlgConduit.DataTier.BlogEntry();

                                             //bind the data to the entry class

                                             PalmDBImporter.Importer.BindToClass(entry, (byte[])vData);                                     

                                             //set miscel items

                                             entry.EAttributes=eAttributes;

                                             entry.Index=nIndex;

                                             entry.UniqueId=vUniqueId;

                                             entry.Category=nCategory;

                                             if(eAttributes==PDStandardLib.ERecordAttributes.eDirty)              dirtyCount++;

                                             if(eAttributes==PDStandardLib.ERecordAttributes.eArchive) archiveCount++;

                                             if(eAttributes==PDStandardLib.ERecordAttributes.eDelete)       deleteCount++;

                                             if(eAttributes==PDStandardLib.ERecordAttributes.eSecret)       secretCount++;

                                             entry.Raw=(byte[])vData;

                                             //add new entry to our collection of entries

                                             entries.Add(entry);

                                             nCount++;

                                      }

                                      //Read the next record

                                      vData = blogrecord.ReadNext(out nIndex,out vUniqueId,out nCategory,out eAttributes);

     

                               }

                         }catch(Exception){}       

                  }

     

                  ///<summary>

                  /// Main caller for worker

                  ///</summary>

                  public PalmBlogWorker() {

                         //import all the entries

                         //query and grab only the blogdb database entries

                         blogrecord=(PDStandardLib.PDRecordAdapter)query.OpenRecordDatabase("blogdb", "PDDirect.PDRecordAdapter",  PDDirectLib.EAccessModes.eRead | PDDirectLib.EAccessModes.eShowSecret | PDDirectLib.EAccessModes.eWrite);

                         ImportEntries();

                        

                         //import all the settings

                         //query and grab only the blogSettings database entries

                         blogSettings=(PDStandardLib.PDRecordAdapter)query.OpenRecordDatabase("blogSettings", "PDDirect.PDRecordAdapter",  PDDirectLib.EAccessModes.eRead | PDDirectLib.EAccessModes.eShowSecret | PDDirectLib.EAccessModes.eWrite);

                         ImportSettings();

     

                         //upload all the items

                         UploadEntries();

                  }

                  publicvoid UploadEntries() {

                         //if we have any ditry entries, meaning any entries that we havnt dealt with yet

                         if(this.entries.Count>0 && DirtyCount>0) {

                               //for each entry

                               for(int x=0;x<entries.Count;x++) {

                                      string results = "";//worker.UploadEntry(entry, settings);

                                      PBlgConduit.DataTier.BlogEntry entry = (PBlgConduit.DataTier.BlogEntry)entries[x];

                                      //if it is dirty

                                      if(entry.EAttributes==PDStandardLib.ERecordAttributes.eDirty) {

                                             //find the associated settings

                                             for(int y=0;y<settings.Count;y++) {

                                                    PBlgConduit.DataTier.BlogSetting setting = (PBlgConduit.DataTier.BlogSetting)settings[y];

                                                    if(setting.Name==entry.SettingsName) {

                                                           //upload the entry with the given settings

                                                           results = this.UploadEntry(entry, setting);

                                                           break;

                                                    }

                                             }

                                             //upload it

                                             //if we have no errors during upload, delete the record

                                             if(results!="") {

                                                    //delete the entry from the db

                                                    DeleteRecord(entry.UniqueId, "blogdb");

                                             }

                                      }

                                }

                         } else {

                               //Nothing new to upload. do nothing right now

                         }

                  }

                  publicstring UploadEntry(PBlgConduit.DataTier.BlogEntry entry, PBlgConduit.DataTier.BlogSetting settings) {

                         //can handle multiple upload types, but right now we only

                         //want to use the WebLogApi

                         //implement more if you like

                         string ret="";

                         if(settings.SType=="WebLogApi") {

                               ret = UploadMetaWebLogAPI(entry, settings);

                         } else {

                               return "Nothing done";

                         }

                         return ret;

                  }

                  publicstring UploadMetaWebLogAPI(PBlgConduit.DataTier.BlogEntry entry, PBlgConduit.DataTier.BlogSetting settings) {

                         //use JDSolutions XmlRPC library to handle the WebLogApi uploads

                         //it can be downloaded at: http://www.jondavis.net/JDSolutions/XmlRpc/readme.htm

                         //ive included the full download with this zip

     

                         //create a new xmlrpcclient

                         JDSolutions.XmlRpc.XmlRpcClient xrc = new JDSolutions.XmlRpc.XmlRpcClient();

     

                         //create xmlrpc strings to hold our auth data

                         JDSolutions.XmlRpc.Elements.XmlRpcString blogid = new JDSolutions.XmlRpc.Elements.XmlRpcString(entry.Subject);

                         JDSolutions.XmlRpc.Elements.XmlRpcString username = new JDSolutions.XmlRpc.Elements.XmlRpcString(settings.Username);

                         JDSolutions.XmlRpc.Elements.XmlRpcString password = new JDSolutions.XmlRpc.Elements.XmlRpcString(settings.Password);

                         JDSolutions.XmlRpc.Elements.XmlRpcBoolean publish = new JDSolutions.XmlRpc.Elements.XmlRpcBoolean(true);

     

                         //Post is an object i needed to create in order to handle the actual post data being sent

                         //It is located in the MetaBlogApi.cs file included in this project

                         //load up the new post

                         Post post=new Post();

                         post.dateCreated=System.DateTime.Parse(entry.DDate);

                         post.description=entry.Entry;

                         post.title=entry.Subject;

     

                         //conver our post class to an xmlrpcstruct

                         JDSolutions.XmlRpc.Elements.XmlRpcStruct ST2 = (JDSolutions.XmlRpc.Elements.XmlRpcStruct)JDSolutions.XmlRpc.XmlRpcTools.ConvertElement(post, true);

     

                         //gather the parameters into our object[]

                         object[] p = newobject[]{blogid, username, password, ST2, publish};

                         string s="";

                         try {

                               //call the method on the client, passing all needed data

                               s = (string)xrc.Call(settings.Domain,settings.Port, settings.Path, "metaWeblog.newPost", p);

                         }catch(Exception e){

                               s = "";

                         }

                         return s;

                  }

     

                  ///<summary>

                  /// Delete the record based on uniqueid from the given db

                  ///</summary>

                  ///<param name="UniqueId"></param>

                  ///<param name="database"></param>

                  ///<returns></returns>

                  publicbool DeleteRecord(object UniqueId, string database) {

                         try {

                               if(database.ToLower()=="blogdb")

                                      blogrecord.Remove(UniqueId);

                               else

                                      blogSettings.Remove(UniqueId);

     

                               returntrue;

                         }catch(Exception exc) {

                               string e = exc.ToString();

                               returnfalse;

                         }

                  }

           }

    }

    Take time to review the above code. Make sure you are familiar with the XML RPC library I'm using and the fact that it will publish the data live to your server.

    So now that we have this setup, make sure you have uploaded the PalmBlog application to your Palm and that you have made an entry or two (including valid settings) because we will need data to pull down out of the device in order to fully test this conduit. If you have a lengthy synchronization process you may consider deleting all of the data on your device (after a good backup of the ChartiR folder), and then just synchronizing the NSBRuntime and the Palm Blog application itself to the device. It makes things run much quicker.

    At this point make sure your solution builds. If it doesn't, review my sample solution and try to determine what you missed and correct any errors. Once you get it to build, you are ready to debug the conduit. Place your device into the cradle and begin the synchronization process.

    Once the HotSync Manager reaches the data that is marked with our Creator ID, it will execute the application that we specified in our conduit's settings, "Com Client", which should be the VS .NET IDE. Once VS .NET finishes loading, choose our PBlgConduit application. You will now be able to step into the application with full debugging available. Make sure it follows the path that you expect and that your data is being uploaded to the appropriate destination.

    Once you have completed the conduit and are happy with its results, don't forget to change the "Com Client" in the Conduit Configuration tool; point it to the "PBlgConduit.exe" executable that should be in your "Palm\" folder.

    Conclusion

    So far, in this series of articles you have learned how to create a simple application targeted for the Palm OS and how to create a conduit which allows us to take the data generated by the Palm and bring it into a fully managed solution on the PC. The last part of this series will focus on the installation process using the deployment tools that ship with VS .NET.

    If you complete this application or any portion of it make sure you e-mail me your completed solution so I can share it with others.

    About the Author

    Robert Chartier has developed IT solutions for more than nine years with a diverse background in both software and hardware development. He is internationally recognized as an innovative thinker and leading IT architect with frequent speaking engagements showcasing his expertise. He's been an integral part of many open forums on cutting-edge technology, including the .NET Framework and Web Services. His current position as vice president of technology for Santra Technology (http://www.santra.com) has allowed him to focus on innovation within the Web Services market space.

    He uses expertise with many Microsoft technologies, including .NET, and a strong background in Oracle, BEA Systems, Inc.'s BEA WebLogic, IBM, Java 2 Platform Enterprise Edition (J2EE), and similar technologies to support his award-winning writing. He frequently publishes to many of the leading developer and industry support Web sites and publications. He has a bachelor's degree in Computer Information Systems.

    Robert Chartier can be reached at rob@santra.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Apr 13, 2004 - Wireless Home Automation Using .NET and X10
    Learn how to use .NET to communicate with the X10 Firecracker Home Automation System through a PC's serial port. Then build a mobile Web form to access all X10-enabled appliances from a wireless device.
    [Read This Article]  [Top]
    Sep 3, 2003 - Programming for the Palm Part 3 - Creating a Windows Installer
    In the third and final installment of the Programming for the Palm series, Robert Chartier shows how to create a Windows Installer that will install and register the Palm application and Palm conduit on the target machine.
    [Read This Article]  [Top]
    Jun 24, 2003 - Programming for the Palm Part 1 - Creating the Palm Application
    The first part of this three part series walks through the process of creating a mobile blog application using a BASIC development environment for Palm OS devices called NS Basic. Subsequent articles will focus on synchronizing the data to the desktop using C# and creating an installer.
    [Read This Article]  [Top]
    Apr 22, 2003 - Creating a Mobile Portal
    In the past, developers typically relied on XML and XSLT to create sites that needed to target multiple client platforms. Today, with ASP.NET mobile controls, developers only need to focus on creating one application. In this article, Rob Chartier shows how easy it is to use the ASP.NET mobile controls to create a full-blown wireless portal.
    [Read This Article]  [Top]
    Mar 27, 2001 - Using ASP to Send a Wireless Text Message
    Even though SMS is now in high gear, developers remain slated with restrictive limits to carrier resources. Sending an SMS message via e-mail requires the acceptance of several hidden flaws. Joe Lauer shows how to avoid these complications by sending a wireless text-message through the use of ASP.
    [Read This Article]  [Top]
    Jun 22, 2000 - HDML and ASP Go Hand in Hand
    Learn how to create applications for wireless devices using the Handheld Device Markup Language (HDML) and ASP. Article covers everything from setting the MIME content type for HDML in ASP to passing data between languages to accessing environment variables from ASP.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry