Rocky Mountain Tech Trifecta v2.0 Call for .NET Speakers

by Erik Lane 18. December 2009 06:45

Rocky Mountain Tech Tri-Fecta v2.0 will be held on February 27th at Metro State College in Denver and we are looking for .NET speakers for the event.  Last years event had over 400 people attend we need speakers who want to deliver great content again this year. 

We encourage you to think about what excites you about .NET and software development and how you can impact software developers with your topic.  Attendees are like you, developers who demonstrate their dedication to their craft by coming to a learning event on a weekend.  Think about the kind of session you would come to see on a Saturday or that topic you've been waiting to speak on...those are the kinds of sessions our attendees are looking for.

Community events like this are a great way to enter the world of speaking and try it out.  If you've thought about speaking before and have a topic you're knowledgeable about, consider taking the next step and submitting a session.  We'll accept as many sessions as we can hold and will work to balance between all levels and topics.  You may (and are encouraged) to submit more than one abstract.

  • The deadline to submit is January 15, 2010
  • Sessions are 75 minutes long, including Q & A.  If you need more time submit 2 parts
  • You can submit a bio along with your abstract to

Don't forget to register for the event and more details can be found on the website.


VisualSVN Server MMC Error

by Erik Lane 2. January 2009 10:14

I’m just posting this in the event it helps someone out in the future. 

  • I have VisualSVN Server installed in Windows 2003 server with the Subversion repositories located on a network share. 
  • The account running the VisualSVN Server service is a domain account that has full control over the repository location.
  • I have no issues with TortoiseSVN from remote machines.

I opened up the VisualSVN Server Manager Manager and received this error

MMC could not create the snap-in”


The Fix

On the server running VisualSVN Server, you need to store the User name and password for the network server that has the repositories. 

Go to Control Panel –> Stored User Names and Passwords:




Click Add and input the logon properties for the network share:



Close and re-open VisualSVN Server Manager and everything should be working now.


Giddy Up!


Merry Christmas 2009

by Erik Lane 25. December 2008 04:27

Taking a few minutes to to wish everyone a very Merry Christmas and I hope that your celebration of Jesus's birth is a great one.

Being of good holiday spirit and a good sense of humor, I would like to share a quote from a famous character in history....Linus from "A Charlie Brown Christmas".  I tried finding the audio clip but it was nowhere to be found.

Luke 2:8-14

And there were in the same country shepherds abiding in the field, keeping watch over their flock by night.  And, lo, the angel of the Lord came upon them, and the glory of the Lord shone round about them: and they were sore afraid.  And the angel said unto them, Fear not: for, behold, I bring you good tidings of great joy, which shall be to all people.  For unto you is born this day in the city of David a Saviour, which is Christ the Lord.  And this shall be a sign unto you; Ye shall find the babe wrapped in swaddling clothes, lying in a manger.  And suddenly there was with the angel a multitude of the heavenly host praising God, and saying,  Glory to God in the highest, and on earth peace, good will toward men.

Categories: Faith and Family

Migrating from Visual SourceSafe to Subversion

by Erik Lane 5. November 2008 13:54

For the the last few years I’ve worked with Visual SourceSafe (VSS), Vault, StarTeam, and Subversion.  For me, the easiest and most straight forward is Subversion (SVN).  Don’t get me wrong, if you come from VSS there is a mind shift to how SVN works but it is well worth it.  After I started my last job and I saw that we still used VSS I immediately started pushing for the change to anything but VSS.

This week I got the approval to start migrating all of our source from VSS over to SVN.  There is a great tool to help with that called VSSMigrate.  Reading through the comments I found that Tim Erickson had created a new version written in C# using SharpSVN (10/22/2008 comment).  Sweet Action!

The tool is really good and does an excellent job.  After running the migration I realized that all of the VSS bindings are still in the project/solution files and that the VSS "*scc" files were in SVN.  I used this codeproject article as the basis for the functionality I added that removes all of the VSS binding information and doesn't import any of the *scc" files. 

