Friday 24 December 2010

Android 2.2 update breaks 3G on O2

So my HTC Magic got the Froyo update last week. The problem was that it broke "the internet".

I thought it was due to the fact that my phone was an Australian Vodaphone branded HTC Magic and the update was through a UK network intended for UK/European versions of the phone. I was going to get a new phone anyway (The Nexus S) so I didn't mind, and put it aside for a later date.

Well it turns out that the mobile internet was also broken on the Nexus S (see my previous blog). In any case, once I fixed the configuration issue on the Nexus, I tried the settings on the HTC and it worked! So here are the settings I used:

APN: payandgo.co.uk
username: payandgo
password: password
MCC: 234
MNC: 10
APN type: internet

Leave everything else blank! Even the proxy!

Hopefully this works for you.

Mobile internet on Nexus S with O2 is broken

I bought the new (Samsung) Google Nexus S this week. I have to say that it is amazing! It is faster and more responsive than anything I have tried. The only problem I had was that the mobile internet was not working with the retrieved settings.

After googling the hell out of this, checking the manual settings on the O2 website, and even calling tech support, I finally figured out that the settings on the website AND the ones tech support told me were wrong.

Without any further adue, I give to you...

APN: payandgo.co.uk
username: payandgo
password: password
MCC: 234
MNC: 10
APN type: internet

If you're having this issue, hopefully these settings will do the trick.

Thursday 16 December 2010

Cannot delete document type - Umbraco

This has been my week of Umbraco database corruption hell!

Today I wanted to delete a document type that just didn't want to budge. There was nothing in the log table, so I opened up firebug and saw this little error:


{"Message":"Umbraco Exception (DataLayer): SQL helper exception in ExecuteNonQuery","StackTrace":" at umbraco.DataLayer.SqlHelper`1.ExecuteNonQuery(String commandText, IParameter[] parameters)\r\n at umbraco.cms.businesslogic.ContentType.Tab.Delete()\r\n at umbraco.cms.businesslogic.ContentType.delete()\r\n at umbraco.cms.businesslogic.web.DocumentType.delete()\r\n at umbraco.nodetypeTasks.Delete()\r\n at umbraco.presentation.create.dialogHandler_temp.Delete(String NodeType, Int32 NodeId, String Text)\r\n at umbraco.presentation.webservices.legacyAjaxCalls.Delete(String nodeId, String alias, String nodeType)","ExceptionType":"umbraco.DataLayer.SqlHelperException"}


I started to delete the properties and tabs manually. Umbraco crashed when trying to delete a tab. It was another foreign key issue.

So again, the solution was to change a delete rule (see my last 2 posts). This time it was cmsPropertyType_cmsTab. I changed it to cascade.

Now I was able to delete the tab as normal.

After that tab was deleted, I was able to delete the document type.

I win again!


Wednesday 15 December 2010

The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPreviewXml_cmsContentVersion". - Swap Master Doc Type Error in Umbraco

Today is my day of Umbraco database hell!

I tried to swap a master doc type. I clicked ok, confirm, yes, ok etc and then nothing!

I looked into the error logs and came cross this:


