2010-02-10

My Second SmallBasic program

This one draws a sinus curve (well a cosinus curve):

GraphicsWindow.Title = "Hello World!"
GraphicsWindow.BackgroundColor = "Yellow"
GraphicsWindow.Width = 320
GraphicsWindow.Height = 200
GraphicsWindow.Show()

oldx = 0
oldy = Math.Cos(0) * 100 + 100

For x = 1 To 320
  y = Math.Cos(x/10) * 100 + 100
  GraphicsWindow.DrawLine(oldx,oldy,x,y)
  oldx = x
  oldy = y
EndFor

My first SmallBasic program

Ok, my first was “Hello World”, but this is my first using the GraphicsWindow:

GraphicsWindow.Title = "Hello World!"
GraphicsWindow.BackgroundColor = "Yellow"
GraphicsWindow.Width = 320
GraphicsWindow.Height = 200
GraphicsWindow.Show()

oldx = Math.Sin(0) * 100 + 160
oldy = Math.Cos(0) * 100 + 100

For i = 0.1 To 2 * Math.Pi Step 0.1
  x = Math.Sin(i) * 100 + 160
  y = Math.Cos(i) * 100 + 100
  GraphicsWindow.DrawLine(oldx,oldy,x,y)
  oldx = x
  oldy = y
EndFor

What does it do? It draws a circle. Great huh? Oh I could have used GraphicsWindow.DrawCircle? Amazing stuff :P

Btw SmallBasic may be downloaded from http://msdn.microsoft.com/en-us/devlabs/cc950524.aspx.

2010-02-05

Upgrading EPiServer to MasterPages

Initial Status:
I have already upgraded the EPiServer solution from Visual Studio 2003 / .NET 1.1 to Visual Studio 2008 / .NET 2.0/3.5. First upgraded to VS2005/.NET 2.0 by opening the projects in VS2005 and using the wizard, then converting the project to a web application. Then did the same again, opening the project in VS 2008. Everything seemed to work fine after the upgrade. So next step is to upgrade from using EPiServer:DefaultFramework to using master pages.

