Posts tagged Programming

Email opt-out: Here’s a great example of how to do it right

A Good Approach to Email Opt-outI came across this opt-out screen today.  It’s one of the best examples I’ve seen recently of an opt-out screen done right.

First, they try to fix one of the key reasons people opt out of email: they are still interested but they want less email.

Then they give you the option to really just quit completely.

Then they give you the option to change your email address.

It really looks like they have done their homework, presenting these in the order that most likely applied whilst also trying to keep you as a recipient.

Anyone implementing email notifications for their startup should also take a look at CAN-SPAM.

Cloud computing – where’s the silver lining?


Colorado Storms 2009 (9)

Cloud Computing - where's the silver lining?

I’ve seen several people propounding the cost savings of cloud computing as being of great benefit to startups. Most recently someone wrote “… cloud offers an amazing opportunity to reduce costs for startups”

This simply isn’t true.

It cost ~$2500 to buy a smoking hot server from Silicon Mechanics with SSD drives and under $100/month to host it at a reputable data center. Over 4 years that’s about $160/month which is less than coffee and a doughnut each day. Even if the cloud was free that still wouldn’t make it an “amazing” cost saving.

In addition, said smoking hot server, can outperform 8 large EC2 instances on any compute heavy or data intensive operation. For individual web requests with some database access it also offers lower latencies = better customer experience.

Depending on the load, cloud computing can cost more than a dedicated server and offer a worse customer experience. It’s not the panacea it’s made out to be.

The ‘correct’ reasons to select cloud computing are …

  • it offloads a bunch of setup and maintenance effort to someone else,
  • you can get another ‘machine’ more quickly / more easily,
  • it allows you to scale up a [well-designed] application easily if your startup is successful and actually needs to go beyond one server, …

“Cost savings” doesn’t even make the list for startups IMHO and many of these same benefits can be had by running your own smoking hot server with virtualization.

The other dirty secret of cloud computing concerns the notion that you can pull together a reliable system from disparate services from different vendors.  Do the math: 0.999 x 0.999 x 0.999 x 0.999 is a lot less than 0.999 and that could mean unacceptable downtime for your users.

Summary: It’s not significantly cheaper, it may be slower, it may be less reliable but it can be much more convenient.

Creative Commons License photo credit: dktrpepr


DateTime values should always be stored in UTC

Developers are sometimes confused about this issue but the fact of the matter is that you should always store Datetime values in your database in UTC and almost never in a local time zone.

Canyon de Chelly Ruins

Canyon De Chelly, Az/NM border: One of the many places where naive use of local time will cause you problems!

Creative Commons Licensephoto credit: JBColorado

You should use UTC because:-

1) There are no ambiguous or missing times in UTC time. Any timezone with daylight savings time has a spring-forward gap and a fall-back repeated hour. That messes up all manner of calculations: How many hours is it from 2:05AM to 2:07AM? In UTC time it’s always 2 minutes but in local time it could be 2 minutes or it could be 1 hour and 2 minutes or it could be ‘error no such time’.

2) All your times sort correctly even if they were entered by users in different timezones. So, user A commenting on user’s B comment on user C’s photo doesn’t have their comments listed in the wrong order even if user C is in Europe, user A is in Japan and user B is in the USA. And user D gets to see the whole thread in whatever timezone they are in because you convert UTC to local on the way out in the user’s local timezone.

3) Daylight savings time rules change from time-to-time. To be able to reliably say how many hours it is from DateTime A to DateTime B you would need to store every historical variation in the DST rules in order to be able to calculate that correctly, and even then because of (1) you couldn’t calculate it in every case because there would be ambiguities.

4) Worse even that (3) is the fact that the boundaries of timezones are not constant but have changed over time. So your database of historical timezone information also needs to include accurate geographical information for every time zone AND you need to record the location of every local datetime value in order to be able to calculate when it happened in UTC time (and even then (1) causes problems).

5) If you think you understand timezones completely and can deal with all these issues go read up on Navajo Indian Reservations, fractional time zones and then consider what happens if you are recording datetime values associated with a moving vehicle.

Storing datetime values in UTC is the only sensible answer to all of these issues.

One of very few exceptions to this rule is when you have a local datetime that you cannot convert to UTC time because you can’t be sure of the timezone, e.g. Datetimes from digital cameras or camcorders where all you have is a local time and have no idea what timezone it is in. In such cases you can store a local datetime but you really have very little ability to do much with it apart from redisplay it.

The other one to watch for is where you have an event at a given time in a given location, e.g. 10AM: Family Reunion in Taos, New Mexico. In this case you need to do the UTC conversion in some timezone other than the one your user is in right now. And you want to store the fact that it is a time that should be shown in the local New Mexico timezone not the user’s timezone.