I emailed the guys at PowerAdmin and the original author but in the event that it doesn’t get posted anywhere I wanted to make it available.

[update this project is now on Codeplex.  Please post issues or comments there. Thanks!] (8.95 mb)

[update: after Dan's comment here is an x86 version that should work on 64 bit systems]

VssMigrate.Tim2(x86).zip (8.95 mb)

Giddy Up!


Use the Theme Default Gravatar in BlogEngine.NET

by Erik Lane 3. November 2008 13:53

When I was setting up BE.NET I was glad to see it had support for Gravatars.  What I don’t like are the options available for people that don’t have one.  My option was to use MonsterID, Wavatar, or Identicon.  Those are pretty good but I wanted a more generic looking default…and less goofy looking.

So I went in and added an option to use the selected theme’s icon.



I added the option in the admin/pages/Settings.aspx page.  Saving it to the data store works without hitch since it just a name value pair.  Getting the theme’s icon to display requires a little bit of setup.

Theme Default Avatar

You need to add a noavatar.jpg image at the root of your theme’s folder.  Then update the BlogEngine.Core.Web.CommentViewBase.cs file:

   1: switch (BlogSettings.Instance.Avatar)
   2: {
   3:     case "identicon":
   4:         imgLink = gravatar + "identicon";
   5:         break;
   6:     case "wavatar":
   7:         imgLink = gravatar + "wavatar";
   8:         break;
   9:     case "monsterid":
  10:         imgLink = gravatar + "monsterid";
  11:         break;
  12:     default:
  13:         imgLink = gravatar + HttpUtility.UrlEncode(Utils.AbsoluteWebRoot + "themes/" + BlogSettings.Instance.Theme + "/noavatar.jpg");
  14:         break;
  15: }

Giddy Up!


How to Move from .Text (Dottext) to BlogEngine.NET

by Erik Lane 2. November 2008 18:54

Back story

My wife and I's blogs have been running on an archaic customized version of .Text for much longer than it should have.  It did the job so it kept getting moved down the to-do list; not to mention I was not looking forward to the data conversion.  David upgraded the server to x64 and after a few tests it was clear that the blog wasn't going to run.  Briefly, I thought I could just recompile in .NET 2.0 and fix a couple of the stored procedures and be done with it.  Thankfully, I came to my senses and decided it was time to bite the bullet and make the jump to something else.

GraffitiCMS and BlogEngine.NET (BE.NET) were the two that I considered because they each could accept a BlogML file of all existing posts.  That would be awesome if my posts where in a BlogML formatted file.  I checked out Rss2BlogML but it kept failing...something with the formatting of my RSS feed.  I realized that I was spending time on getting my blog into BlogML and I'm not even sure it will produce the results I want (read where Dave Donaldson mentioned an issue with redirects for old links if they are not "named" posts in GraffitCMS).  None of my posts are "named" and I wanted a way to keep/update my old links.  So I started down the path of doing the conversion in a more manual fashion.

BE.NET has a pretty slick BlogImporter web service that abstracts away the data repository and it would've done the trick with just a little bit of coding on my part (highly recommend looking at that option).  I have and understand the .Text database and so hitting the database directly seemed like a logical way to go for me.  When I jumped onto this path I felt that GraffitiCMS was out of the picture because of the redirect issues and, having the code to BE.NET, I felt I could get BE.NET to produce the results I was wanting.

Everything after this assumes that you already run the BE.NET database setup scripts and have the BE.NET source code.


Here are the files that I added or modified as part of this process including the SQL script.

Updating BE.NET Database

Thanks to Dave Burke's migration script most of the work was already done for me.  I will summarize it here but please go read it since he explains the script in detail.  Generally speaking, we are going to add the .Text postID and .Text CategoryID to BE.NET so we can use them to link posts, comments, and categories back together once the data is in the BE.NET database.  I told you you needed to go and read Dave's post.  :-)
Following along like a kid in school, I took good notes and updated the CommunityServer references to the .Text equivalent.  In my script, these are the items that you need to update for your personal settings:

  •     BlogID
  •     Author
  •     Default email address for the comments.