Next steps:
I found the (very good I might add) article: http://world.episerver.com/Articles/Items/Experiences-from-migrating-to-EPiServer-461-and-ASPNET-20/ and tried to follow the steps described from the section called “Upgrading your custom templates to ASP.NET 2.0”. However there seems to be some little information missing:

  1. In addition to changing the <@ Control … to <@ Master … you must also in code-behind change the inheritance so that the master page inherits from System.Web.UI.MasterPage in stead of EPiServer.WebControls.ContentFramework.
    This will cause some problems:
    1. If you have any references to CurrentPage, you will need to fix it. I fixed it by creating a new property on the master page called CurrentPage:

      public PageData CurrentPage
      {
          get
          {
              PageBase pb = (PageBase)this.Page;
              return pb.CurrentPage;
          }
      }

    2. Also if you are using any commands that are not prefixed and are using functionality from the previous base class you will need to fix them:
      1. Translate(…) => EPiServer.Global.EPLang.Translate(…)
        I solved this by creating a private function in the master page code-behind, which saved me from changing code in multiple places:
      2. private string Translate(string key)
        {
            return EPiServer.Global.EPLang.Translate(key);
        }

      3. GetPage(…) => EPiServer.Global.EPDataFactory.GetPage(…)
        Again I solved it by creating a private function with the same name:
      4. private PageData GetPage(PageReference pageLink)
        {
            return EPiServer.Global.EPDataFactory.GetPage(pageLink);
        }

  2. The process of converting from the 1.1 style of declaring the controls in code-behind to the 2.0 way using the .designer.cs file is not always working as is should. I had to go into the code-behind file and remove declarations of controls, and then made a slight change to the front master page file, and the saved it, so that the controls using the runat=”server” attribute were (automatically) declared in the designer.cs file. Also some events vere explicitly declared in code-behind (opposed to the new way of using “AutoEventWireup=True”. I just removed them as they were doing nothing anyway.

  3. Also had a small problem due to some additions to the asp.net control gallery and poor naming conventions. The old EPiServer Content Framework files declared a conrtol called simply “Menu”. This name crashes with the “System.Web.UI.WebControls.Menu” web control, so I just changed the name.

And now my web is up and running with EPiServer 4.51 (on VS2008) and using Master Pages (on only one page so far: default.aspx). After changing all aspx-web forms so that they use the new master page, the next step will be to upgrade EPiServer to 4.62B, and thanks to the previously linked article this should hopefully be a piece of cake.

2010-01-29

Moving log files

I am using log4net and other logging in my apps, and the logs are filling up the disks of the test server, so I created a Windows Scheduled Task to move logs to an archive disk, and also delete very old logs from the archive. I move logs older than 2 weeks to the archive and delete logs older than a year from that archive. I created this vb-script (started from the scheduled task) to do the job:

'VBScript that moves old log files from C:\LogFiles to E:\LogArchive

'Folders
Const FOLDER = "C:\LogFiles" 
Const BACKUP_FOLDER = "E:\LogArchive" 

'Objects
Dim objFSO, objFolder, objFolder2, objFile 
Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objFolder = objFSO.GetFolder(FOLDER)

'Loop and move
For Each objFile In objFolder.Files 
  If objFile.DateLastModified < DateAdd("w", -2, Now) Then 
    objFile.Move BACKUP_FOLDER & "\" & objFile.Name 
  End If 
Next

'Delete very old files from target BACKUP_FOLDER
Set objFolder2 = objFSO.GetFolder(BACKUP_FOLDER)
For Each objFile In objFolder2.Files 
  If objFile.DateLastModified < DateAdd("w", -52, Now) Then 
    objFile.Delete
  End If 
Next

Plain old ASP-like code. No Types, everything is just Variant types.

2009-12-16

Check if any new properties have been added in EPiServer 4.x

The scenario for this is that you have a Test server and a Production server. You are rolling out all changes that have been tested on the Test server to the Production server. You did, being a pro and all, of course make a note of all the changes that were done to properties on the Test server since the last rollout to Production, but just to make sure you want to check what new properties have been added.

Step 1

Add the Production server as a linked server in SQL Server Management Studio on the Test server, in this example called [LinkedServer].

Step 2

Create a new query on the Test server and paste the following query into it. You will need to substitute the names of the database and linked server with names from your environment.

-- CHECKS IF ANY NEW FIELDS HAVE BEEN ADDED ON THE TEST SERVER
-- THAT DO NOT EXIST ON THE PRODUCTION SERVER
USE EPiServerDb;
GO

IF EXISTS(
    SELECT testTable.pkID, prodTable.pkID
    FROM tblPageDefinition testTable
    LEFT JOIN [LinkedServer].[EPiServerDb].[dbo].[tblPageDefinition] prodTable 
        ON testTable.pkID = prodTable.pkID
    WHERE prodTable.pkID IS NULL)
BEGIN
    PRINT 'NEW PAGE PROPERTIES DETECTED!'
    SELECT pt.Name, pd.Name
    FROM tblPageType pt JOIN tblPageDefinition pd ON pt.pkID = pd.fkPageTypeID
    WHERE pd.pkID IN (
    SELECT testTable.pkID
    FROM tblPageDefinition testTable
    LEFT JOIN [LinkedServer].[EPiServerDb].[dbo].[tblPageDefinition] prodTable 
        ON testTable.pkID = prodTable.pkID
    WHERE prodTable.pkID IS NULL)
END
ELSE BEGIN
    PRINT 'NO NEW PROPERTIES DETECTED.'
END

Step 3

If any new properties have been added, you will see a list of the names of page templates and what properties are new.

This script was tested on EPiServer 4.61/62 only, but may also work for newer versions of EPiServer.

2009-11-06

Generic Object Factory

The following class is a generic object factory. It is used for creating instances of objects from configured or otherwise provided strings.

The “User Guide” is in the comments.

/// <summary>
/// Generic object factory that creates instances of objects from configured or otherwise provided strings.
/// </summary>
public class ObjectFactory
{
    /// <summary>
    /// Creates an instance of a class from a string "[namespace.[...].className], [component without filname extension],[Version],[Culture],[…]".
    /// </summary>
    /// <typeparam name="T">The type to create.</typeparam>
    /// <param name="configuredClassAndAssembly">Format: [namespace.[...].className], [component without filname extension]</param>
    /// <returns>An object of type T.</returns>
    /// <remarks>This method uses generics!</remarks>
    public static T CreateClassInstance<T>(string configuredClassAndAssembly)
    {
        //Get type to instanciate
        Type tp = Type.GetType(configuredClassAndAssembly, true);

        //load assembly
        Assembly assembly = Assembly.GetAssembly(tp);

        //create class instance
        T instance = (T)assembly.CreateInstance(tp.FullName);

        //return instance
        return instance;
    }
}

I am using it to create instances of objects that implement certain interfaces, so that I can swap the implementation, or even mock it, by changing the configuration.

The string that tells which object to create uses the format of the Type.GetType(string) string.

Some error handling should be added.

2009-10-05

Skjermbrev (in Norwegian)

Jeg kom opp i en problemstilling på jobben der jeg trengte et ord for “bekreftelses-e-post”, og så lurte jeg på hva man da skal bruke, for jeg synes det ser litt rart ut med disse alternativene:

  • bekreftelsese-post
  • bekreftelses-e-post (bryter regel om bruk av bindestrek)
  • bekreftelses e-post (bryter regel om orddeling)

Det er jo anbefalt å bruke ordet “e-post” for det som på engelsk heter e-mail.

Jeg sendte derfor spørsmålet til Per Egil Hegge i Aftenposten, og fikk følgende svar: “Du løser dette ved å bruke mitt favorittord: skjermbrev.”

Så nå vet jeg (og dere) det. Fra nå av skal jeg prøve å snike inn ordet “skjermbrev” alle steder det er mulig :D

2009-10-02

Styles missing in EPiServer Edit/Admin mode

If you ever experience this, it’s probably because EPiServer uses a custom remapping for the 404 – Page Not Found error in IIS. To fix it do the following:

  1. Open IIS manager, and right click on the web site.
  2. Select “Properties” from the dropdown menu.
  3. On the “Custom Errors” tab, scroll down the list until you see “404” in the HTTP Error column.
  4. Double click the 404 entry to open the properties box.
  5. Set the Message type to “URL”.
  6. Type “/util/NotFound.aspx” in the URL text box.
  7. Click “OK”.
  8. Click “OK” in the web site properties dialog to close it.
  9. That’s it, now Bob’s your Uncle!

2009-09-21

EPiServer declines to support XForms on IE8 for CMS 4.x

According to this thread http://world.episerver.com/Forum/Pages/Thread.aspx?id=28931&epslanguage=en it seems that EPiServer is denying responsibility to make XForms on EPiServer 4.x work with IE8 since IE8 was released after EPiServer 4.x.

The customers are experiencing an error when loading XForms with radiobuttons and/or checkboxes. The error is “invalid form” (translated from the Norwegian “ugyldig skjema”).

UPDATE 2011-01-17: Also I have experienced that in IE8, the submit button will not submit the xform which is strange, since it should be calling a javascript function: “return(false)”, and then specifying an action string.

In the comments to this posting, Björn Sållarp has proposed a solution from his blog: http://blog.sallarp.com/episerver-xforms-ie8/

Save power on the cell phone

My HTC S730 is using a lot of power, and has little standby time. Recently it stopped working, so I played with the settings, and by setting the Band Select (“Båndvalg” in Norwegian, and number 3 on the Settings menu) to a fixed value in stead of using the “Auto” option, my phone now uses a lot less power. I selected the “GSM” network type and the “Euro band” band type. My standby time used to be like one to two days, but now its about twice that.

2009-09-11

Getting paths for an application

I am creating an application that needs to load an assembly dynamically from the bin-folder of the application. This is not as straight forward as one might think.

So I tried the following:

string s1 = Directory.GetCurrentDirectory();
string s2 = Environment.CurrentDirectory;
string s3 = Assembly.GetExecutingAssembly().Location;
string s4 = new DirectoryInfo("~/bin").FullName;
string s5 = new DirectoryInfo("/bin").FullName;
string s6 = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string s7 = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
string s8 = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase);