At /umbraco/theoutfield/doctypeextensions/dialogs/SwapMasterDocType.aspx?id=1071&rndo=27.8 (Referred by: http://localhost/umbraco/theoutfield/doctypeextensions/dialogs/SwapMasterDocType.aspx?id=1071&rndo=27.8): System.Data.SqlClient.SqlException: The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPreviewXml_cmsContentVersion". The conflict occurred in database "LOTUS_DEV", table "dbo.cmsPreviewXml", column 'versionId'. The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPreviewXml_cmsContentVersion". The conflict occurred in database "LOTUS_DEV", table "dbo.cmsPreviewXml", column 'versionId'. The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPreviewXml_cmsContentVersion". The conflict occurred in database "LOTUS_DEV", table "dbo.cmsPreviewXml", column 'versionId'. The statement has been terminated. The statement has been terminated. The statement has been terminated. at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection) at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj) at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) at System.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean async) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe) at System.Data.SqlClient.SqlCommand.ExecuteNonQuery() at TheOutfield.UmbExt.DocTypeExtensions.Dialogs.SwapMasterDocType.DoSwitch() at TheOutfield.UmbExt.DocTypeExtensions.Dialogs.SwapMasterDocType.btnConfirm_Click(Object sender, EventArgs e) at System.Web.UI.WebControls.Button.OnClick(EventArgs e) at System.Web.UI.WebControls.Button.RaisePostBackEvent(String eventArgument)



The solution is identical to my previous post...

Open up SQL Management Studio.
Change delete rule for the relationship between cmsPreviewXml and cmsContentVersionto "cascade".


Now you can swap those master doc types!



The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPropertyData_cmsPropertyType" - Umbraco

The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPropertyData_cmsPropertyType".



This was incredibly painful!

It occurs when you try to delete a property form a document type.

Here is a quick fix that does not involve manually deleting things....


Open up SQL Management Studio.
Change delete rule for the relationship between cmsPropertyType and cmsPropertyData to "cascade".

DONE!


Friday 10 December 2010

Reseeding Umbraco

Back when I was working at The Farm we needed to do some sweeping changes to an existing Umbraco site.

To make sure the new content you upload does not conflict with additions the client makes during the development time, you must do the following... Take a back up of the live db for development, then reseed the tables of your new development db to a number much much higher. This allows you to synch up the database changes when it comes to deploy time. We reseeded the primary keys of some key tables to 500,000. (see http://www.farmcode.org/post/2009/09/09/How-to-sync-data-across-multiple-Umbraco-environments.aspx).

The issue we had though was that the time between reseeding and deployment turned out to be 3 months and the reseeding was no longer high enough. We learned this the hard way.

Today I'm about to begin the whole process on another existing Umbraco site, so I decided to check the current seeds.

Here is the script I used:

SELECT IDENT_SEED(TABLE_NAME) AS Seed,
IDENT_INCR(TABLE_NAME) AS Increment,
IDENT_CURRENT(TABLE_NAME) AS Current_Identity,
TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), 'TableHasIdentity') = 1
AND TABLE_TYPE = 'BASE TABLE'


It turns out that in just over 2 months, the cmsPropertyData and umbracoLog tables had current seeds of 306208 and 145973 (respectfully).

Final deliverables for this site are not until March 2011. So it seems that a reseed of even 1,000,000 might not be enough.

So I've decided to reseed to 10,000,000

Here is all I needed to run:
DBCC CHECKIDENT (cmsContent, reseed, 10000000)
DBCC CHECKIDENT (cmsContentVersion, reseed, 10000000)
DBCC CHECKIDENT (cmsPropertyData, reseed, 10000000)
DBCC CHECKIDENT (umbracoNode, reseed, 10000000)
DBCC CHECKIDENT (umbracoLog, reseed, 10000000)



Saturday 13 November 2010

jQuery 1.4.4 Released

All I can say is...

.fadeToggle()

FINALLY!!!

Wednesday 11 August 2010

Print this!

I have had some interesting discussions lately about web design, clients and coding in general.

My friend and I were talking about interface design and cool JQuery effects. I showed him a site I built which had a bajillion hidden divs which were displayed when the user hovers over and clicks on certain images, text and buttons.

I told him that the problem with pages that have a whole bunch of hidden content which is displayed by hovering and clicking etc is that when a user wants to print the page, what do you print? What if there are 10 pages worth of text and images (and a video)? The printed page is never going to look like it does on the screen. I know that there are CSS files for printing, but those types of pages are horrible to write them for.

My friend's answer: "It's a website. Why do people need to print it? You print word documents and pdf's. Why do you need to print a webpage? Seriously!"



Thursday 1 July 2010

Formsy

Over the last few months I have been working on an open source forms engine I call Formsy.

"Formsy is an XML driven forms engine built with ASP.Net 3.5. Formsy is super easy to use, is completely extensible and generates clean markup for easy styling."

Today I finally launched it on Codeplex.

Formsy came about after my experiences with Umbraco Contour. I had to do some crazy code to get Contour to do things it was really not meant for. It was a real nightmare. Getting Contour to regionalize form labels, validation messages, and validation regular expressions was the least crazy thing we needed to do.