I ran the db script a few different times for each of our blogs so I think it is pretty solid.

Updating BE.NET Post Class

In BlogEngine.Core project I added a DottextPostID property to the Post class.

   1: private int _dottextPostId;
   2: ///<summary>
   3: /// Dottext Post Id to handle migrated links.
   4: ///</summary>
   5: public int DottextPostId
   6: {
   7:     get{ return _dottextPostId; }
   8:     set { _dottextPostId = value; }
   9: }

Update DbBlogProvider Class

In BlogEngine.Core project I modified the DbBlogProvider.SelectPost(Guid id) method to populate the Post object with the DottextPostId value from the database.

   1: string sqlQuery =
   2: "SELECT PostID, Title, Description, PostContent, DateCreated,"
   3: + "DateModified, Author, IsPublished, IsCommentEnabled,"
   4: + "Raters, Rating, Slug, DottextPostID "
   5: + "FROM " + tablePrefix + "Posts "
   6: + "WHERE PostID = " + parmPrefix + "id";
   7: ///
   8: /// unchanged code left out
   9: ///
  10: if (rdr.HasRows)
  11: {
  12:     rdr.Read();
  13:     post.Id = rdr.GetGuid(0);
  14:     post.Title = rdr.GetString(1);
  15:     post.Content = rdr.GetString(3);
  16:     if (!rdr.IsDBNull(2))
  17:         post.Description = rdr.GetString(2);
  18:     if (!rdr.IsDBNull(4))
  19:         post.DateCreated = rdr.GetDateTime(4);
  20:     if (!rdr.IsDBNull(5))
  21:         post.DateModified = rdr.GetDateTime(5);
  22:     if (!rdr.IsDBNull(6))
  23:         post.Author = rdr.GetString(6);
  24:     if (!rdr.IsDBNull(7))
  25:         post.IsPublished = rdr.GetBoolean(7);
  26:     if (!rdr.IsDBNull(8))
  27:         post.IsCommentsEnabled = rdr.GetBoolean(8);
  28:     if (!rdr.IsDBNull(9))
  29:         post.Raters = rdr.GetInt32(9);
  30:     if (!rdr.IsDBNull(10))
  31:         post.Rating = rdr.GetFloat(10);
  32:     if (!rdr.IsDBNull(12))
  33:         post.DottextPostId = rdr.GetInt32(12);
  34:         post.Slug = !rdr.IsDBNull(11) ? rdr.GetString(11) : "";
  35: }

Update UrlReWrite HttpModule

In BlogEngine.Core project I updated the UrlReWrite module to catch any old .Text links that are coming to the site.  By snagging the archive regex expression from the .Text web.config I saved myself some time.

   1: private static readonly Regex DOTTEXT = new Regex(@"/archive/\d{4}/\d{2}/\d{2}/(?<postId>\d+)\.aspx$", RegexOptions.IgnoreCase | RegexOptions.Compiled);

Modify context_BeginRequest
Added an else statement to look for any .Text links.

   1: /// unchanged code left out
   2: ///
   3: else if (url.Contains("/AUTHOR/"))
   4: {
   5:     string author = ExtractTitle(context, url);
   6:     context.RewritePath(Utils.RelativeWebRoot + "default" + BlogSettings.Instance.FileExtension + "?name=" + author + GetQueryString(context), false);
   7: }
   8: else
   9: {
  10:     Match match = DOTTEXT.Match(url);
  11:     if (match.Groups.Count > 0)
  12:     {
  13:         int postId;
  14:         if (int.TryParse(match.Groups["postId"].ToString(), out postId))
  15:         {
  16:             RewriteDottextPost(context, postId);
  17:         }
  18:     }
  19: }