Grouping is another key issue – you need to convert your UTC times into local times BEFORE you group them into days because my ‘today’ might not be the same as your ‘today’. This complicates your ability to perform grouping in your database.

UTC is the only sensible format to store date time information in a database. If you can’t generate a UTC datetime from the input then the value you have may as well be stored as a string because there’s very little you can do with it without a lot of extra effort!

ASP.NET MVC 2 and the Ambiguous Match Exception for Action methods with different signatures

Although you can use this technique to allow POST requests to a page avoiding a redirect this is now considered a bad practice from a usability perspective because if the user hits refresh they get the classic browser warning. You normally want to use a Post-Redirect-Get pattern: when you make a POST request, once the request completes you do a redirect so that a GET request is fired. In this way when the user refreshes the page, the last GET request will be executed rather than the POST. You can still use this technique to have two post methods with different parameters but the same name, but why bother if each is going to do a redirect anyway back to the page Action method?

One frustration I have with ASP.NET MVC is that you can’t easily have two actions with the same name but with different parameters, e.g. Index(int a, int b), and Index (int a). If you try this you will get an AmbiguousMatchException because it makes no attempt to match the form values with the method parameters to figure out which method you want to call. Now you can decorate the Index() with [AcceptVerbs(HttpVerbs.Get)] so that it at least will not be competing for ASP.NET MVC’s attention during the form post but your other two index methods will still cause the exception.

Supposed you wanted a page /Home/Index that had two forms on it:-

<%using (Html.BeginForm()) { %>
<%=Html.TextBox(“a”) %>
<input type=”submit” name=”submitOne” title=”click me” />
<%} %>

<%using (Html.BeginForm()) { %>
<%=Html.TextBox(“a”) %>
<%=Html.TextBox(“b”) %>
<input type=”submit” name=”submitTwo” title=”click me” />
<%} %>

What we’d like to do is be able to have three action methods, Index(), Index(Int a) and Index (Int a, Int b).

So let’s define our action methods like that and add a filter attribute to them that will filter methods according to the posted values ignoring any for which there aren’t enough posted values to match the number of parameters or for which the parameter names don’t match.

30 /// <summary>

31 /// Post a single integer back to the form, but don’t allow url /Home/Index/23

32 /// </summary>

33 [ParametersMatch]

34 [AcceptVerbs(HttpVerbs.Post)]

35 public ActionResult Index([FormValue]int a)

36 {

37 ViewData["Message"] = “You supplied one value “ + a ;

38

39 return View();

40 }

41

42 /// <summary>

43 /// Post two integers back to the form OR include two integers in the path

44 /// </summary>

45 [ParametersMatch]

46 [AcceptVerbs(HttpVerbs.Post | HttpVerbs.Get)]

47 public ActionResult Index([FormValue]int a, [FormValue]int b)

48 {

49 ViewData["Message"] = “You supplied two values “ + a + ” “ + b;

50

51 return View();

52 }

And finally, here’s the code that makes that possible: an attribute you can apply to a method parameter to indicate that you want it in the posted form, and an action filter that filters out any action methods that don’t match.

With this in place you can (i) avoid an unnecessary redirect and (ii) have actions with the same name but with different parameters.

Create a new ActionFilter like this …

1 namespace TestApplication.Controllers