After the Contour experience I realized that I needed some practice with composite controls. So I started to make a little forms engine. Before long, I had all the extra functionality that we required in Contour (eg. custom data storage, custom emails to name just two). At that point I realized that Formsy might be useful to other people. So I set out to add even more functionality.

So here I am 3 days away from my flight overseas launching my Codess-Opess.

I think it's pretty rad.




Saturday 27 March 2010

Regionalizing validation messages, and regex in Umbraco Contour




Umbraco Contour is a great package for ultra fast building of forms. What we used it for was not entirely what it was meant for.

We were asked to build a form where labels, validation messages AND the regular expressions to validate phone numbers were all regionalized. Contour uses Umbraco's dictionary to store regionalized labels, so we decided to store our validation messages and regex there.

Here is how we did it all...

Firstly, we name our field's in the form #Form_FirstName, #Form_LastName etc. In the dictionary, add your languages. Then create items with the same names as the form fields (without the #). This allows Contour to replace your labels. We create two matching items to handle regionalized values for validation messages and regex: #Form_FirstName_vmsg, and #Form_FirstName_regex respectively.

Contour installs RenderForm.ascx under \usercontrols\umbracoContour\ in your project. Noticing this, you can easily change it's CodeBehind property to your own "RenderForm.ascx.cs" which you inherit from Contour's. Overriding OnPreRender() is where the magic happens.

The code is pretty self explanatory. We override OnPreRender(), loop through the fields, use their caption property and a suffix ("_vmsg" or "_regex") to get the values from the dictionary.

Here is the code...



public class RenderForm : Umbraco.Forms.UI.Usercontrols.RenderForm
{
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);

// get the form fields
FormStorage fs = new FormStorage();
var form = fs.GetForm(new Guid(this.FormGuid));
var fields = form.AllFields;

foreach (var f in fields)
{
// get this field's validator
var fieldId = f.Id.ToString();
var vals = Page.Validators
.Cast()
.Where(x => x.ControlToValidate == fieldId).ToList();
if (vals.Count > 0)
{
foreach (var baseVal in vals)
{
// get the validator type and assign properties
BaseValidator val = baseVal as RegularExpressionValidator;
if (val != null) // it is RegularExpressionValidator
{
// get regionalized regular expression
string valExpression = GetRegionalizedValidationText(f.Caption, "_regex");
((RegularExpressionValidator)val).ValidationExpression = !string.IsNullOrEmpty(valExpression) ? valExpression : ((RegularExpressionValidator)val).ValidationExpression;
}
else // either a RequiredFieldValidator or another type which you must handle here!
{
// cast to another Validator type you are expecting, then set it's properties
}

// Get the error message
val = baseVal as BaseValidator;
if (val != null)
{
// get regionalized error message
string errorMessage = GetRegionalizedValidationText(f.Caption, "_vmsg");
val.ErrorMessage = !string.IsNullOrEmpty(errorMessage) ? errorMessage : val.ErrorMessage;
}
val.ValidationGroup = form.Name;
}
}
}
}


// Uses's the given string and suffix to get a value from the Umbraco dictionary.
public string GetRegionalizedValidationText(string key, string type)
{
if (key.Contains("#"))
{
string itemName = key.Split('#')[1] + type;

if (umbraco.library.GetDictionaryItem(itemName) != null) // note: item can exist and be ""
return umbraco.library.GetDictionaryItem(itemName);
}
return ""; // key does not contain #, or not found in dictionary
}
}



-- Copied from my post on Farmcode.org.





Monday 1 March 2010

Flv mime type in IIS


I had to put a site live which had flv's that 404'd. From past experience I knew that it was a mime type issue. So I Googled the mime type for flv (video/x-flv) and added it to IIS. However it did not work.

It turns out that the correct correct definition for the mime type is actually:flv-application/octet-stream



Go figure!


Wednesday 10 February 2010

Publishing PDF's from Visual Studio 2008

Here's something that annoyed me for a while. In VS2008 even when you include PDF's in the solution, when you hit publish, it doesn't copy them to the destination.