Added ReWriteDottextPost Method

This method locates the right BE.NET post from the .Text post Id in the url, creates the new link, and sends back a response code of 301 so sites know that the link has been permanently moved.

   1: private static void RewriteDottextPost(HttpContext context, int postId)
   2: {
   3:     Post post = Post.Posts.Find(delegate(Post p)
   4:     {
   5:         return p.DottextPostId == postId;
   6:     });
   7:     if (post != null)
   8:     {
   9:         string redirUrl = string.Format("{0}://{1}{2}", context.Request.Url.Scheme, context.Request.Url.Authority, post.RelativeLink);
  10:         context.Response.AppendHeader("location", redirUrl);
  11:         context.Response.StatusCode = 301;
  12:         context.Response.End();
  13:     }
  14: }

Update Links in Content

This step is optional because the updated UrlReWriter will catch any of the old links, to my own content, in my posts but I did it for a clean break from .Text.  Beware that depending on your URL structure (,, etc.) you'll need to update the code so the regex used will catch your specific URL's.  Be sure and backup your BE.NET database or be prepared to do the whole conversion again (like I did) if the links don't turn out the way you want.

Created ConvertDottextLinks.aspx admin page.
This page can go anywhere but I put it in the admin section so it's not open for everyone.  I load up all of the posts in the database, find those which have old .Text links to my own content, find the new BE.NET post for that link, and create the new link for that post.

It is one aspx page with a button and literal on it and here is the code-behind:

   1: public partial class admin_Pages_ConvertDottextLinks : Page
   2: {
   3:     private static readonly List<Post> postList = BlogService.FillPosts();
   4:     protected void Page_Load(object sender, EventArgs e)
   5:     {
   6:     }
   7:     protected void btnGo_Click(object sender, EventArgs e)
   8:     {
   9:         // update this regex with your URL structure.
  10:         Regex regex = new Regex("href\\s*=\\s*(?:\\\"\\d{4}/\\d{2}/\\d{2}/(?<postId>\\d+)\\.aspx)",
  11:             RegexOptions.IgnoreCase
  12:             | RegexOptions.Multiline
  13:             | RegexOptions.Compiled
  14:         );
  15:         int count = 0;
  16:         postList.ForEach(delegate(Post post)
  17:         {
  18:             if (regex.IsMatch(post.Content))
  19:             {
  20:                 string updatedContent = regex.Replace(post.Content, new MatchEvaluator(convertLink));
  21:                 post.Content = updatedContent;
  22:                 post.Save();
  23:                 count++;
  24:             }
  25:         });
  26:         listResult.Text = string.Format("Finished! - {0} links were converted.", count);
  27:     }
  28:     private static string convertLink(Match match)
  29:     {
  30:         int dottextPostId;
  31:         if (int.TryParse(match.Groups["postId"].ToString(), out dottextPostId))
  32:         {
  33:             Post linkPost = postList.Find(delegate(Post post) { return post.DottextPostId == dottextPostId; });
  34:             return "href=\"/post/" + linkPost.Slug + BlogSettings.Instance.FileExtension;
  35:         }
  36:         return match.ToString();
  37:     }
  38: }

Copy Images

This will be totally dependent on how how you store your images.  I've kept all of mine in one folder so mine "just worked" by copying the image folder over.  However, you could update your image links to use BE.NET's image HttpHandler to serve them up.  If it were me, I would do it similar to how I updated the content links.

Update Feedburner

