.NET (C#) – format decimal as price – with no culture specific information and two decimal points

This is one of those where there’s so many ways of doing something simple – you end up going “will someone please just tell me how the…” etc etc :0)
The below is a simple basic way, which ignores all culture specific information (you add the currency symbol yourself), and gives you two decimal points.

		decimal decimalValue = 12.99M;
		string test = String.Format("Item costs £{0:N} only", decimalValue);
		//"Item costs £12.99 only"
		//This will also round correctly - e.g. 12.995 to "13.00", and 12.994 to "12.99".

And if you need to inject the currency symbol based on some logic:

		string currencySymbol = "£";
		string test = String.Format("Item costs {0}{1:N} only", currencySymbol, decimalValue);
		//"Item costs £12.99 only"

And then of course finally we stick this into an extension method:

	public static class ExtDecimal
	{
		public static string ToMoney(this Decimal d, string currencySymbol)
		{
			return String.Format("{0}{1:N}", currencySymbol, d);
		}
	}

	...

	string test = decimalValue.ToMoney("£");
	//"£12.99" - and above example:
	test = String.Format("Item costs {0} only", decimalValue.ToMoney("£"));
	//"Item costs £12.99 only"
Advertisements

Umbraco Upgrade hangs at 35% “Upgrading Database Tables”

This is an issue that seems to apply to the install wizard for Umbraco 4.6 and 4.7, when upgrading from older versions.
At the database step you get to 35% with the status “upgrading database tables” – and nothing else happens.

This is caused by a bug in the install code – the format of the code makes it hard to spot – but below reformatted section from \umbraco\presentation\install\utills\p.aspx.cs shows the problem – the first block is incorrect and should be removed:

Howver, at the point where you see the “35% Updatings database tables…” the code has already checked that’s it’s able to connect to and upgrade your database. The Install() call (above) is a quick set of SQL statements – only takes a couple of seconds to run – and the RefreshContent() is async (will run separately in another thread), so if you have been looking at the “35 upgrading tables” for a little while it’s pretty safe to assume that this has completed without errors, and hitting F5 will then force a recheck of your database which should send you on to the next step.

I’ve also covered this issue in the Umbraco forums here: http://our.umbraco.org/forum/getting-started/installing-umbraco/17531-Upgrade-to-461-Updating-database-tables-Problem

Application Timers (to replace scheduled tasks)

I do not like scheduled tasks.
They most often take the form of little bits of unversioned code (in console apps) that exist outside the main solution.
Moving these into the main application allows us to utilise the application’s logging utilities, adds versioning to the logic and configuration settings and ensures that the code is both updated and deployed along with the rest of the solution.

Below is some initial code – the idea is to have a singleton class that starts a set of timers. This can then be called from Application_Start or a similar global event.
Some improvements to the below would be to make the application timers use the provider pattern – so we can code up new timers when we need, and perhaps add a .config section to load these from.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Timers;
using System.Net;
using HobNobClubServices.Library;
 
namespace HobNobClubApps.Library
{
      /// 
      /// Singleton timer
      /// 
      public sealed class ApplicationTimers
      {
            private static readonly ApplicationTimers instance = new ApplicationTimers();
            private static bool timersInitialised = false;
 
            private ApplicationTimers() { }
 
            public static ApplicationTimers Instance
            {
                  get
                  {
                        return instance;
                  }
            }
 
            public void InitTimers()
            {
                  if (timersInitialised)
                        return;
 
                  InitHobNobInsuranceEmailAbandonedQuotesTimer();
 
                  timersInitialised = true;//Only do this once in the application:
            }
 
