Friday 24 December 2010
Android 2.2 update breaks 3G on O2
Mobile internet on Nexus S with O2 is broken
Thursday 16 December 2010
Cannot delete document type - Umbraco
Wednesday 15 December 2010
The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPreviewXml_cmsContentVersion". - Swap Master Doc Type Error in Umbraco
The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPropertyData_cmsPropertyType" - Umbraco
The DELETE statement conflicted with the REFERENCE constraint "FK_cmsPropertyData_cmsPropertyType".
Friday 10 December 2010
Reseeding Umbraco
Saturday 13 November 2010
Wednesday 11 August 2010
Print this!
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
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
}
}
Monday 1 March 2010
Flv mime type in IIS
Sunday 28 February 2010
The page cannot be found on Windows Server in a .Net MVC site
Did you forget your wildcard mapping?
Wednesday 10 February 2010
Publishing PDF's from Visual Studio 2008
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
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#
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 > combinations)
throw new Exception(String.Format("noOfCodes > maximum combinations. I.e. noOfCodes > {0}", combinations));
List<string> codes = new List<string>();
for (long i = 0; i < 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 < 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 <= 1) ? 1 : (n * Factorial(n - 1)));
}
}
Thursday 21 January 2010
Ninite Review
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
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!
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
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
Classic ASP in Visual Studio 2008 on IIS6 and IIS7 on Windows XP and Windows 7
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)
- Right-click the website, and then click Properties.
- Select Home Directory, and then click Configuration.
- Click Options, and select the Enable Parent Paths check box.
- Click the website, and then click ASP (under the IIS section)
- Under Enable Parent Paths (5th item in Behavior section), select true.
- While you're there, select Send Errors To Browser (so you can see any errors)
- Click Apply.
- Go to Turn Windows Features on or off under Programs and Features (control panel).
- Expand Internet Information Services, then World Wide Web Services, then Application Development Features.
- Select ASP, and then click OK.
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: |