You will need to update Feedburner with the new BE.NET feed URL (


After all of this I have:

  • All of the posts.
  • All of the post comments.
  • All posts are in the correct categories.
  • All old links are caught and redirected.

These steps pretty much sum up what I did to convert a our .Text blogs over to BE.NET.  It's not a point and click operation but it wasn't as painful as I was expecting.

New(er) MSDN Magazine Column

by Erik Lane 22. August 2008 00:07
I've been trying to catch up on my reading and came across a new (since June) column in MSDN magazine that I think is very good and all of us developers can benefit from.  The column is called Patterns in Practice and currently authored by Jeremy Miller from  If you've ever ready any of his blog then you know that Jeremy is a smart guy and usually focuses on topics that are about good programming techniques and not to a specific technology (although he's a .NET guy) and this column is no different.
The articles try to represent a real-world issue and an approach to solve it with tried and true programming patterns (has code samples, etc.).  For me, this gets me thinking of how I could've done something better on a previous project or how I can do something better on current and future projects.  Either way, I hope they get us all thinking of how we can hone our skills and become better developers.
Even if you don't have access to the print version of the magazine they are all available online.

This Day in Geocaching History...

by Erik Lane 22. June 2008 16:52

We began our Geocaching journey 5 years ago on June 22, 2003. In late 2002 I remember seeing a show on the Travel Channel "Top 10 Lost Treasures" and #7 on the list was Geocaching (couldn't find a link). Using a handheld GPS to go "treasure hunting" was very appealing. It wasn't until the following summer when I was looking for something that the entire family could do and would also get us outside.

Being the geek that I am I immediatly started Googling and trying to remember that show or what the sport was called because I could remember the show in my head but I couldn't remember the name.  I guess it didn't take long and the next thing you know I had created us an account on After just a few minutes I was amazed at all of the caches that were around our house. The next step in the process was to buy a GPS.  I found a Magellan Meridian GPS on sale at Fry's and the Wife Acceptance Factor was high since Geocaching was going to be a family sport. We bought the GPS and headed out the following weekend. We didn't take the camera with us on our maiden voyage but we did on our second outing and here is one of those photos.


Fast forward 5 years and here is photo from two weeks ago when were geocaching here in Colorado. Everyone has grown up and we have added another kid to the team...not to mention I look a bit older too.


In the last five years Geocaching has really become common place with outdoor sports and there is software and tools all over the place to help out. My two favorite pieces of software are CacheStats (written in .NET) and Geocaching Swiss Army Knife (GSAK). When we started out we were all about the numbers...trying to find as many as we could and as fast as we could.  After the second year we really slowed down and tried to enjoy the whole caching experience.  Somewhere along the way we decided to start tracking which states we had cached in. Here is the most current map of the states that we've physically found a cache in (35 + Washington DC).


Well, enough memories for now. Since moving to Colorado we have really picked up the caching bug again and are excited about caches out in the mountains that require hiking, etc. and that has increased our enjoyment yet again.  God is good!

Giddy Up!

ReSharper 4.0 beta for VS2008 is Out

by Erik Lane 23. May 2008 05:09


I recieved a notifcation email last night from JetBrains that ReSharper 4.0 beta is out and can be downloaded here.

UPDATE (6/10/08):  ReSharper 4.0 has been released.   Good Stuff!


Don't Wait To Become a Better Developer

by Erik Lane 13. May 2008 02:32
Yesterday I ranted a little about how some just wait until a feature shows up in a Microsoft product before they'll even look at it...and how I use to be that guy. My jumping off point was when I finally took the time to investigate Test Driven Development (TDD). He may not remember it, but Scott Dockendorf was working with me at Healthvision and he gave us a demo on TDD. Like everyone else, I blew over it pretty fast because I knew we weren't going to change our corporate dev style. Soon after he jumped ship for Telligent and never looked back. :-)

When TDD started to click for me I finally woke up and realized that if I was going to be good at my profession then I couldn't wait on my employer (or Microsoft for that matter). This profession moves too fast and for everything I think I know there are 1000 things that I don't know. I'm not an extremist either, meaning that if it has MS attached to the name or process I don't automatically discount it like some. I will, however, take the time to look at ways to increase my productivity and ability to perform my job. It is such a blessing that a company pays me money to write code for a living and that's the least I can do for them.

Giddy Up!