Posts

Your bug is my bug

I recently released an update to some software and a bug slipped through the net. It introduced some odd behaviour with a control named SmartGrid. After some testing I was able to determine that it wasn't my fault and that I could reproduce a bug in SmartGrid. I hate bugs in other people's source code, I can't fix it, I am at their complete mercy. Thankfully the Resco support was amazing! I posted on their forums and immediately someone sent me instructions on where to send my project. The next morning I was disappointed to see an email saying that the project worked fine. I posted again and almost immediately someone had offered to chat on skype. We did that for a while, both confused by the problem. We then went on to use Remote Assistance so that he could observe my bug which he wasn't experiencing. In the end the problem was very confusing. I had Version A of the DLL in which the error occurred. I upgraded to the latest version (B) and it still occurred. T

Converting a recurring decimal to a fraction

For a couple of hours a week I am doing a beginner's level maths course. The topic today was converting recurring decimals into fractions. For example (the [] are the repeating digits 0.[6]  1x = 0.[6] 10x = 6.[6] 9x = 10x - 1x 9x = 6.[6] - 0.[6] = 6 Therefore the answer is 6/9, or 2/3 When it got to numbers like 0.12[34] (ie 0.12343434343434.....) the lesson was really complicated, but I came up with a more simple approach, so here it is if ever you need it. My first observation was that we need a large number and a small number. So let's start with the 10x we used above  1x = 0.12[34] 10x = 1.2[34] therefore 9x = 10x - 1x which is  1.2[34] -0.12[34] This is going to give us 1.1(something) My second observation is that fractions cannot have decimal values in them. In order to get rid of the fraction we need the big number to have the exact same fraction as the small number. e.g.  B.[34] -S.[34] =X.[00] So our small number needs to end with [34]. Given the number 0.12[34]

MaxLength

Implementing HTML maxlength was a bit of a pain. Not to write the helpers though, that was easy.... $EcoModelHelper.AttributeLength($Product, "ID") But when it came to specifying that in the <input> it was too much work! This is how it is done statically... $FormHelper.TextFieldValue("Product.ID", $Product.ID, "%{maxlength='32'}") Now I had to replace the static 32 with the EcoModelHelper code. #set ($ProductIDLength = $EcoModelHelper.AttributeLength($Product, "ID")) $FormHelper.TextFieldValue("Product.ID", $Product.ID, "%{maxlength='$ProductIDLength'}") This was starting to look like too much typing! So instead I have decided to add new methods to the EcoFormHelper. Here is the first: $EcoFormHelper.ObjectTextField("Product.ID", $Product, "ID") This will output something like this <input type="text" id="Product_ID" name="Product.ID" value="Alt

EcoRail validation

Here is yesterday's update. I wanted a way to validate the user input. Seeing as there are constraints in the model to me this was the obvious approach to take. The HTML in my main layout (MasterPage) was changed like so <body>   #if ($Errors && $Errors.Count > 0)     <ul class="errors">       #foreach ($currentError in $Errors)         <li>$currentError</li>       #end     </ul>   #end   $childContent </body> This outputs all errors passed in PropertyBag["Errors"] or in my case I used Flash["Errors"]. To validate my product input I changed my controller like so: [AllowEcoSpaceDeactivateDirty(true)] public void Modify([EcoDataBind("Product", Allow = "ID,Name", NoObjectIdAction = ObjectIdAction.CreateNewInstance)]Product product) {   PropertyBag["Product"] = product;   IList<string> errors = GetErrorsForAllDirtyObjects();   if (errors.Count > 0)     Flash["Erro

Changing the URL structure

I wanted the following URL structure in my website www.mysite.com/product/myproductname/whatsnew but the default url mapping in MonoRail would translate this as www.mysite.com/[controller]/[action]/[id] So it would expect to find this public class ProductController {   public void MyProductName(string id)   {   } } whereas what I actually want is public class ProductController {   public void WhatsNew(string productName)   {   } } Open Web.Config Locate the monorail node Locate the routing child node Now add a new <rule> to the top of the list: <rule> <pattern>/(product)/(\w+)/(\w+)</pattern> <replace><![CDATA[ /product/$3.rails?productName=$2]]></replace> </rule> As this is at the top of the list it will have the highest priority. If the URL matches /product it will remap the url From: www.mysite.com/product/myproductname/whatsnew To: www.mysite.com/product/whatsnew.rails?productname=MyProductName without the user ever seein

ECO docs progress

I'm currently in the process of migrating the QuickStart series from BDS over to VS and recreating the accompanying source code. There's quite a lot of information in those articles, I hadn't realised how much I had written! Well, the transcription is going quite well. So far I have made it as far as article number 5. This one is going a bit slower because it is also a translation from VCL .NET to WinForms.

Inversion of control

As you may already know I am writing a website. I've chosen to use MonoRail for the web part and ECO for the persistence. Today has been great fun! I have modified the Castle.MonoRail.EcoSupport library with the following enhancements. You can now specify a [DefaultEcoSpaceType(typeof(MyEcoSpace))] on either the class or method. On the EcoDataBind reflection attribute you can now specify as little as [EcoDataBind("Product")] on your method parameter, this will use the specified DefaultEcoSpaceType specified, or throw an exception if no default was specified. This lets me write code like this [AllowEcoSpaceDeactivateDirty(true)] [UseEcoSpacePool(false)] [UseEcoSpaceSession(EcoSpaceStrategyHandler.SessionStateMode.Never)] public class ProductAdminController : BaseController {   public void Create()   {     PropertyBag["Product"] = new Product(GetEcoSpace<MyWebSiteEcoSpace>());     RenderView("Modify");   } } I can now easily create actions Creat