I ran into this issue today. When I logged into our Project Web Server website I received this error:

The controls for Project Web Access cannot be downloaded correctly. To download the controls:
  • Verify your security settings in Internet Explorer are set to allow ActiveX controls to be downloaded.
  • Check to see if Internet Explorer has stopped the installation of the ActiveX controls.
  • To install the controls, on the Information Bar, click Install ActiveX Control. You need to use a 32-bit version of your browser to download and run the ActiveX controls.
  • Contact your systems administrator.

After a reboot found this article entitled Error message when you start Microsoft Project Web Access: "The controls for Microsoft Project Web Access could not be downloaded correctly" in the Microsoft Knowledge Base. To fix the issue I removed the Project Web Access ActiveX controls by:

Remove any controls that are already downloaded
Project 2007
  1. Start Internet Explorer.
  2. On the Tools menu, click Internet Options.
  3. Click the General tab, and then click Settings in the Browsing history section.
  4. Click View Objects.
  5. Right-click Pj12enuC Class, and then click Remove.
  6. Right-click PjAdoInfo4 Class, and then click Remove.
  7. Close the View Objects window, and then click OK two times. 

I then went back into our Project Web Access website and downloaded the ActiveX controls again. Worked like a charm.

Posted by Jorriss | 2 comment(s)
Filed under:

A few months ago we started development on a new system. From the ground up we redesigned everything from our business processes to how we store data. Part of the redesign was deciding on using SOA technology in our middle tier. This will allow us to separate our UI from our middle tier even further. Due to the disconnected way our objects were going to work we decided to use guid or unique identifiers for our primary keys in our data model and assign guids in the middle tier. Of course, our DBAs weren't too keen on the idea and even now they are still a bit gunshy but they're coming around.

Of course, is one of the big concerns that the DB team has is the performance of SQL Server with GUIDs which has been well documented all across the net. So we decided to use the NewSequentialID() function as the default for all guid primary keys. On the application side we decided to implement a GUIDComb which was created by Jimmy Nilsson. The issue that we ran into with the GUIDComb was that it was creating guid sequence that was different from the NewSequentialID guid sequence.

At this point I decided to jump into the Google abyss and see if anyone else conquered this problem. The first solution that I found took a guid generated from System.Guid.NewGuid and reordered it so SQL Server would sort it correctly. The major issue that I found with this approach was the fact that it incremented the guid internally and didn't store the guid in the SQL Server sequence.

It was at this time that I found and excellent article by Rob Garrison entitled "Exploring NewSequentialID() in SQL Server 2005". In the article he discusses the differences between NewID() and NewSequenceID() and how NewSequenceID() uses a shared counter. So if you insert a row into Table1 then Table2 then Table1 again you will see the following GUID sequence.

63DD0AD3-A111-DD11-B2EB-005056AE063C -- Table1
64DD0AD3-A111-DD11-B2EB-005056AE063C -- Table2
65DD0AD3-A111-DD11-B2EB-005056AE063C -- Table1

That article led me to another article "How are GUIDs sorted by SQL Server?" Which linked to to the SQL Programmability & API Development Team Blog where I found this gem "Newsequentialid (Histrory/Benefits and Implementation)". In this post, they explain that sequential guids are created by calling UuidCreateSequential function of the rpcrt4.dll "with some byte scrambling to convince the rest of SQL engine that guids are produced in sequential order". Here's an example of the usage. The output of two calls to the UuidCreateSequential function would look like this:

6F9F9BFB-1203-11DD-BC40-001641E22FDB
6F9F9BFC-1203-11DD-BC40-001641E22FDB

But if you look at a SQL Server generated sequential guid it would looks like this:

4782336F-0312-DD11-B2EB-005056AE063C
4882336F-0312-DD11-B2EB-005056AE063C

And that's when it hit me, that "byte scrambling" that SQL Server was doing was in the first four bytes. If your guid is 6F9F9BFB-1203-11DD-BC40-001641E22FDB the first for bytes would be 6F 9F 9B FB. If you reverse them, FB 9B 9F 6F that would be in the sequence that SQL Server is currently using.

6F9F9BFB-1203-11DD-BC40-001641E22FDB -- UuidCreateSequential
6F9F9BFC-1203-11DD-BC40-001641E22FDB -- UuidCreateSequential
FB9B9F6F-1203-11DD-BC40-001641E22FDB -- UuidCreateSequential Reversed Bits 
FC9B9F6F-1203-11DD-BC40-001641E22FDB -- UuidCreateSequential Reversed Bits
4782336F-0312-DD11-B2EB-005056AE063C -- NewSequentialID
4882336F-0312-DD11-B2EB-005056AE063C -- NewSequentialID

