Migrating to .Net7

Nov 17, 2022 EST by:   Tim Stanley

On November 8, 2022, Microsoft released .Net 7.  After getting Visual Studio Professional 17.4 installed, updating to .Net 7 was fairly painless.

Changing the obligatory TargetFramework entry in all the projects:


Updating the package references from 6.0.0 to 7.0.0:

<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.0" />

Updating the github action yml file to use the new dotnet version:

dotnet-version: '7.0.x'

Azure even had all the website hosting ready so I didn't have to wait for anyone to deploy .Net 7. Microsoft does list some incompatabilities in .Net 7, but it's not a long list. This has probably been the easiest migration since .net46 to .net48.


Related Items

Building An Azure Dev Test Lab Series

Sep 17, 2022 EST by:   Tim Stanley

Microsoft has a very large quantity of documentation on Azure. But most of those articles are focused on new large scale production scenarios, or migrating existing production scenarios to Azure. For a software development firm that is looking only to leverage Azure for software development and testing, and not expose public web services to the internet, where does one start?

The Micorosft documentation that I've read leads one to believe that it's a simple as just creating an Azure VM or an Azure Web service and your done. The reality is there is much more infrastructure required to do that. This series attempts to put together a roadmap or summary of some solutions aimed solely toward software development for Enterprise services and applications. You may find it helpful for preparing your Azure migration or if you have some services in Azure extending it.


Azure is a big world. In order to narrow down the scope of things, I'm going to create a narrow set of assumptions to build a development and test lab in Azure.

  • Software development teams are distributed in multiple locations in Europe, Asia, and the United States.
  • There is an existing Windows on premesis Active Directory system in place for Authentication.
  • There is an existing Windows network system in place in at least three physical locations / offices.
  • There is an existing Wide Area Network system in place between the physical locations / offices.
  • There are existing file shares / network shares in place for software distribution and storage.
  • The software development team utilizes Visual Studio 2022 Professional.
  • There is an extremely large source code base in Microsoft Team Foundation Server.
  • The development lab utilizes Microsoft Hyper-V Virtual Machines for dev / test servers.
  • There is an extremely large code base of web based services used for an Enterprise Suite of applications.
  • Microsoft Office 365 (hosted in the cloud) is used throughout the company for email and team communication.
  • All remote access to Azure systems requires Multi Factor Authentication.
  • No "production" and no "public" facing websites, databases or services.
  • For Dev Test Labs, no load balancing or hot failover and no region failover.


  1. Building An Azure Dev Test Lab Why Azure
  2. Building An Azure Dev Test Lab Authentication
  3. Building An Azure Dev Test Lab Azure Devops
  4. Building An Azure Dev Test Lab DataCenters
  5. Building An Azure Dev Test Lab Networking
  6. Building An Azure Dev Test Lab File Shares
  7. Building An Azure Dev Test Lab App Services
  8. Building An Azure Dev Test Lab Virtual Machines
  9. Building An Azure Dev Test Lab Remote Access
  10. Building An Azure Dev Test Lab Azure SQL

Related Items

Migrating To .Net6 and Azure

Sep 02, 2022 EST by:   Tim Stanley

In 2022, I decided to make a significant update the the code base and hosting platform used by this site.  I decided to migrate to .Net 6 and host it on Azure.

I could have taken the old site to Azure, but I wanted to start with a cleaner code base. I removed some of the old dependencies, libraries and assumptions to lighten up as much as possible.  A general list of the new requirements:

  • Store content as XML or JSON.
  • Do not require the use of a database.
  • Provide support for as much of the original content as possible.
  • Remove dependencies on third party packages as possible.

The main course of effort was the original site was written in ASP.Net Web forms.  The new site was written in ASP.Net Core Razor pages in C#.

Some interesting points:

  • Start: 2022 06 10
  • End: 2022 07 31
  • 32 days of working changes, a few hours on nights & weekends
  • Occurred over 50 calendar days
  • The equivalnet of about 15-20 full time equivalent working days
  • 15,552 Lines of Source Code
  • 4,438 Lines of Executable Code
  • Go Live: 2022 08 28

Here is a summary of some of the key points of the new site:

  • Developed using Visual Studio 2022
  • Targets .Net 6
  • ASP.Net Core Razor Pages
  • Content / object model is all XML based
  • Supports pages, posts, tags, categories, authors, and site statistics
  • Uses Azure DNS
  • Uses Azure App Services / an Azure Website for hosting the site
  • Uses GitHub Azure integrations to publish software updates to Azure
  • Uses prism.js for code formatting
  • Uses tinymce for content editing
  • Uses bootstrap for a CSS styling.
  • Some moving parts were greatly influenced by Miniblog.Core. This site is not a derivative of Miniblog.Core, but I did use some of the ideas as a base for this sites code base.
  • The Table Of Content generator leverages the HtmlAgilityPack

A few things about Azure I learned along the way.

Pick carefully what Azure Datacenter you want for hosting. Not all Azure Datacenters have the same features, or the same pricing and you cannot easiliy mix parts from other Azure Datacenters.  For example, once your publishing a site from Github to Azure, moving that Azure Website to another Azure DataCenter basically requires configuring everything back from scratch.

Using an Azure Static Website is really for a "static" site.  A dynamic site that runs ASP.Net Core isn't suited for a Azure Static Website.

Using GitHub actions to publish to Azure is a timesaver.  However, each action stores the result as storage, and if your not careful, very quickly you will exceed the 500 MB storage limit for "free" GitHub repositories.

Azure App Services provide several layers of scalability for the Azure Hosting Plans.

