Upgrading my BlogEngine.NET website from 3.1.1.0 to 3.3.80

Upgrading my BlogEngine.NET website from 3.1.1.0 to 3.3.80
Photo by Anete Lūsiņa / Unsplash

Last year I was having trouble upgrading my BlogEngine.NET orginal blog website, prior to moving to the Ghost platform. This article is a copy of the original and about what I did to fix the issue. Even though I no longer use BlogEngine this information may be useful to somebody else.

To upgrade your BlogEngine.NET website, you must log in to the Admin page "http://www.website.com/admin/" and you will get a message on the Home page if you can upgrade or nothing at all.

You can see what I did to get upgraded below and more simply here in my reported issue with the BlogEngine.NET team. Unfortunately they closed it with the suggestion to use a different product.

Now, whenever I go on the admin home page it's really slow when getting the gallery theme list and logged messages, so this picture took some patience to get.

If you get your browser developer tools (F12) open on this page you will notice that it will call this URL http://www.website.com/api/setup?version=3.1.1.0 to get the latest version to upgrade to. In my case "3.3.8.0".

You would then click on the Upgrade button and it will take you to this page "http://www.website.com/setup/upgrade":

"Looks like you already running latest version!"

Of course we know this isn't true. We know there is a new version available.

To track down the issue, I looked for the upgrade page and try to understand what it was doing.
Ah, the http://www.website.com/setup/upgrade/index.cshtml page has three script tags, one of which references Updater.js.

<script src="~/setup/upgrade/jquery-2.0.3.min.js"></script>
<script src="~/setup/upgrade/bootstrap.min.js"></script>
<script src="~/setup/upgrade/Updater.js"></script>

When the page is ready it will check the version

$(document).ready(function () {
    Check();
});

var newVersion = "";

function Check() {
    // CurrentVersionCheckVersion();
    if (!newVersion) { newVersion = ""; }

    if (newVersion.length > 0) {
        $("#spin1").hide();
        $("#spin2").hide();
        $("#spin3").hide();
        $("#spin4").hide();
        $("#spin5").hide();
        $("#spin9").hide();
        $("#step9").hide();
        $('#msg-success').hide();
        $('#spnNewVersion').html(newVersion);
    }
    else {
        $("#frm").hide();
        $("#btnRun").hide();
        $("h2").html("Looks like you already running latest version!");
    }
}

function CheckVersion() {
    $("#spin1").show();
    $.ajax({
        url: AppRoot + "setup/upgrade/Updater.asmx/Check",
        data: "{ version: '" + CurrentVersion + "' }",
        type: "POST",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        async: false,
        success: function (result) {
            newVersion = result.d; // e.g. "3.2.0.0";
        }
    });
}

Note, the CheckVersion function calls "http://www.website.com/setup/upgrade/Updater.asmx/Check" with the current website version value in the POST request.
I needed to see what the newVersion variable is populated with so I added a console.log() call to the success function.

success: function (result) {
	console.log(result);
	newVersion = result.d; // "3.2.0.0";
},
error: function(err){
	console.log(err);
}

But nothing was getting logged so I added an error function.

error: function(err){
	console.log(err);
}

The returned a large responseText value with a HTML page titled "binary dreams | Error".

Ok, there is something wrong happening in the ASMX file. But, what?

This is the summarised class (the ... (dots) replace unused by the Check method) :

[ScriptService]
public class Updater  : WebService {

    private StringCollection _ignoreDirs;
    private List<InstalledLog> _installed;
    private string _root;
    private string _newZip;
    private string _oldZip;
    private static string _upgradeReleases = BlogConfig.GalleryFeedUrl.Replace("nuget", "/Releases/");
    //private static string _upgradeReleases = "http://dnbe.net/v01/Releases/";
    ...
    private string _versionsTxt = _upgradeReleases + "versions.txt";
    ...

    public Updater()
    {
        _root = HostingEnvironment.MapPath("~/");
        if (_root.EndsWith("\\")) _root = _root.Substring(0, _root.Length - 1);

        _newZip = _root + "\\setup\\upgrade\\backup\\new.zip";
        _oldZip = _root + "\\setup\\upgrade\\backup\\old.zip";

        _ignoreDirs = new StringCollection();
        _ignoreDirs.Add(_root + "\\Custom");
        _ignoreDirs.Add(_root + "\\setup\\upgrade");

        _installed = new List<InstalledLog>();
    }

    [WebMethod]
    public string Check(string version)
    {
        try
        {
            WebClient client = new WebClient();
            Stream stream = client.OpenRead(_versionsTxt);
            StreamReader reader = new StreamReader(stream);
            string line = "";

            while (reader.Peek() >= 0)
            {
                line = reader.ReadLine();

                if (!string.IsNullOrEmpty(version) && line.Contains("|"))
                {
                    var iCurrent = int.Parse(version.Replace(".", ""));
                    var iFrom = int.Parse(line.Substring(0, line.IndexOf("|")).Replace(".", ""));
                    var iTo = int.Parse(line.Substring(line.LastIndexOf("|") + 1).Replace(".", ""));

                    if (iCurrent >= iFrom  && iCurrent < iTo)
                    {
                        return line.Substring(line.LastIndexOf("|") + 1);
                    }
                }
            }
            return "";
        }
        catch (Exception)
        {
            return "";
        }
    }

    ...
}

So I started ruling things out. I tried to log the exception messages in the Check() try-catch but nothing was logged let alone returning.
The I set the return values to "test" + number so I would know the failing path and reloaded the upgrade page.

try {
    WebClient client = new WebClient();
    Stream stream = client.OpenRead(_versionsTxt);
    StreamReader reader = new StreamReader(stream);
    string line = "test1";
    
    while (reader.Peek() >= 0)
    {
    	line = reader.ReadLine();
			
        if (!string.IsNullOrEmpty(version) && line.Contains("|"))
        {
            var iCurrent = int.Parse(version.Replace(".", ""));
            var iFrom = int.Parse(line.Substring(0, line.IndexOf("|")).Replace(".", ""));
            var iTo = int.Parse(line.Substring(line.LastIndexOf("|") + 1).Replace(".", ""));

            if (iCurrent >= iFrom  && iCurrent < iTo)
            {
            	return "test2";//line.Substring(line.LastIndexOf("|") + 1);
            }
        }
    }
    return "test3";
}
catch (Exception)
{
    return "test4";
}

Still same error page returned in the Check response. I then commented out everything in the Updater() constructor as the Check method never used any of it anyway and still I'm getting error page response.

Then I had a hunch, it had to be in the class initialisation and this line was the likely culprit:

private static string _upgradeReleases = BlogConfig.GalleryFeedUrl.Replace("nuget", "/Releases/");

So I commented that line out and uncommented the line below it:

private static string _upgradeReleases = "http://dnbe.net/v01/Releases/";

Now I get this object logged in the AJAX success function.

Object { d: "test2" }

This means the happy path was executed and I can undo my previous debugging changes.

Low and behold another refresh and I get the expected page to say I can upgrade!