Here's the code I created to create SQL Server formatted sequential guids in .Net:

Public Class SequentialGuid
    Declare Function UuidCreateSequential Lib "rpcrt4.dll" (ByRef id As Guid) As Integer

    Public Shared Function CreateSequentialGUID() As Guid

        Dim newGuid As Guid
        Dim returnVal As Integer
        returnVal = UuidCreateSequential(newGuid)

        Dim bytes As Byte() = newGuid.ToByteArray

        If returnVal <> 0 Then
            Throw New Exception("CreateSequentialGUID failed.")
        Else
            Array.Reverse(bytes, 0, 4)
            Array.Reverse(bytes, 4, 2)
            Array.Reverse(bytes, 6, 2)
            newGuid = New Guid(bytes)

            Return newGuid
        End If
    End Function
End Class

The one caveat is that DB generated guids and .Net generated guids may be not reflect the order in which the rows were inserted due to the mac address in the guid and the way SQL sorts its guids. (See the "How are GUIDs sorted by SQL Server?" article for more details.) You may see blocks of guids in your table generated by different machines. So if you need to know the true sequence of when a row was added to a table then use a created date field and the GetDate function.

Other Sources:

Improve Your Guid Key Performance with GuidCombs

The Cost of GUIDs as Primary Keys

The NewSequentialID Function

Generate Sequential GUIDs for SQL Server 2005 in C#

Sequential GUID Generator on Codeplex

UuidCreateSequential rptcrt4.dll 

SqlGuid Structure

How are GUIDs compared in SQL Server 2005?

Posted by Jorriss | 1 comment(s)

Recently, I started to use Google Calendar to share my schedule with my wife. To do this I'm using Google's Outlook Calendar Sync utility. The first version that I used (0.9.3.0) worked fine but it didn't get all of my appointments and it loaded my Deleted folder with thousands of blank appointments after each sync. A few weeks ago they released an update (0.9.3.2) that appeared to fix the blank appointment issue but I started to get this error:

Some of your Outlook appointments could not be loaded. Sync is interrupted in order to prevent actual data loss.

I ignored it for some time hoping for a quick patch from Google. But today I started to investigate while waiting for some software to uninstall. A quick trip to the Google Calendar Help forum proved to be quite useful. My first task was to find out to view the Outlook Calendar Sync Logs which can be viewed in the following locations:

WINDOWS XP
C:\Documents and Settings\<username>\Local Settings\Application Data\Google\Google Calendar Sync\logs
WINDOWS VISTA
C:\Users\<username>\AppData\Local\Google\Google Calendar Sync\logs

The log had this information in it:

SEVERE: IDispatch::GetProperty : EntryID //  [hr: -2147352567] [exception One or more items in the folder you synchronized do not match. To resolve the conflicts, open the items, and then try this operation again. wCode: 4096 scode: -2147352567]
SEVERE: Failed to load even brief info.
Unable to load basic info
SEVERE: Unable to get events from Outlook

So, there was some sort of issue that the sync tool was having when trying to retrieve the calendar events. The resolution came when I came across this post in the forum. It details the following steps to resolve an Outlook conflict.

  1. Open your calendar in Microsoft Outlook.
  2. Select "View by Category." (Main Menu > View > Arrange By > Current
    View > By Category)
  3. You'll see a list of events (if the events are collapsed in categories, you can expand them by clicking the "+" sign"). Using the icons to the left of each event, find events that have a "warning" icon (i.e. crossing swords).
  4. Double-click on each problematic event to resolve the problem
 

Sure enough, I found seven conflicts with appointments dating all the way back to 2003. They must of been hanging around for the past five years and I didn't know it. I cleared the conflicts and reran the Google Outlook Sync and it worked.

Posted by Jorriss | with no comments
Filed under:

Microsoft is offering free SQL Server 2008 online courses. The offered titles are:

  • What's New in SQL Server 2008 for Enterprise Data Platform
  • What's New in SQL Server 2008 for Business Intelligence
  • What's New in SQL Server 2008 for Database Development