Results:

s1 = s2 = “C:\Windows\system32”

s3 = "C:\\WINDOWS\\Microsoft.NET\\Framework\\v2.0.50727\\Temporary ASP.NET Files\\root\\101551d3\\93890f66\\assembly\\dl3\\f2069ce7\\fe4f0aea_dc32ca01\\MyAssemblyName.DLL"

s4 = "C:\\WINDOWS\\system32\\~\\bin"

s5 = "C:\\bin"

s6 = "C:\\Documents and Settings\\MyMachineName\\ASPNET\\Local Settings\\Application Data" (getting desperate, I know)

s7 = "C:\\Documents and Settings\\MyMachineName\\ASPNET\\Application Data"

Finally found one that worked:

s8 = “file:\\C:\\DevProjects\\…\\MyAppDir\\bin

2009-08-24

Bare linefeeds in SMTP Messages, status 451

I was having a problem with mails that were not being sent as they were supposed to be, and the problem could be caused by the use of bare linefeeds in the message body.

A bare linefeed is a linefeed that has only a linefeed (LF = “\n” in C#/C++/Java, ASCII code 10 decimal) and no carriage return (CR = “\r”, ASCII code 13 decimal).

Internet e-mail standards forbid the use of bare linefeeds, and some mailservers will reject a mail using bare linefeeds, with the status 451 (other mailservers wil accept them and just correct the mistake itself).

In stead of using bare linefeeds, a linefeed should always come with a carriage return (CR + LF = “\r\n”).

Read the full story at http://www.dylanbeattie.net/docs/iis6_bare_linefeed.html.

2009-07-01

TIP: Defragment your VMs and VPCs

I have several VMs (VMWare) and VPCs (MS VPC), and one of them in particular has been performing worse and worse, so I thought it could be good to defragment it.

Now there’s internal fragmentation and there’s external fragmentation (just like indexes in SQL Server :P). The internal fragmentation is handled using the windows defragmentation tool inside the VM or VPC. External fragmentation occurs if you have set your disks to grow incrementally as needed. You could also say that all the space for your virtual disks should be reserved, and if your physical disks were defragmented in the first place, there would be no external fragmentation of your virtual disks. But if you let them grow incrementally, or your physical disk was fragmented when you created the virtual disk, there might be some fragmentation.

So I found this excellent tool from Sysinternals: http://technet.microsoft.com/nb-no/sysinternals/bb897428(en-us).aspx

Now I don’t need to defragment the whole physical disk. I can just defragment one file at a time. Should save me some time :)