Here's how to fix it.

In the Solution Explorer, right-click the file and select Properties.
In the Properties window change Build Action to "Content"
Change Copy to Output Directory to "Copy always".

Done!

*Hint you can select multiple files but you cannot select a folder.

Wednesday 3 February 2010

Freeing up space on Windows Server

Yesterday we went to install service pack 2 on a Windows Server 2008 machine. It turns out you need at least 5GB free on C: which we didnt have. After deleting everything we possibly could, including running CCleaner and making the Page File non-existant we were still 400MB off the mark.

Then I noticed a system file c:\hiberfil.sys which was 3GB.

Well it turns out that Windows Server 2008 still allocates space for a hibernate file. Who would want to hibernate their Live server?

Anyway, this is how to gain an exta 3GB...

C:\Users\Administrator>powercfg.exe /hibernate off

That's it!

Monday 25 January 2010

Problem: Inserting custom media types in the WYSIWYG of Umbraco 4.0.2.1 shows blank.gif instead of the correct Url



The Scenario
We had a custom media type called Image. We did this to store more information about each image that was uploaded.

The Problem
The CMS user wants to insert the image to the WYSIWYG of one of the content nodes but sees blank.gif inserted into the Url field when they click on the custom media type. This does not occur for standard Umbraco files.

Investigation
I used Charles to see what Umbraco was doing when a user clicks. Umbraco makes a call to ~/umbraco/dialogs/imageViewer.aspx to get the url. Let's take a look at the source code...

protected void Page_Load(object sender, System.EventArgs e)
{
 //Response.Write(umbraco.helper.Request("id"));
 //Response.End();
 // Put user code to initialize the page here
 if (Request.QueryString["id"] != null) 
 {
  if (Request.QueryString["id"] != "")  
  {
   //TODO: fix Nasty FAST'N'CANELINE HACK. ..
   int MediaId = int.Parse(Request.QueryString["id"]);
   
   image.Controls.Clear();
   int fileWidth = 0;
   int fileHeight = 0;
   string fileName = "/blank.gif";
   string altText = "";

   try 
   {
    cms.businesslogic.media.Media m = new cms.businesslogic.media.Media(MediaId);

    // TODO: Remove "Magic strings" from code.
    try 
    {
     fileName = m.getProperty("fileName").Value.ToString();
    } 
    catch 
    {
     try 
     {
      fileName = m.getProperty("umbracoFile").Value.ToString();
     } 
     catch 
     {
      fileName = m.getProperty("file").Value.ToString();
     }
    }

    altText = m.Text;
    try 
     {
     fileWidth = int.Parse(m.getProperty("umbracoWidth").Value.ToString());
     fileHeight = int.Parse(m.getProperty("umbracoHeight").Value.ToString());
     }
    catch {
    
    }
    string fileNameOrg = fileName;
    string ext = fileNameOrg.Substring(fileNameOrg.LastIndexOf(".")+1, fileNameOrg.Length-fileNameOrg.LastIndexOf(".")-1);
    string fileNameThumb = GlobalSettings.Path + "/.." + fileNameOrg.Replace("."+ext, "_thumb.jpg");
    image.Controls.Add(new LiteralControl("<a href=\"" + GlobalSettings.Path + "/.." + fileNameOrg + "\" title=\"Zoom\"><img src=\"" + fileNameThumb + "\" border=\"0\"/></a>"));
   } 
   catch {
   }
   image.Controls.Add(new LiteralControl("<script>\nparent.updateImageSource('" + GlobalSettings.Path + "/.." + fileName.Replace("'", "\\'") + "','"+altText+"','" + fileWidth.ToString() + "','" + fileHeight.ToString() + "')\n</script>"));
  }
 }
}



Let's ignore the shamefullness of the code. We've all had our bad moments, and open source projects are bound to have some things like this. Lets comment on what the code does.

Notice this line:
string fileName = "/blank.gif";
Now notice that the bottom catch is empty. This catch is hit whenever a file does not have one of these attibutes:fileName, umbracoFile, file. So filename is never set to anything.

The solution
The last catch needs to get your custom media type. In our case:
Media m = new Media(MediaId);
fileName = m.getProperty("Image").Value.ToString();