2 {

3 using System;

4 using System.Collections.Generic;

5 using System.Collections.ObjectModel;

6 using System.Diagnostics.CodeAnalysis;

7 using System.Linq;

8 using System.Reflection;

9 using System.Web.Mvc.Resources;

10 using System.Web.Mvc;

11 using System.Diagnostics;

12

13

14 /// <summary>

15 /// This attribute can be placed on a parameter of an action method that should be present on the URL in route data

16 /// </summary>

17 [AttributeUsage(AttributeTargets.Parameter, AllowMultiple=false)]

18 public sealed class RouteValueAttribute : Attribute

19 {

20 public RouteValueAttribute() { }

21 }

22

23 /// <summary>

24 /// This attribute can be placed on a parameter of an action method that should be present in FormData

25 /// </summary>

26 [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]

27 public sealed class FormValueAttribute : Attribute

28 {

29 public FormValueAttribute() { }

30 }

31

32

33 /// <summary>

34 /// Parameters Match Attribute allows you to specify that an action is only valid

35 /// if it has the right number of parameters marked [RouteValue] or [FormValue] that match with the form data or route data

36 /// </summary>

37 /// <remarks>

38 /// This attribute allows you to have two actions with the SAME name distinguished by the values they accept according to the

39 /// name of those values.  Does NOT handle complex types and bindings yet but could be easily adapted to do so.

40 /// </remarks>

41 [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]

42 public sealed class ParametersMatchAttribute : ActionMethodSelectorAttribute

43 {

44 public ParametersMatchAttribute() { }

45

46 public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)

47 {

48 // The Route values

49 List<string> requestRouteValuesKeys = controllerContext.RouteData.Values.Where(v => !(v.Key == “controller” || v.Key == “action” || v.Key == “area”)).Select(rv => rv.Key).ToList();

50

51 // The Form values

52 var form = controllerContext.HttpContext.Request.Form;

53 List<string> requestFormValuesKeys = form.AllKeys.ToList();

54

55 // The parameters this method expects

56 var parameters = methodInfo.GetParameters();

57

58 // Parameters from the method that we haven’t matched up against yet

59 var parametersNotMatched = parameters.ToList();

60

61 // each parameter of the method can be marked as a [RouteValue] or [FormValue] or both or nothing

62 foreach (var param in parameters)

63 {

64 string name = param.Name;

65

66 bool isRouteParam = param.GetCustomAttributes(true).Any(a => a is RouteValueAttribute);

67 bool isFormParam = param.GetCustomAttributes(true).Any(a => a is FormValueAttribute);

68

69 if (isRouteParam && requestRouteValuesKeys.Contains(name))

70 {

71 // Route value matches parameter

72 requestRouteValuesKeys.Remove(name);

73 parametersNotMatched.Remove(param);

74 }

75 else if (isFormParam && requestFormValuesKeys.Contains(name))

76 {

77 // Form value matches method parameter

78 requestFormValuesKeys.Remove(name);

79 parametersNotMatched.Remove(param);

80 }

81 else

82 {

83 // methodInfo parameter does not match a route value or a form value

84 Debug.WriteLine(methodInfo + ” failed to match “ + param + ” against either a RouteValue or a FormValue”);

85 return false;

86 }

87 }

88

89 // Having removed all the parameters of the method that are matched by either a route value or a form value

90 // we are now left with all the parameters that do not match and all the route and form values that were not used

91

92 if (parametersNotMatched.Count > 0)

93 {

94 Debug.WriteLine(methodInfo + ” – FAIL: has parameters left over not matched by route or form values”);

95 return false;

96 }

97

98 if (requestRouteValuesKeys.Count > 0)

99 {

100 Debug.WriteLine(methodInfo + ” – FAIL: Request has route values left that aren’t consumed”);

101 return false;

102 }

103

104 if (requestFormValuesKeys.Count > 1)

105 {

106 Debug.WriteLine(methodInfo + ” – FAIL : unmatched form values “ + string.Join(“, “, requestFormValuesKeys.ToArray()));

107 return false;

108 }

109

110 Debug.WriteLine(methodInfo + ” – PASS – unmatched form values “ + string.Join(“, “, requestFormValuesKeys.ToArray()));

111 return true;

112 }

113 }

114 }

Issues combining ASP.NET MVC and ASP.NET Web Forms in the same application

Recently I started migrating an ASP.NET WebForms project to ASP.NET MVC.  Hoping to do this in phases I created a combined project that is both a webforms project and an MVC project.

Routing allows some requests to go to the WebForms pages and some to go to the new MVC pages.

Routing has also enabled SEO friendly URLs for all pages.

Everything seemed to be working great until I added a form to an MVC page and the URL it decided to use for posting the results back was one of the ASPX pages instead of the page it should have been.  The issue was that routes added for the legacy ASPX pages were being picked up as matches for the route that was being requested.

This article was helpful in explaining how to configure routes to avoid this problem http://forums.asp.net/t/1484855.aspx but I still had an issue with the root “/” Route which was being picked for every form I created.  So I changed the root route to this and now all is well.  Of course, changing the home page to an MVC Action would also have solved the issue but I’m not ready to flip it just yet.

Route(“”,

new RouteValueDictionary(new { Controller = “Dummy”, Action = “Dummy” }),

new RouteValueDictionary(new { Controller = “Dummy”, Action = “Dummy” }),

routeHandler);

If it walks like a class, talks like a class, it probably is a class

I occasionally come across attempts to extend Enums to include additional fields.  These attempts typically use Attributes and reflection to get at the extra values.  I have to say I don’t like them.  The most extreme example of trying to get an Enum to do something else was this article on Code Project attempting to create a new type of enum: http://www.codeproject.com/KB/cs/EnumBuilder.aspx. Eugh!

Why do folks get so obsessed with trying to make enums do things that classes do better?

  • As soon as you hit a limitation that an Enum can’t handle your best bet is to create a class.
  • Need inheritance => use classes
  • Need more than one value on the object => use a class
  • Need more control over ToString() => use a class
  • Need to be able to localize the string value => use a class
  • Might need to do any of these in the future => use a class
  • If in doubt => use a class