            private void InitHobNobInsuranceEmailAbandonedQuotesTimer()
            {                
                  Timer HobNobInsuranceEmailAbandonedQuotesTimer = new Timer();
                  int intervalInMinutes = Properties.Settings.Default.HobNobInsuranceEmailAbandonedQuotesTimerInterval;
                  HobNobInsuranceEmailAbandonedQuotesTimer.Interval = (intervalInMinutes * 60000); //Convert to millisecs
                  HobNobInsuranceEmailAbandonedQuotesTimer.Elapsed += new ElapsedEventHandler(HobNobInsuranceEmailAbandonedQuotesTimer_Elapsed);
                  HobNobInsuranceEmailAbandonedQuotesTimer.Start();
            }
 
            private void HobNobInsuranceEmailAbandonedQuotesTimer_Elapsed(object sender, ElapsedEventArgs e)
            {
                  string errorMsg = String.Empty;
                  try
                  {
                        int intervalInMinutes = Properties.Settings.Default.HobNobInsuranceEmailAbandonedQuotesTimerInterval;
                        //Set the delay in emailing people to the same as this timer interval (so if this timer runs every 30 mins, people will be emailed if they've left a quote alone for 30 mins):
                        string methodNameAndParams = String.Format("/EmailAbandonedQuickQuotes?delayInMinutes={0}", intervalInMinutes);
                        WebRequest webRequest = HttpWebRequest.Create(Properties.Settings.Default.HobNobClubApps_SLHobNobInsurance_HobNobInsurance + methodNameAndParams);
                        WebResponse webResponse = webRequest.GetResponse();                    
                  }
                  catch (Exception ex)
                  {
                        errorMsg = ex.Message;
                        ExceptionManager.LogExceptionEvent(ex, Logger.Source.HobNobInsurance);
                  }
 
                  Logger.WriteInfoLog(
                        String.Format("The HobNobInsuranceEmailAbandonedQuotesTimer ran at {0} {1}",
                                                DateTime.Now, String.IsNullOrEmpty(errorMsg) ? "with no errors (from the timer)." : "and failed with: " + errorMsg),
                              Logger.Source.HobNobInsurance);
            }
      }
}
 

Maintaining Session State in .NET Web Services

Very informative article on this here: http://msdn.microsoft.com/en-us/library/aa480509.aspx and a step by step of the client side implementation here: http://support.microsoft.com/kb/816637