How to check if an assembly has been built in DEBUG or RELEASE mode

I found this cool code that checks if an assembly has been built in debug or release mode: http://blogs.msdn.com/jb/archive/2006/06/14/631469.aspx 
It compiles and runs using .NET 1.1, and thats what I used for building it.

I used it on some assemblies in a solution I have, and were somewhat surprised to find that the following assemblies were reported as being debuggable:

  • EPiServer.dll (version 4.62)
  • log4net.dll
  • Microsoft.Web.Services2.dll

This is probably done on purpose (to enable debugging), but it makes me wonder if my applications would run faster if the assemblies were built using Release mode.

2009-06-16

MVVM Toolkit for WPF and Silverlight

Laurent Bugnion has created a toolkit for creating MVVM applications. He says:

“To make development of WPF and Silverlight applications according to the Model-View-ViewModel pattern easier, I have put together a small toolkit which should speed up the creation of such applications by automating certain tasks.”

Here’s the URL: http://geekswithblogs.net/lbugnion/archive/2009/06/14/mvvm-lsquolightrsquo-toolkit-for-wpf-and-silverlight.aspx

2009-06-03

The Web Platform Installer

ScottGu’s last blog post is about the Web Platform Installer: http://weblogs.asp.net/scottgu/archive/2009/06/02/microsoft-web-platform-installer.aspx

Looks like a very useful application for configuring your web server or web development server. It can be downloaded for free from this direct link to the installer.

I also like very much that it integrates with the new Windows Web Application Gallery: www.microsoft.com/web/gallery. I am very likely going to use it very soon.

2009-05-28

Are you mocking me?

I am learning to mock :D. I understand the principle, that you can write your unit tests without any finished methods or data sources (sometimes referred to as TDD). So just looking for nice places to start with Moq. Found a couple of nice links so far:

http://stephenwalther.com/blog/archive/2008/06/12/tdd-introduction-to-moq.aspx

http://blog.objectmentor.com/articles/2009/05/19/a-first-look-at-moq

2009-05-14

Getting started with S#arp Architecture

I am trying to get started with S#arp Architecture, and I found some nice (short) videos at Dime Casts.NET:

Introdction to S#arp Architecture

Another look at Sharp Architecture- Validation, Design Decisions and Automapping

Taking a look at how to modify the T4 templates used by Sharp Architecture

I’ll be looking at them and creating my own test project. Should be good :)

There should also be a good Northwind example available with the downloads from Google Code.

2009-05-12

Microsoft laying off 12 people in Norway

A sad day when even MS has to start downsizing: http://www.digi.no/812605/microsoft-norge-maa-nedbemanne (Norwegian). Good luck to the twelve people laid off in Norway, and to their families.

2009-05-08

TSQL: Checking if an ID is in a Comma Separated String

Ok, so the scenario is that we have a list of IDs, maybe from a checkboxlist, and we want to get the records that match those IDs from a table. So for the sake of this example, I just assume that the list of IDs is passed to my stored procedure as a varchar(8000) string. Using Northwind as an example database, heres an example of how an SP that gets products could look like:

CREATE PROCEDURE GetProducts
@ListOfProductsAsCSVString varchar(8000)

AS

SET @ListOfProductsAsCSVString = ',' + @ListOfProductsAsCSVString + ',';

SELECT ProductID, ProductName FROM Products
WHERE CHARINDEX(',' + CAST(ProductID as varchar(10)) + ',', @ListOfProductsAsCSVString ) > 0;

So what I do is to first append a comma before and after the CSV-list. This is because I need to search for somthing that starts with a comma and ends with a comma, and usually a CSV-list doesn’t have a comma before the first element or after the last one. Then, in my select, I search using the CHARINDEX function for the ProductID prefixed and postfixed by a comma.

Now, please be aware that this could lead to a possible SQL Injection attack, if you use this procedure uncritically without validating the input before passing it to this stored procedure, so use with caution.