That is the fix for Umbraco. So you have a couple options on how to implement it.

1. You can recompile Umbraco's source then redeploy.

2. If you don't want to recompile Umbraco you can can create a new file called ImageViewer.cs that inherits from umbraco.dialogs.imageViewer. Copy and paste the code, do your fix, then modify the ~/umbraco/dialogs/imageViewer.aspx file to inherit from your new file.

I.e. Change the header:
<%@ Page Language="c#" CodeBehind="imageViewer.aspx.cs" AutoEventWireup="True" Inherits="umbraco.dialogs.imageViewer" %>

To this:
<%@ Page Language="c#" CodeBehind="MyImageViewer.aspx.cs" AutoEventWireup="True" Inherits="My.Project.UmbracoExtensions.MyImageViewer" %>

The downside of both methods is that you will overwrite your changes if you upgrade Umbraco.


The awesome solution
Here is a solution that is awesomely hilarious. Using the already installed Urlrewriting.Net module that comes with Umbraco.

1. Create a new file called ImageViewer.aspx in your project somewhere. Mine was in ~/UmbracoExtensions/

Make the code behind inherit from umbraco.dialogs.imageViewer. Copy and paste the code, do your fix.

2. Open ~/config/UrlRewriting.config and add this entry:

<add name="ImageViewer"
          virtualUrl="~/umbraco/dialogs/imageViewer.aspx(.*)"
          rewriteUrlParameter="IncludeQueryStringForRewrite"
          redirectMode="Permanent"
          destinationUrl="~/UmbracoExtensions/ImageViewer.aspx$1"
          redirect="Application"
          ignoreCase="true" />

This redirects ~/umbraco/dialogs/imageViewer.aspx to your new ~/UmbracoExtensions/ImageViewer.aspx and passes the query string which allows the lookup of the file.

3. Open your ~/web.config and add /UmbracoExtensions/ to your umbracoReservedPaths under appSettings. This allows your newly created file to be redirected to.

That's it!

I find this solution absolutely hilarious! But it means I will not get undone by an upgrade. Hopefully they will eventually fix the imageViewer class to look for other files.

UPDATE
Ok after all that, I found out that you just need to change the alias name in the cmsPropertyType in the database.

First check if your file alias is being used more than once. In our case we had an Image file type, and a field in a document type called Image. So we have to modify the correct one.

Here is how to check your table:
SELECT * FROM [YOUR_DATABASE].[dbo].[cmsPropertyType]
  WHERE Alias LIKE 'Image'

To figure out which was which I did this really lazily. I had a synced db already on dev, so I just changed the alias of one to see if it would change in Umbraco. Note that you must bump the config for the alias to change in Umbraco.

Here is the sql to update your file type alias:
UPDATE [YOUR_DATABASE].[dbo].[cmsPropertyType]
  SET Alias = 'umbracoFile'
  WHERE Alias in ('YOUR_FILE_TYLE_ALIAS') // for multiple file types
  AND id !=  // line is optional


So it turns out there was no coding involved after all. Well at least I learned heaps about how Umbraco was structured :)



Saturday 23 January 2010

How to insert a link tag in Blogger / Blogspot html - Hacking Blogger without JQuery



In my previous post I showed how it was possible to insert a CSS file into the head element of a Blogger / Blogspot page, at load time using JQuery. This is useful because Blogger does not allow you to add <link> tags in the "Edit HTML" tab.

I decided that JQuery was a bit overkill. Ok shitloads overkill. It's better to just do it with a small amount of javascript. The following code will insert a <link> tag into the head at load time.

function insertCSS(filename) {
    var link = document.createElement("link")
    link.setAttribute("rel", "stylesheet")
    link.setAttribute("type", "text/css")
    link.setAttribute("href", filename)
    document.getElementsByTagName("head")[0].appendChild(link)
}
insertCSS("http://your.site/tools/libraries/prettify.css");