If you do this your code will be

  1. more readable: you can say “x is Duck” instead of “x == Animal.Duck”
  2. more maintainable
  3. more extensible
  4. more object oriented (less switch statements and branching code)
  5. easier to localize (if you use the Enum’s name in the UI which isn’t a good practice anyway)
  6. almost certainly more efficient than using enums and reflection

The Blog of Ian Mercer: Home Automation++

This is the blog of Ian Mercer, Serial entrepreneur, Digital Mapping Pioneer, Inventor of Windows Movie Maker, Microsoft Producer, HighMat, SnapTune, … Patent holder, Guinness world record holder, and founder and CEO of SignSwift, LLC,

Here you’ll find my thoughts on Home automation, Energy Conservation, Programming, Operations, Entrepreneurship, Business, Startups, Quality, Agile, Optimization, .NET, Natural Language Processing, Digital Signage and more.

Home Automation Energy SavingMy home automation system recently won 1st and 3rd place in the international, Microsoft MyDotNetStory competition.  You can view a demonstration of it under the home automation menu above.  I believe that it is the world’s smartest house because I haven’t seen anything smarter.  It controls lights, heating, sprinklers, audio, and more; it has hundreds of sensors including PIR, strain gauges, door switches, and more; it interfaces to Caller ID, PBX, Google Calendar, Google Contacts, Email, NOAA, Twitter, Facebook, RSS, Traffic, Podcasts and more. For the most part it works autonomously doing the right thing and reducing our energy consumption by over 40%.  You can control it using a web, voice or chat interface.  It has a unique Natural Language Interface that understands sentences and can hold a two-way conversation with you.

Keyword diagram snippetUnder the SEO menu you’ll find my SEO keyword mapping tool; it can untangle a list of keyword phrases and volumes (like you get from Google’s Adwords tools) to give you a clearer picture of the keywords you need to put on your pages.  Using variable sized boxes and lines it shows you which words are the most important and how they are linked.

Thoughts under programming are mostly related to Microsoft’s .NET platform and the C# language but there are some that are more general in nature.  I’ve been using Visual Studio 2010 and .NET 4 extensively recently including the Entity Framework, WCF, WPF and Silverlight.

You can view my professional profile on Linkedin or follow me on Twitter.

I’m also an avid photographer and videographer and I’m in the process of adding a few of my favorite pictures to the site.

Tip: getting the index in a foreeach statement

Using LINQ you can easily get at the index in a foreach statement.

List x = new List() {"a", "b", "c"};

var augmented = x.Select((item, index) => new { item = s, index = index });
foreach (var d in augmented)
{
Console.WriteLine(d.item + " " + d.index);
}
Console.ReadKey();

a 0
b 1
c 2

SQL Server – error: 18456, severity: 14, state: 38 – Incorrect Login

Despite the error message this problem can be caused by something other than an Authorization failure.  In fact, simply misspelling the Initial Catalog can cause this message to appear.  I wish developers wouldn’t reuse error messages when the problem and solution is completely different.

Shortened URLs should be treated like a Codec …

Codecs are used to compress data to send over the wire, but when it gets to the other end it is decoded back to its original form for display.

Shortened URLs are used to compress long URLs to send over Twitter.

So why aren’t they expanded again on the other side? Why do Twitter clients show short urls instead of expanding them back out to a long URL, or at least a display that tells you what the real web site is.

This has implications for reducing attacks hidden in short URLs and for allowing you to see at a glance that “Check out http://bit.ly/a567as” is actually the same site you’ve already read once today from another Tweet.

So for my own Twitter client I decided to expand all shortened URLs as far as I could go. Here’s a code snippet to do that:-

        /// <summary>

        /// Follow any redirects to get back to the original URL

        /// </summary>

        private string UrlLengthen(string url)

        {

            string newurl = url;

 

            bool redirecting = true;

 

            while (redirecting)

            {

 

                try

                {

                    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(newurl);

                    request.AllowAutoRedirect = false;

                    request.UserAgent = “Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 4.0.20506)”;

                    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                    if ((int)response.StatusCode == 301 || (int)response.StatusCode == 302)

                    {

                        string uriString = response.Headers["Location"];

                        Log.Debug(“Redirecting “ + newurl + ” to “ + uriString + ” because “ + response.StatusCode);

                        newurl = uriString;

                        // and keep going

                    }

                    else

                    {

                        Log.Debug(“Not redirecting “ + url + ” because “ + response.StatusCode);

                        redirecting = false;

                    }

                }

                catch (Exception ex)

                {

                    ex.Data.Add(“url”, newurl);

                    Exceptions.ExceptionRecord.ReportCritical(ex);

                    redirecting = false;

                }

            }

            return newurl;

        }