The short of the long is:

  • The web service must be marked with the EnableSession=true attribute.
  • On the consuming client, you must use an instance of the CookieContainer class to store the session cookie (with the unique session ID created on your first request
  • You must then re-use this instance of the CookieContainer for each subsequent call in order to maintain session state on the web service host – a logical way to do this is to add the CookieContainer instance to session state on your client (so do a get property with “session bag” null check logic

Some .NET Debugging Tools and Tricks

Very interesting case study here http://www.wintellect.com/Consulting/Debugging of some Microsoft MVPs trying to find an error in a client’s ASP.NET application, while working off-site.
Couple of important, but lesser known debugging tools gets mentioned along the way: Sysinternals for monitoring your Windows server and .NET Reflector (which was previously Roeders Reflector until RedGate took it over) for digging through assembly code. Also Windows Server Minidump is worth knowing about.

A tool not mentioned in that article (because it’s not relevant) is the “Microsoft Intermediate Language Disassembler”, ILDASM – if you need to really take some .NET code apart.
For web application debugging the Fiddler Web Debugger is indispensable. You can get the basic functionality from here in the Firebug net tab – but Fiddler adds more debugging options, like for example the ability to change the data being posted to your web server.

Finally Visual Studio is of course the most used debugging tool for .NET developers, and there are some new debugger features in VS2010 that’s worth knowing about, like the ability to label break points, to pin the data tips to retain the value (and compare to the previous after a refresh) and even append comments to these.

Finally, finally – if you’re lucky enough to own a version of VS2010 Ultimate, you will also have access to IntelliTrace which lets you step backwards up through your code (with some limitation I believe).

Absolutely last finally – the best debugging tool is sometimes to have a cup of coffee, and then fetch one of your colleagues, or a friend or even Irene from reception – and explain to them what the code is trying to do, how it fails, what you have tried to fix it – and nine times out of ten (well six out of ten at least) somewhere along that process – between the coffee and rambling at innocent bystanders – you will probably at the very least come up with something you haven’t considered yet.

What’s New in ASP.NET 4 and .NET 4?

Seems MS are churning out new versions of everything at a pace – or is it just me? Quite often you fall into the trap of just tagging along – when I start a new website now and VS asks me – “do you want this in 3.5 or 4.0” – well I go for 4.0.
Why shouldn’t I? It’s nice to be up to date right? But of course the better question is “why should I?”

Well for the .NET framework it’s of course the case that 3.5 was built on top of the 2.0 CLR, and as such they we’re really just additions to the 2.0 framework (some people have speculated that MS were keen to speed up the advancement of their version numbers (Java EE recently made it to 6), and really 3.0 and 3.5 would have made a lot more sense as 2.1 and 2.2).
The .NET 4 framework however uses a grand spanking new CLR (with some improvements to garbage collections, and changes to allow support for functional programming ao), and a load of additional features to the framework.

Some C# changes include optional and named parameters which essentially allows you to pass only some parameters and/or in any order you like. Also we have a new keyword: dynamic. Basically this switches off type checking for parameters defined as such – so I can for example do this:

 
		public MyMethod(dynamic someObject)
		{
				someObject.DoSomethingCrazy();
		}

And the compiler will not attempt to check if someObject does indeed have a DoSomethingCrazy method. This is mainly intended for COM objects, but could also be used for reflection – and tbh could also be misused something awful.
You could start throwing dynamic objects around the place and pretty soon you’d have half of your application outside the compilers type checking – but of course why would anyone ever want to do that? (What could possibly go wrong?)
Kind of reminds me of the var keyword that was introduced in 3.0 – of course as this was just a convenience (the compiler would infer the type from the usage, and perform full type checking on compilation (if not intellisense had picked it up already)) – but it had (has) the same potential for misuse that dynamic does, imho anyway.
The var keyword was needed to support Linq – but pretty soon you saw code all over the place looking like Javascript – which did not really pose any risks – but on picking up someone elses code, the problem is that you have to start doing type inference as well – it’s not just the compiler.
When someone writes var x = GoGetMyThing(); – what do you think x is?
So you sit around hovering your mouse over stuff relying on good old Intellisense to do your job for you.
Anyways – of course as frameworks have to support more and more functionality, the potential for misuse will inevitable increase. And as someone pointed out the other day: I am of course free to programme all my projects in .NET 1.1 if it’s something I feel that strongly about.

With 4.0 we also got an update to the Visual Studio IDE – VS2010 – which besides a very neat design and a new and improved default font (Consolas) – also has some very useful new features.
A really nice feature you should def get to know is the Navigate To – use “ctrl+,” to pop this up. It basically allows you to search through everything, from file names to methods, interfaces – etc, and you can even use CamelCase or abbreviations to narrow your search.
Reference Highlighting is another one of my favourites – hover your mouse over any variable in the code window, and instances of this will be highlighted throughout the document. I’m telling ya – if MS ever removed Intellisense you’d see some stressed MS developers around.
Call hierarchy is an improvement to the “view all references” option – which allows you to see calls to and calls from any method or property. Very nifty when getting to know a new project. Also you can see all implementations of an interface (use this when you do the “go to ref” and you end up looking at the same interface every time) as well as all overrides of virtual and abstract members.
Also there is some improved support for unit testing, including the ability to stub out your code from the unit test that you of course always write before you do anything (don’t you? of course you do).

Moving swiftly along to the core of the matter (for me anyway) – ASP.NET 4.0:

Multiple Left Joins in Linq to SQL

Had some fun with this – rubbish formatting below – but paste into Visual Studio and autoformat it (ctrl+e+d).

I’ll write some details on this later – but the basic principle is that if you have a nullable foreign key – i.e. you are not sure if you have matches at the end of your table relation and you would normally do a SQL LEFT JOIN, what you need to do in Linq is use the into clause to declare a collection for the results of your join – the reason being that you can then use the DefaultIfEmpty() method in a subsequent from clause to return empty objects where there is no match.
Couple of examples below – first creates a anonymous object on the fly – here you have to null check to set values. The second example beforehand declares a little helper class with Nullable id’s – which gets you round the null checking.
Note that the below uses multiple from clauses to handle the mutiple left join quires (so basically we select from each declared sub-collection).

from p in Persons
    join l in Languages on p.PrimaryLanguageId equals l.Id into tempResult
    join jt in JobTitles on p.JobTitleId equals jt.Id into anotherTempResult    
    from tr in tempResult.DefaultIfEmpty()
    from atr in anotherTempResult.DefaultIfEmpty()    
    orderby p.Id
    where p.Deleted == null
    select new {
        PersonId = p.Id,
        LanguageId = tr == null ? new Nullable() : tr.Id,
        LanguageName = tr.Name,    
        JobTitleId = atr == null ? new Nullable() : atr.Id,
        JobTitleName = atr.Name
    }    

And a more extensive example:

        ///
        /// Person Grid Helper.
        ///
        ///
        /// Linq joins would normally create an anonymous type
        /// – however we cannot use anon types as the grid collection is passed to another method when searching (LoadPersonForSearch).
        ///
        private class PersonGridHelper
        {    
            public int Id { get; set; }
            public string GivenName { get; set; }
            public string FamilyName { get; set; }
            public string OfficeLocation { get; set; }
            public Nullable OfficeLocationId { get; set; }
            public string JobTitle { get; set; }
            public Nullable JobTitleId { get; set; }
            public string Email { get; set; }
            public string EmailDomain { get; set; }
            public int EmailDomainId { get; set; }
            public string AlternateEmail { get; set; }
            public string Mobile { get; set; }
            public string Telephone { get; set; }
            public string Fax { get; set; }
            public string CVFile { get; set; }
            public string ProfilePictureFile { get; set; }
            public string PrimaryLanguage { get; set; }
            public Nullable PrimaryLanguageId { get; set; }
        }

        ///
        /// Loads the main browse grid.
        ///
        public override void LoadGrid()
        {
            IQueryable coll = from person in this.CurrentDataContext.Persons
                                                 join officelocation in this.CurrentDataContext.OfficeLocations
                                                    on person.OfficeLocationId equals officelocation.Id
                                                join jobtitle in this.CurrentDataContext.JobTitles
                                                    on person.JobTitleId equals jobtitle.Id into jobtitles //Nullable FK => left join, DefaultIfEmpty() below
                                                join language in this.CurrentDataContext.Languages
                                                    on person.PrimaryLanguageId equals language.Id into languages //Nullable FK => left join, DefaultIfEmpty() below
                                                join firmemaildomain in this.CurrentDataContext.FirmEmailDomains
                                                    on person.EmailDomainId equals firmemaildomain.Id
                                                from jobtitle in jobtitles.DefaultIfEmpty() //Left join, records from jobtitles collection, if missing default constructor is called
                                                from language in languages.DefaultIfEmpty() //Left join, records from jobtitles collection, if missing default constructor is called
                                                orderby person.FamilyName
                                                where person.Deleted == null
                                                select new PersonGridHelper()
                                                 {
                                                        Id = person.Id
                                                    ,    GivenName = person.GivenName
                                                    ,    FamilyName = person.FamilyName
                                                    ,    OfficeLocation = officelocation.Name
                                                    ,    OfficeLocationId = person.OfficeLocationId
                                                    ,    JobTitle = jobtitle.Name
                                                    ,    JobTitleId = person.JobTitleId
                                                    ,    Email = person.Email
                                                    ,    PrimaryLanguage = language.Name
                                                    ,    PrimaryLanguageId = person.PrimaryLanguageId
                                                    ,    EmailDomain = firmemaildomain.Domain
                                                    ,    EmailDomainId = person.EmailDomainId
                                                 };
                                                 ………………