I'm talking within the context of being able to prettyprint your code, so I put this code into a file called bloggerPrettifyHack.js. This allows me to simply include 2 javascript files - bloggerPrettifyHack.js, and prettify.js.
<script type="text/javascript" src="http://your.site/tools/libraries/bloggerPrettifyHack.js"></script>
<script type="text/javascript" src="http://your.site/tools/libraries/prettify.js"></script>

Then at the bottom of my page I make the call to colorize :)
<script type="text/javascript">
  prettyPrint();
</script>

Note: I tried to add the prettify.js file dynamically using the same technique. It loads just fine, however the pretty-printing doesn't work. I'm guessing it's something to do with event firing. Ideally I'd like to have a single .js file to which does everything. Can someone can provide a quick (not too nasty) workaround?


Update:
Due to a few code posts, I noticed multiple duplicates of the CSS file in the <head> tag. Also the prettyprint.js was seen in the content sections of each post. To combat this I decided to do a simple check and delete. Here's the modified code.
function insertCSS(filename) 
{
    var inHead = alreadyInHead(filename);    
    if (inHead == true)
        return;
    
    var link = document.createElement("link")
    link.setAttribute("rel", "stylesheet")
    link.setAttribute("type", "text/css")
    link.setAttribute("href", filename)
    document.getElementsByTagName("head")[0].appendChild(link)
}

function alreadyInHead(filename) {
    var links = document.getElementsByTagName('link');
    
    for (var i = 0; i < links.length; i = i +1)
    {
        var link = links[i];
        var href = link.getAttribute("href");
        if (href == filename) {
            return true;           
        }
    }
    return false;
}

function remove(filename) 
{
    var scripts = document.getElementsByTagName('script');
    for (var i = 0; i < scripts.length; i = i + 1) {
        var node = scripts[i];
        var src = node.getAttribute("src");
        if (src == filename) {
            node.parentNode.removeChild(node);
            i -= i - 1;
        }
    }
}

insertCSS("http://your.site/tools/libraries/prettify.css");
remove("http://your.site/tools/libraries/bloggerPrettifyHack.js");
remove("http://your.site/tools/libraries/prettify.js");

I'm still cringing because there are still multiple calls of prettyPrint(). Can anyone help out with this one?

How to insert a link tag in Blogger / Blogspot html - Hacking Blogger with JQuery



This article will show you how to insert a <link> tag in the header of the html when in the "Edit HTML" tab of Blogger/Blogspot. The example I give involves using the prettify library.

The background behind why I want to do this
I wanted to use prettify to colorize my code in blogspot. This fantastic awesome tool requires only a .js file and some CSS. Blogger allows you to insert at link to an external Javascript file in the "Edit HTML" tab. It does not however allow an external CSS file. I find this really annoying. I do not want to copy and paste all this CSS every time I insert code. So I thought, if I can insert a Javascript file then maybe I'll just hack it with my favorite tool JQuery :)

The first order of business is to include JQuery:
<script src="http://your.site/tools/libraries/jquery-1.4.min.js" type="text/javascript">
</script>

Next we insert the CSS file into the <head> element:
<script type="text/javascript">
    function hackHead() {
        var src = '<link type="text/css" rel="stylesheet"  href="http://your.site/tools/libraries/prettify.css"/>'
        $("head").append(src);
    }
    hackHead();
</script>

Now we add the Prettify library.
<script src="http://your.site/tools/libraries/prettify.js">
</script> 

Finally, at the very bottom of your page you need need to call prettyPrint()
<script type="text/javascript">
  prettyPrint();
</script>


Update: Ok I give in. JQuery is overkill. See my new post for a neater way to do this.

Random Code Generator in C#

I needed to generate a whole bunch of random codes so I wrote a little class to do it for me. Here is the code for it