Using Azure App Services / Azure Websites for a Developer Lab Instance provides a free hosting service (F1), an SSL certificate, and is extremely helpful for go live preparation.  The D1 service plan provides the bare bones minimum to host a non azure domain name.

You can't get an SSL certificate (even if you buy one) on a custom domain name on the F1 or D1 service plan.  Microsoft tells you that a B1 service plan or higher is needed.

The D1 service plan provides:

  • 1 GB of memory
  • 240 minutes / day compute

The D1 service plan is more than enough power to drive this website.  It uses about 250-350 Mb of memory (everything is store in memory since there is no database). Because everything is stored in memory it barely uses any compute time.

The positives of moving to Azure App Services:

  • Github Actions to publish to Azure is a great timesaver.
  • Azure DNS is much easier to administer than other DNS services I've used.
  • The minimum D1 plan is still screamingly fast.
  • The Azure monitoring provides some usefull analysis tools.

The only negative I've experienced so far with Azure is that it tries to steer the creation to a default S1 plan.  If you accidentally setup an S1 plan, and remove it from you site, you still pay for the plan until you remove it from the subscription.  If you don't pay attention, you can quickly run up a hefty bill.  Few people really need an S1 hosting plan to start a small website.

Related Items

2010 Era Blog Platform Retired

Sep 01, 2022 EST by:   Tim Stanley

This site ( was first started in February 2006. It first went publicly live October 8, 2007.  The engine used to power this site was used from 2006 to 2022. The main technology really hadn't been modified since 2010. Not bad for a sixteen year run.

In 2022, this site was updated, but this is a summary of the underlying technology that powered this site for sixteen years.

Original Site Platform

Original Blog Platform

The site utilized BlogEngine.Net with several Extensions.  Some custom controls are used on a lot of the pages.

As I developed one site, I had another, then another, then another. Before long I was spending more time applying patches / changes to the main code base and distributing it to all the sites than I was on content. That lead me to try to focus on one code base for multiple websites and that eventually led to a multi-tenant solution.

The main portions of BlogEngine.Net provided a solid basis, but it was heavily modified to support a multi-tenant blog platform.  That meant some pretty significant changes to the model and code base.  What was left had it's origins in BlogEngine.Net but it was pretty significantly different than BlogEngine.Net.

Related Items

Use HostingEnvironment.MapPath

Jun 25, 2010 EST by:   Tim Stanley

When running a service under IIS, the HttpContext.Current object is not available, so HttpContext.Current.Server.MapPath will fail.

fileName = HttpContext.Current.Server.MapPath(fileName);

The solution is to use Hosting.HostingEnvironment.MapPath instead.

fileName = System.Web.Hosting.HostingEnvironment.MapPath(fileName);

Related Items

Custom Controls In ASP.NET

Feb 26, 2010 EST by:   Tim Stanley has that neat little feature where all the controls can start with <asp:.  It makes it easy to code.  I had numerous custom controls and I always had to register the control on each page to use it.  Scott Guthrie had a great tip on how to register the controls in the web.config file so that it doesn’t have to be done in each page.


I’m really surprised I haven’t read about this earlier.


Related Items

Windows Live Writer XMLRPC and BlogEngine.Net

Feb 26, 2010 EST by:   Tim Stanley

BlogEngine.Net supports XMLRPC and the MetaWeblog API.  This allows it to support other tools like Windows Live Writer.  But where are the specifications for the API and WLW found?  I came across some interesting related links along the way in trying to figure out how to add proper slug support for pages in BlogEngine.Net.

WordPress outlines the definitive guide to the WordPress API at  This includes:

  • wp.getTags
  • wp.getPage
  • wp.getPages
  • wp.newPage
  • wp.deletePage
  • wp.editPage
  • wp.getCategories
  • wp.getAuthors

Several other API’s are listed on the site.  The reference is the only tool I’ve found that outlines the structures used for XMLRPC for the MetaWeblog API.

Windows Live Writer outlines the list of all the options, capabilities supported between the MetaWeblog, MoveableType, and Wordpress systems in their article Defining Weblog Capabilities with the Options Element.

In BlogEngine.Net the Windows Live Writer manifest is defined in the file wlwmanifest.xml.  This can be extended to support some of the additional options supported by WLW.  However, additional code is required in the BlogEngine.Net XMLPCRequest, XMLRPCResponse and MetaWeblog files to support these features.

One of the interesting design decisions about BlogEngine.Net is that it supports XML files and uses a Guid as the ID for all posts and pages.  The MetaWeblog API wants to use an int for the ID.  This causes some unexpected results when selecting a parent, or the author in page editing mode with WLW.  This is just a design tradeoff of not using a database (sequential ID’s are difficult and cumbersome to generate without a database).

Interestingly enough, there is an unusual nuance either in the API or WLW, in that in order to get a hierarchical indented list in the dropdown list of pages, XMLRPCResponse.WriteShortPages needs to set the wp_page_parent_id to the “title” and the page_parent_id to the “guid” of the page. It seems a bit backwards to me.

I’ve extended the MetaWeblog API in BlogEngine.Net to support slugs properly.  The trick was using value wp_slug in the XML for the same as the post code does.

Code added from XMLRPCResponse.WritePage and WritePages.  The MWAPage class must also add the slug properly to support this.

// wp_slug
data.WriteElementString("name", "wp_slug");
data.WriteElementString("string", _page.slug);

I’ve published the changes to the MetaWeblog API but keep in mind these changes go way beyond just this change and break compatibility with BlogEngine.Net.

Download: (15.98 kb).  Includes XMLRPCRequest, XMLRPCResponse, and MetaWeblog changes.


Related Items