We've been keeping our ear pretty close to the ground on SQL Server 2008 so this may come in handy. But according to my boy Jason SQL Server 2008 is a minor release. The course is free nonetheless.

          Via Tim Mitchell.

          Posted by Jorriss | with no comments
          Filed under: ,

          imageSince installing Visual Studio 2008 when I debug web projects VS opened the project in my default browser (currently Maxthon) and not Internet Explorer. Of course this isn't what I wanted. So I opened up trusty Google and found an answer on stevenharman.net.

          As it turns out setting this is quite simple.

          1. Open a WebForm file in VS (anything ending in .aspx will do)
          2. Select the "Browse With..." option from the File menu
          3. Select your preferred browser from the list and click the "Set as Default" button

          Now opening, browsing, or debugging a WebForm from within Visual studio will open the file in the specified browser (IE in my case) rather than my system default.

          And what do you know it works. Here's the complete article if you are so inclined. Thanks Steven.

          Posted by Jorriss | with no comments
          Filed under:

          Microsoft has released the Visual Studio 2008 and .Net Framework 3.5 Training Kit.

          The Visual Studio 2008 and .NET Framework 3.5 Training Kit includes presentations, hands-on labs, and demos. This content is designed to help you learn how to utilize the Visual Studio 2008 features and a variety of framework technologies including: LINQ, C# 3.0, Visual Basic 9, WCF, WF, WPF, ASP.NET AJAX, VSTO, CardSpace, SilverLight, Mobile and Application Lifecycle Management.

          I always love free training material. Enjoy. Via Elegant Code.

          Posted by Jorriss | with no comments
          Filed under: ,

          After the nightmare that was the Team Foundation Server 2005 installation I was secretly dreading the 2008 upgrade. But somewhere in the back of my mind I was also cautiously optimistic as well. I mean could it possibly be any worse than the 2005 install? I did my homework pouring over the install instructions over the past few days. I wanted to be ready for anything. Fortunately for me, I didn't have much to worry about. Two resources that helped immeasurably were the Team Foundation Installation Guide for Visual Studio Team System 2008 and Grant Holliday's Tips for upgrading from TFS2005 to TFS2008 post. I also got to give the guys over at Radio TFS an assist for their TFS 2008 What's New and Should You Upgrade show.

          The only issue that we ran across was directly related to the installation instructions in the the Installation Guide. In the "Upgrading Your Team Foundation Server" page in the "Before You Upgrade Team Foundation Server" section step six says to "Uninstall Team Foundation Server". What it doesn't say is what applications consist of Team Foundation Sever. We later determined that this meant TFS 2005 Build and TFS 2005 Services and TFS 2005 Databases but initially we only uninstalled the build and services apps. Luckily, the System Health Check caught the problem and after uninstalling the databases app the install went fine.

          Big ups to the TFS team for dramatically improving the install experience. What once took days now only takes hours.

          Posted by Jorriss | with no comments
          Filed under:
          I'm back. It's been a long time since my last post. Since then Alexa is 1.5 times older, I've been promoted at work, I've gotten more involved at church and I'm busier than ever. I did have a good logical reason why I stopped blogging but I'm going to save that for later. I've also been able to move the blog from .Text to Community Server thanks to Kevin Harder and his migration tool. I was able to move web hosts as well. I'm still going to keep the personal stuff on Jorriss.com and the technical stuff at Jorriss.net. The design of the blogs will also be changing over the next few months. Frankly, I have no idea what it's going to look like. Maybe J can help. Anyways brace yourself kids...I'm back.

           

          Posted by Jorriss | with no comments
          Filed under:
          I found this tool this morning, ieHTTPHeaders. This Internet Explorer plug-in shows all of the HTTP Headers on a page. Quite useful for those times when you need to see what headers your site is sending the client.
          Posted by Jorriss | with no comments

          Last week, Microsoft announced Sandcastle which produces MSDN style documentation for your Visual Studio projects. Sandcastle is used internally to build the .Net Framework documentation. About the same time, Kevin Downs the creator of NDoc an open-source .Net documentation tool, announced that he will not be working on future versions of NDoc. It's kinda sad to see a good project go wrong but it just goes to show you how frail the open source movement is. It is difficult enough to manage a project team that's on your payroll. It's exponentially more difficult to do so when contributors are doing so out of their own free time. Don't get me wrong open-source has it's place and I use open-source software just about everyday. But I wouldn't risk my projects on it unless I knew what the source was doing. A good example of this is Rocky Lhotka's CSLA. We use the CSLA in the office and build all of our business objects on it. But if Rocky didn't have a book on how the CSLA was built wouldn't I have used it. It would of taken too much time and money to dissect the source to figure out what it was doing. Sure it cost me $40 to essentially buy a manual but it is definately worth it. If more open-source projects had better documentation I would use open-source more often.

          A few years back I demoed nSurvey it worked just fine but I had some major problems with the 1) lack of support, 2) lack of documentation. Now the open-source camp would say "just fix it yourself". But my company doesn't pay me to fix free software, they pay me to deliver corporate solutions. Purchasing a survey package gave me both the support and documentation. Fixing survey code doesn't help the company bottom line. Do I blame Microsoft for releasing their own documentation tool? Nope. I welcome it. Could of NDoc competed with Sandcastle? Probably. Can you blame Kevin for moving on? No way. So good luck Kevin you created a nifty little tool.

          BTW - those people who mail-bombed Kevin, that was just wrong.

          Some other opinions on the subject:

          "I cannot understand the mentality of someone who demands for developers to hurry up and release a new version of a free software product. If you are in such dire need of the new version, why not hurry up and contribute? Having said that, I feel particularly bad that I never contributed to NDoc, yet enjoyed so much use out of it…. So let’s [band] together and declare today, July 26, 2006, Contribute To Open Source Day. Look at the open source software you use and consider making a tiny contribution to the project if you find it useful." -- Phil Haack

          "It's too bad to see what happens to such a useful project. I guess it's common for hobby projects like this one. Having worked for big companies, I can testify that they use open source products extensively, but wouldn't do the slightest thing to contribute to the projects or help them in any way. They just expect the free tools to work perfectly, just like they had paid big money for them!" -- Fabrice Marguerie

          "Personally, as an Open Source project co-leader, I'd much rather folks who use DasBlog pick a bug and send me a patch (unified diff format) than give money. I suspect that Kevin would have been happy with a dozen engineers taking on tasks and taking on bugs in their spare time. We are blessed. This Open Source stuff is free. But it's free like a puppy. It takes years of care and feeding. You don't get to criticise a free puppy that you bring in to your home." -- Scott Hanselman

          Via The Server Side.

          Posted by Jorriss | with no comments
          Filed under:

          I hate throwing away code. Recently, we had a requirement to create an Excel spreadsheet with formulas and specific data for a particluar user. Of course we could always use Reporting Services to get the data in Excel format but then there would be no formulas. So I ran across this article by Peter Bromberg titled Create Dynamic ASP.NET Excel Workbooks In C#. It's a short article but it gives a good code listing at the end. I created a prototype in VB.Net & ASP.Net and it was working pretty well, a bit slow, but it worked. Then it got yanked. Since I hate throwing away code a modified version ends up here. Enjoy.

           

            Imports Microsoft.Office.Interop

           

            Public Class test

              Inherits System.Web.UI.Page

           

              Private Sub RemoveFiles(ByVal strPath As String)

           

                Dim di As System.IO.DirectoryInfo = New System.IO.DirectoryInfo(strPath)

                Dim fiArr() As System.IO.FileInfo = di.GetFiles()

                For Each fri As System.IO.FileInfo In fiArr

           

                  If fri.Extension.ToString() = ".xls" Or fri.Extension.ToString() = ".csv" Then

           

                    Dim min As TimeSpan = New TimeSpan(0, 0, 60, 0, 0)

                    If fri.CreationTime < DateTime.Now.Subtract(min) Then

                      fri.Delete()

                    End If

           

                  End If

                Next

           

              End Sub

           

              Private Sub CreateExcelWorkbook()

           

                Dim strCurrentDir As String = Server.MapPath(".") & "\"

                RemoveFiles(strCurrentDir) ' utility method to clean up old files

                Dim oXL As Excel.Application

                Dim oWB As Excel._Workbook

                Dim oSheet As Excel._Worksheet

                Dim oRng As Excel.Range

                Try

           

                  GC.Collect() ' clean up any other excel guys hangin' around...

                  oXL = New Excel.Application

                  oXL.Visible = False

           

                  ' Get a new workbook.

                  oWB = CType(oXL.Workbooks.Add, Excel.Workbook)

                  oSheet = CType(oWB.ActiveSheet, Excel.Worksheet)

           

                  ' Write Header in Excel

                  oSheet.Cells(1, 1) = "Col1"

                  oSheet.Cells(1, 2) = "Col2"

                  oSheet.Cells(1, 3) = "Col3"

                  oSheet.Cells(1, 4) = "Col4"

                  oSheet.Cells(1, 5) = "Total Value"

           

                  ' Format Cells.

                  oSheet.Range("A1", "Z1").Font.Bold = True

                  oSheet.Range("B1", "D3").HorizontalAlignment = Excel.XlHAlign.xlHAlignCenter

                  oSheet.Range("E1", "E3").HorizontalAlignment = Excel.XlHAlign.xlHAlignRight

                  oSheet.Range("E1", "E3").NumberFormat = "$0.00"

                  oSheet.Range("E1", "E1").Formula = "= A1 * C1"

                  oSheet.Range("E2", "E2").Formula = "= A2 * C2"

                  oSheet.Range("E3", "E3").Formula = "= A3 * C3"

           

                  ' AutoFit columns A:Z.

                  oRng = oSheet.Range("A1", "Z1")

                  oRng.EntireColumn.AutoFit()

           

                  oXL.Visible = False

                  oXL.UserControl = False

                  Dim strFile As String = "report" & System.DateTime.Now.Ticks.ToString() & ".xls"

                  oWB.SaveAs(strCurrentDir & strFile)

           

                Catch e As Exception

                  System.Diagnostics.Debug.WriteLine(e)

                Finally

                  ' Need all following code to clean up and extingush all references!!!

                  oWB.Close(Nothing, Nothing, Nothing)

                  oXL.Workbooks.Close()

                  oXL.Quit()

           

                  System.Runtime.InteropServices.Marshal.ReleaseComObject(oRng)

                  System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL)

                  System.Runtime.InteropServices.Marshal.ReleaseComObject(oSheet)

                  System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB)

           

                  oSheet = Nothing

                  oWB = Nothing

                  oXL = Nothing

                  GC.Collect() ' force final cleanup!

                End Try

              End Sub

            End Class

          Posted by Jorriss | with no comments

          The Miami Users Group will be offering a free session on the new Sharepoint Server 2007 on August 17th at Carnival Cruise Lines - World Wide Headquarters 3650 NW 87th Avenue Miami, FL. Here is a snipet on the session:

          Introducing Microsoft Office SharePoint Server 2007 (MOSS) by Joe Homnick Regional Director Ambassador and MVP - July 13 at GCUG in Boca Raton, July 15 at Tampa CodeCamp and August 17 MUG @ Carnival in Miami

          Office and Sharepoint Server 2007 are chock full of developer opportunities.  Come see how new ASP.Net features such as Master Pages, Site Navigation, etc. and the Net Framework 3.0 Workflows are integrated into SharePoint 2007.  This product is going to be huge and it's going to become a "SharePoint World".  We'll investigate the awesome new capabilities in the "Free" Windows SharePoint Services (WSS) and compare those to the value added Microsoft Office SharePoint Services.

        • Developer Roadmap
        • SharePoint Services (WSS) Ver 3 architecture
        • WSS Storage
        • WSS Security 
        • Developing Portal Applications
        • InfoPath 12 in WSS 
        • Web Content Management with MOSS 
        • Workflow Integration in MOS
        • MOSS 2007 Business Intelligence
        • Posted by Jorriss | with no comments


          Microsoft has announced some updates to thier Windows Live Local service (I really hate that name). Then enhancements include real-time traffic reporting and new social sharing tools. Here are the highlights:

          • Real-time traffic flow. Customizable driving directions are now even more useful with the addition of real-time traffic flow and incident reporting provided by Traffic.com. This functionality will be available only in the U.S. release.
          • Collections. Social networking functionality allows customers to create lists of favorite landmarks and locations, attach personal photos and save them to a Scratchpad. Collections can be saved, recalled later, “permalinked,” and shared with friends and community in e-mail or through their MSN Spaces blog.
          • Integration with Windows Live Messenger. Sharing maps and location information from within Windows Live Messenger chats is easier. Users begin a sharing session from the Actions menu. People sharing a chat session can see and interact with the same Windows Live Local map and benefit from a shared mapping and local search experience.

          But what's really got me excited is the enhancements made to Virtual Earth. Over the weekend I toyed a bit with Virtual Earth and thier map control. I was impressed with the ease of development but underwhelmed with the features. Now with the announced enhancements I might have to take another look. Via Virtual Earth Developer Blog.

          • Place/Address lookups (Geocoding) – With a simple new Find() method, you can easily add a Where box to your application to allow users to input addresses, cities/towns, zip codes, landmarks or other locations and quickly and easily pinpoint them on the map. Support for handling ambiguous addresses is included as well.
          • Driving Directions/Routing and Polylines – Driving directions, routing and polylines. The new route methods allow developers to quickly enable driving directions from one location to another in their application. You also can create your own custom polylines for highlighting key information on maps and imagery.
          • Quick data-binding for GeoRSS – Now, you can quickly a simply bind data to pushpins using the standard data format GeoRSS. Just point the control at your GeoRSS file or service and it will automatically manage the process of creating pushpins and pop-ups.
          • Public Collection layers – Even easier than creating a GeoRSS file, you can bind a Windows Live Local public collection to the control. Just build a public collection of your favorite places in your local town or a listing of your business’ locations, drop the map control in your web page using the sample code in the SDK and point it to your collection—voila, instant mashup.
          • Built in pushpins and pop-ups – Now, you can quickly use our methods to create pushpins and pop-ups in the default style without having to design them yourselves. Of course, the very popular, simple methods for rolling your own are still there as well; so you have your choice from easy default styles to full look and feel control.

          MS has also made available a pretty nice interactive SDK which should get you up and running with Virtural Earth. Original heads up via Scoble.

          Posted by Jorriss | with no comments
          Filed under: ,

          In the office we're currently investigating Smart Client vs Web Applications. It seems that I'm not alone. A few months ago Rob Howard and Paul Ballard recently got in a holy war over this exact issue. Rob's premise is that web applications rule and smart clients suck. Paul believes that smart clients rule and web apps suck. Other bloggers have also chimed in with their two cents. Each have their own valid points but I'm with Paul sometimes a smart client just makes sense. In my case we have a web site that is available to our partners and employees. We have a piece of functionality that is only available for employees. So do we create an employee application or just put it up on the web? Having a rich client will allow our users to view their data quickly without postbacks. It will also help us, the developers, create a better user experience since we can use better controls and forget about stateless session management. Personally, I'll feel better with the functionality in a smart client where a web script attack can't access corporate functionality or data. What are we going to do? That's up in the air. What ever we decide I still think smart client is the better choice.

          Posted by Jorriss | with no comments

          As I mentioned in my previous post I'm in the middle of moving a blog from MSN Spaces to my Community Server site. Of course there were some issues to resolve. You first need to turn on e-mail publishing for your MSN Spaces blog. You cannot use the MetaWeblog API without it. You can turn it on by following the steps documented in the Getting Started with the MetaWeblog API for MSN Spaces page. Note: you may have to use Firefox to do this. No lie. While using IE6 an error kept popping up on me. Weird.

          Next you will have to download the XML-RPC dll. Unzip the file and create a reference to the XmlRpc.dll in your project.

          I also figured out there is no way through the API to retrieve comments or trackbacks. Luckily for me there weren't many comments or trackbacks so losing this data wasn't a big deal. Also, MSN Spaces doesn't let you retrieve any more than the most recent 20 posts via the API. This is a problem. The API does allow you to retrieve a single post item through the getPost() method. So I ran a test. I used the getRecentPosts() method to retrieve the postIDs of the most recent posts. I found out that the postIDs are composed of an alphanumeric key and a numeric id. In this case the key looked like D8F20BDF7ECC5C2B!106 where the last three digits would differ between each post. You can clearly see this postID in the permalink of any MSN Spaces post. There is my rosetta stone. If I was to loop through a simple counter and concatenate the counter value at the end of the D8F20BDF7ECC5C2B! (we'll call this the MSNblogkey) I could ask the API for that post. If it threw an exception it didn't find a post. If it did then we load the post into CS. After all of that I sucessfully loaded http://spaces.msn.com/flamingbluemonkeys/ to http://www.flamingbluemonkeys.com.  

          public static void PostMSNBlogData (){

            MsnSpacesMetaWeblog mw = new MsnSpacesMetaWeblog();

            string blogid = "MyBlog"; // doesn't change will be MyBlog for everyone

            string username = "username"; // your msn blog name, found in the url

            string password = "password"; // your e-mail publishing password

            mw.Credentials = new NetworkCredential(username, password);

           

            net.jorriss.BlogService bservice = new net.jorriss.BlogService();

           

            // Loop from 100 to 234. 234 was the most recent post number.

            for(int i = 100; <= 234; i++) {

              try {

                // replace yourMSNblogkey with the

                MetaWeblogApi.Post msnPost = mw.getPost("yourMSNblogkey" + i.ToString(), username, password);

           

                net.jorriss.BlogPost post = new net.jorriss.BlogPost();

                net.jorriss.ServiceCredentials bcred = new net.jorriss.ServiceCredentials();

           

                bcred.Username = "CSUsername"; // your CS username

                bcred.Password = "CSPassword"; // your CS password

                bcred.SectionName = "blogappkey"; // your CS BlogAppKey

           

                post.Body = msnPost.description;

                post.Date = msnPost.dateCreated;

                post.FormattedBody = msnPost.description;

                post.IsPublished = true;

                post.Title = msnPost.title;

                post.Categories = msnPost.categories;

                post.Syndicate = true;

                post.EnableTrackbacks = true;

                post.EnableComments = true;

                post.EnableAllOwnerNotification = true;

                post.EnableRatings = true;

                post.EnableCrossPosting = true;

                post.SydicateRoot = true;

                post.FeedbackNotificationType = net.jorriss.FeedbackNotificationType.AllFeedback;

           

                bservice.ServiceCredentialsValue = bcred;

                bservice.Create(post);

              }

              catch { // if it errors out no post found

              }

            }

           


          MetaWeblogAPI object structures. Place this in a new .cs file. Taken from Microsoft's MSN Spaces MetaWeblogAPI sample project.

           

          using System;

          using CookComputing.XmlRpc;

          using System.Net;

           

          namespace MetaWeblogApi {

           

            /// <summary>

            /// This struct represents information about a user's blog.

            /// </summary>

           

            [XmlRpcMissingMapping(MappingAction.Ignore)]

           

            struct UserBlog{

              public string url;

              public string blogid;

              public string blogName;

            }

           

            /// <summary>

            /// This struct represents information about a user.

            /// </summary>

           

            [XmlRpcMissingMapping(MappingAction.Ignore)]

           

            struct UserInfo{

              public string url;

              public string blogid;

              public string blogName;

              public string firstname;

              public string lastname;

              public string email;

              public string nickname;

            }

           

            /// <summary>

            /// This struct represents the information about a category that could be returned by the

            /// getCategories() method.

            /// </summary>

           

            [XmlRpcMissingMapping(MappingAction.Ignore)]

           

            struct Category{

              public string description;         

              public string title;

            }

           

            /// <summary>

            /// This struct represents the information about a post that could be returned by the

            /// editPost(), getRecentPosts() and getPost() methods.

            /// </summary>

           

            [XmlRpcMissingMapping(MappingAction.Ignore)]

           

            struct Post {         

              public DateTime dateCreated;       

              public string description;         

              public string title;

              public string postid; 

              public string[] categories;                   

            }

           

            /// <summary>

            /// This class can be used to programmatically interact with a Weblog on

            /// MSN Spaces using the MetaWeblog API.

            /// </summary>

           

            [XmlRpcUrl("https://storage.msn.com/storageservice/MetaWeblog.rpc")]   

           

            class MsnSpacesMetaWeblog : XmlRpcClientProtocol {

           

              /// <summary>

              /// Returns the most recent draft and non-draft blog posts sorted in descending order by publish date.

              /// </summary>

              /// <param name="blogid"> This should be the string MyBlog, which indicates that the post is being created in the user’s blog. </param>

              /// <param name="username"> The name of the user’s space. </param>

              /// <param name="password"> The user’s secret word. </param>

              /// <param name="numberOfPosts"> The number of posts to return. The maximum value is 20. </param>

              /// <returns></returns>

           

              [XmlRpcMethod("metaWeblog.getRecentPosts")]

           

              public Post[] getRecentPosts(

                string blogid,

                string username,

                string password,

                int numberOfPosts){

           

                return (Post[]) this.Invoke("getRecentPosts", new object[]{ blogid, username, password, numberOfPosts});                                   

              }

           

              /// <summary>

              /// Posts a new entry to a blog.

              /// </summary>

              /// <param name="blogid"> This should be the string MyBlog, which indicates that the post is being created in the user’s blog. </param>

              /// <param name="username"> The name of the user’s space. </param>

              /// <param name="password"> The user’s secret word. </param>

              /// <param name="post"> A struct representing the content to update. </param>

              /// <param name="publish"> If false, this is a draft post. </param>

              /// <returns> The postid of the newly-created post. </returns>

           

              [XmlRpcMethod("metaWeblog.newPost")]

           

              public string newPost(

                string blogid,

                string username,

                string password,

                Post content,

                bool publish){

           

                return (string) this.Invoke("newPost", new object[]{ blogid, username, password, content, publish});                                   

              }

           

              /// <summary>

              /// Edits an existing entry on a blog.

              /// </summary>

              /// <param name="postid"> The ID of the post to update. </param>

              /// <param name="username"> The name of the user’s space. </param>

              /// <param name="password"> The user’s secret word. </param>

              /// <param name="post"> A struct representing the content to update. </param>

              /// <param name="publish"> If false, this is a draft post. </param>

              /// <returns> Always returns true. </returns>

           

              [XmlRpcMethod("metaWeblog.editPost")]

           

              public bool editPost(

                string postid,

                string username,

                string password,

                Post content,

                bool publish){

           

                return (bool) this.Invoke("editPost", new object[]{ postid, username, password, content, publish});                                   

              }

           

              /// <summary>

              /// Deletes a post from the blog.

              /// </summary>

              /// <param name="appKey"> This value is ignored. </param>

              /// <param name="postid"> The ID of the post to update. </param>

              /// <param name="username"> The name of the user’s space. </param>

              /// <param name="password"> The user’s secret word. </param>

              /// <param name="post"> A struct representing the content to update. </param>

              /// <param name="publish"> This value is ignored. </param>

              /// <returns> Always returns true. </returns>

           

              [XmlRpcMethod("blogger.deletePost")]

           

              public bool deletePost(

                string appKey,

                string postid,

                string username,

                string password,             

                bool publish){

           

                return (bool) this.Invoke("deletePost", new object[]{ appKey, postid, username, password,  publish});                                 

              }

           

              /// <summary>

              /// Returns information about the user’s space. An empty array is returned if the user does not have a space.

              /// </summary>

              /// <param name="appKey"> This value is ignored. </param>

              /// <param name="postid"> The ID of the post to update. </param>

              /// <param name="username"> The name of the user’s space. </param> 

              /// <returns> An array of structs that represents each of the user’s blogs. The array will contain a maximum of one struct, since a user can only have a single space with a single blog. </returns>

           

              [XmlRpcMethod("blogger.getUsersBlogs")]

           

              public UserBlog[] getUsersBlogs(

                string appKey,

                string username,

                string password){

           

                return (UserBlog[]) this.Invoke("getUsersBlogs", new object[]{ appKey,  username, password});                                           

              }

           

              /// <summary>

              /// Returns basic user info (name, e-mail, userid, and so on).

              /// </summary>

              /// <param name="appKey"> This value is ignored. </param>

              /// <param name="postid"> The ID of the post to update. </param>

              /// <param name="username"> The name of the user’s space. </param> 

              /// <returns> A struct containing profile information about the user.

              /// Each struct will contain the following fields: nickname, userid, url, e-mail,

              /// lastname, and firstname. </returns>

           

              [XmlRpcMethod("blogger.getUserInfo")]

           

              public UserInfo getUserInfo(

                string appKey,

                string username,

                string password){

           

                return (UserInfo) this.Invoke("getUserInfo", new object[]{ appKey,  username, password});                                           

              }

           

              /// <summary>

              /// Returns a specific entry from a blog.

              /// </summary>

              /// <param name="postid"> The ID of the post to update. </param>

              /// <param name="username"> The name of the user’s space. </param>

              /// <param name="password"> The user’s secret word. </param>

              /// <returns> Always returns true. </returns>

           

              [XmlRpcMethod("metaWeblog.getPost")]

           

              public Post getPost(

                string postid,

                string username,

                string password){

           

                return (Post) this.Invoke("getPost", new object[]{ postid, username, password});                                   

              }

           

              /// <summary>

              /// Returns the list of categories that have been used in the blog.

              /// </summary>

              /// <param name="blogid"> This should be the string MyBlog, which indicates that the post is being created in the user’s blog. </param>

              /// <param name="username"> The name of the user’s space. </param>

              /// <param name="password"> The user’s secret word. </param>

              /// <returns> An array of structs that contains one struct for each category. Each category struct will contain a description field that contains the name of the category. </returns>

           

              [XmlRpcMethod("metaWeblog.getCategories")]

           

              public Category[] getCategories(

                string blogid,

                string username,

                string password){

           

                return (Category[]) this.Invoke("getCategories", new object[]{ blogid, username, password});             

              }

            }   

          }

          More Posts Next page »