public class CodeGenerator
    {
        private const string Characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890$-_.+!*'(),";
        private Random m_Random;
        
        public CodeGenerator()
        {
            m_Random = new Random();
        }

        public List<string> GenerateRandomCodes(double noOfCodes, int codeLength)
        {
            double combinations = MathLibrary.GetCombinations(Characters.Length, codeLength);

            // check permutations
            if (noOfCodes &gt; combinations)
                throw new Exception(String.Format("noOfCodes &gt; maximum combinations. I.e. noOfCodes &gt; {0}", combinations));

            List<string> codes = new List<string>();
            for (long i = 0; i &lt; noOfCodes; )
            {
                string code = GenerateCode(codeLength);
                if (!codes.Contains(code))
                {
                    codes.Add(code);
                    i++;
                }
            }
            return codes;
        }

        public string GenerateRandomCode(int codeLength)
        {
            return GenerateCode(codeLength);
        }

        private string GenerateCode(int codeLength)
        {
            string code = "";

            // select random character 
            for (int i = 0; i &lt; codeLength; i++)
                code += Characters[m_Random.Next(Characters.Count())];

            return code;
        }
    }


Oh and my Math Library

public class MathLibrary
    {
        public static double GetCombinations(int n, int k)
        {
            double top = Factorial(n + k - 1);
            double bottomLeft = Factorial(k);
            double bottomRight = Factorial(n - 1);

            return (double)top / (bottomLeft * bottomRight);
        }

        public static double Factorial(int n)
        {
            return ((n &lt;= 1) ? 1 : (n * Factorial(n - 1)));
        }
    }

Thursday 21 January 2010

Ninite Review

Ninite is the most useful piece of software I've used in a while.

It downloads and installs all the software while you go out and play. No longer must I sit there clicking, waiting, and restarting - a process that in the past took 2 hours, not to mention configuration eeek!

I've tried 
Ninite on a Windows XP and 7 machine.

The procedure could not be more simple:

Go to the website
Select the checkboxes of the software you want to install. Don't bother with trial software, you'll just have to uninstall it later.
Click "Get Installer".
Run the installer and go for lunch.

General Comments

It would be better with some intelligent download threading (which they will probably implement soon anyway). Essentially, I'd like to see at least 2 intelligent download threads. E.g. Start downloading the largest file at the beginning so it will finish by the time the other packages are downloaded and installed. Also, I'm not likely to be using my computer while all this software is being installed.

Conclusion

This software is amazing! If you've formatted your computer and you want your software be installed auto-magically then this is the software for you.


Chrome OS - First Impressions


I downloaded the new Google Chrome OS and ran it on Sun’sVirtualBox VM software.

My first impressions...

It was only an 8 second start up time to the login screen. Awesome! Then a single sign-on to your computer with your Gmail account. Another 8 seconds and the Chrome browser was open with my Gmail account and Google Calander. Now that was impressive! Within 25 seconds of me turning on my computer I was reading my email.


What else is there to Chrome OS? It doesnt seem like there is anything else. I couldn't find anywhere to configure system preferences or anything. Do you want to open other programs or windows, or install other software (like Firefox)? Unfortunately you can't! It felt like I was in an internet cafe with a computer that is so locked down that all I can do is surf the web. A note to all internet cafe's around the world...None of the big players online support IE6 anymore. Please upgrade to anything else!


Anyway, Chrome OS is aimed at netbooks (at least initially). A netbook user would typically like to turn on their computer, have it quickly boot, have their browser immediately open, check their mail and calendar, and then continue surfing. That is what Chrome OS allows them to do, but thats it. The OS is merely a portal to the internet. You can't run anything locally.


But I guess that over the years Google has been introducing online services and applications so the average consumer doesn't really need local applications. With Chrome OS, Google can encourage the use of online applications such as Google Documents, and (when it gets a lot better) it might actually start to rival MS Office, because it is free and online. After all, who needs local storage when there is cloud computing?


Conclusion... Google Chrome OS boots damn fast! It allows you to quickly get on the interweb. It's not exciting from an OS perspective as far as user experience goes, but damn it's fast!

If you want to try out, navigate your interweb browser to this hyperlink:http://www.techcrunch.com/2009/11/19/guide-install-google-chrome-os/

P.s. Google seems to be putting all types of applications online. What is next? Is Google going to make an online Pro Tools? Now that would be impressive!



Meta tags and Umbraco


You’d think that you could do something like this to get meta description and keywords from umbraco
 <meta name="description" content="" />

Unfortunately umbraco will render this:
<meta name="description" content="<umbraco:Item runat='server' field='PageDescription'/>" />

The solution is inline xslt:
<umbraco:Item ID="Item" Field="PageDescription" runat="server" Xslt="concat('')"XsltDisableEscaping="true">umbraco:Item>


*Duplicated from my post on Farmcode.org


A problem using sIFR for menus that link to databound forms in IE7


This is quite possibly the most interesting/annoying/crazy quirk/bug I have ever come across.

Scenario

Your site has a sIFR menu. One of the links goes to a typical databound form (in our case an update user details form).

Problem

The user modifies a field and submits. The database table shows the change. However, when you navigate back to the form using your sIFR menu link, you notice the old value(s) in the fields. The correct values only appear once you clear your cache. This problem only occurs in IE7.

Reason

It turns out that the sIFR link is not a normal link. It is essentially like hitting the enter key in the address bar of a page that is already loaded. The browser merely loads from its cache. No matter how many times you click that link!

Solution

In the code behind of your form on page load call this:

Response.Cache.SetCacheability(HttpCacheability.NoCache);





*Duplicated from my post on Farmcode.org

Tuesday 19 January 2010

Programmers are Gods

I found this post very amusing.


"So if you’re working with a programmer, you have to treat him or her like a God. You have to pray. You cannot issue edicts. You have to come on bended knee. “Here’s the problem I have. I need a solution. Please help.”"

"if you give a programmer a problem with parameters, they’ll apply every bit of genius they have to solve it in the best possible way. If you tell them how to do it, you’ll suffer the wrath of an angry God."

This is entirely true. We hate being told to do something. And we hate being told by someone (who is not a programmer) how to make/fix something.

Classic ASP in Visual Studio 2008 on IIS6 and IIS7 on Windows XP and Windows 7

I had to migrate a couple sites in classic ASP. I also had to make some modifications. I had to do these on  Windows XP (IIS6) and Windows 7 (IIS7) so I thought I'd write a post before I forget how to do it all.

Classic ASP in Visual Studio
Visual Studio 2008 has great intellisense for html, javascript etc. so it's definitely one of the nicest options for an IDE. According to a few posts I saw, you need SP1 for Visual Studio 2008. I already had it installed. 


In Visual Studio 2008, create a new Website (NOT Web Project). It does not make sense to create a Web Project because ASP doesn't require you to compile it. Likewise. "Websites" in Visual Studio 2008 are not precompiled before publishing. Copy the site to the root folder. In Visual Studio click the refresh button at the top of the Solution Explorer.


As far as I'm aware (correct me if I'm wrong), you cannot run ASP on Cassini (Visual Studio's lightweight web server). So you have to run your site using IIS (install it form your windows disk if you don't have it).


If you're running Windows XP, here is a nice tool that enables you to set up multiple of sites in IIS. Note that you can only have one site started at a time, however if you're constantly having to switch between sites you're testing/developing etc then this tool is rad!


Running Classic ASP in IIS
In IIS6 and 7, "enable parent paths" is disabled. You must enable it for your website, otherwise your ASP pages that access files in their parent folder (e.g. trying to access ../some_file.asp) will throw an error.


In IIS6 (Windows XP)
  1. Right-click the website, and then click Properties.
  2. Select Home Directory, and then click Configuration.
  3. Click Options, and select the Enable Parent Paths check box.
In IIS7 (Windows Vista and Windows 7)
  1. Click the website, and then click ASP (under the IIS section)
  2. Under Enable Parent Paths (5th item in Behavior section), select true.
  3. While you're there, select Send Errors To Browser (so you can see any errors)
  4. Click Apply.
Note that in II7 you have to install ASP as it is not installed by default. It's real simple. Just do the following:
  1. Go to Turn Windows Features on or off under Programs and Features (control panel).
  2. Expand Internet Information Services, then World Wide Web Services, then Application Development Features.
  3. Select ASP, and then click OK.
Now assuming you pointed the IIS to the correct folder, you should be able to see your website in your browser (in anything other than IE6) via http://localhost


I hope this was informative. If I left anything out, please let me know.



Google vs China


Ok so this is huge! They all but accuse the Chinese government of espionage: 


First blog

Nuff said