Feb 20

JavaScript gotcha: inherited properties do not get created until assignment

Everyone know JavaScript has some weird gotchas, such as the already infamous JavaScript equality table. While a good framework / compiled language (such as LiveScript) will let you easily avoid a lot of them, there are things inherent to the way JS works that you can’t really sidestep. One example: properties defined on the prototype.

Let’s say we have a simple constructor function:

var ctor = function() {
  ctor.prototype.number = 15;

  ctor.prototype.increaseNumber = function() {
    this.number += 5;
  }
}

Now, here’s what would happen

var obj1 = new ctor();
var obj2 = new ctor();
obj1.number // 15
obj1.increaseNumber();
obj1.number // 20

obj2.number // 15

Everything as it should be. However, if the property was an object, and instead of setting its value you accessed it’s properties, something weird would happen:

ctor = function() {
  ctor.prototype.testObj = {};
  
  ctor.prototype.changeTestObj = function() {
    this.testObj.testValue = 50;
  }
}

obj1 = new ctor();
obj2 = new ctor();
obj1.changeTestObj();
obj1.testObj.testValue; // 50

obj2.testObj.testValue; // 50 - WTF!?

Those better at thinking in JavaScript probably aren’t surprised, but I sure was. Why would the value be modified on the instance in one case, but on the prototype on the other? The answer is, because JavaScript only creates instance copies on assignment. And since ctor.testObj is never actually assigned to from the object instance — only its property is accessed — JavaScript doesn’t create a new instance property and instead modifies the one in the prototype. Which means it modifies every “new ctor()” instance everywhere in the code.

The solution? Set the instance value in addition to prototype value in the constructor, if you must use prototype at all.

ctor = function() {
  // Do NOT use x = y = 12 assignment syntax, you'll just end up with the same
  // problem because of both instance and prototype properties pointing to the
  // same object
  this.testObj = {}; 
  ctor.prototype.testObj = {};
  
  ...
}

Apr 28

Why are you wishing cancer on me?

While the described problem is objectively real, this is, overall, an emotional rant. Adjust expectations & interpretation accordingly.

It started with Microsoft .NET’s MVC model binding (if you don’t know what model binding is, here is a short and simple explanation). Localization in a business application is not a luxury, or an extra, it is a fundamental, non-negotiable requirement. Do you know how to localize the error message that .NET’s DefaultModelBinder throws if you enter “Owl” in a text field that’s bound to an int? No, you don’t, and good luck finding out. If you dig deep enough in the source code for DefaultModelBinder, you will find the magic string that you need to put in your resources to make it work. Oh, you also wanted to localize the error message for when the value is missing (null) for a non-null variable? Dive right back in and look for the other magic string.

Mind, these are not some 1% edge cases, missing and wrong values are one of the most common errors in web data input. And if you want the error messages to say anything other than the default English text, you need to hunt through the source code for a hard-coded magic string that you then have to put in your resource (eliminating any custom localization mechanisms that don’t rely on the resource provider pattern). That’s not even insane, that’s just evil.

“Oh, I know”, you say, “I’ll just extend & override …” No. You will not. Because the part that generates the error message is buried so deep inside non-virtual and private methods that if you try, you will end up either giving up and wrangling with the resources, or giving up and re-writing the whole ModelBinder (or using mine, once I finish it and put it up on GitHub & NuGet) just so that you would have something that can actually be extended where it matters. And, quite possibly, murdering some kittens, in which you would be totally justified at that point.

Then came HtmlTags from the FubuMVC project. It’s a beautiful, elegant little library for generating HTML tags and passing them around as objects, thus allowing further modification by other parts of the code before output. This is opposite of the .NET’s MvcHtmlString, which is just that — a string (that’s protected from double-encoding).

And I was happily using it for a while, until I stumbled upon a seemingly trivial need that turned out to be an insurmountable challenge. What was this decadent, arrogant and completely unreasonable demand that I had the gall to expect from this humble little piece of code? I wanted *two* tags. Specifically, I wanted to take a HtmlTag and make a copy of it. And again, my evening was filled with one “can’t” after another. I can’t Clone() it because it’s not ICloneable. I can’t use a constructor that takes another HtmlTag and creates a copy of it, because there is no such constructor. I can’t use AutoMapper, because the tag’s attributes are of type HtmlTag.HtmlAttribute, which is a private class. And I can’t extend and override it because everything that isn’t already public, is private.

Why? Why do good programmers hate other programmers so much? I understand that making convenient extensibility points isn’t trivial, but what’s wrong with “protected”?

You know what? I’m just going to shortcut all this and declare — “private” is evil. “sealed” is evil. Unless you have a nuclear-bunker-rock-solid reason, every time I see “private” in someone’s code I will read it as “I hope whoever uses this gets cancer and dies”. Because that’s how it feels. Declaring private members in your code feels like you’re wishing cancer on me.

Please, “public/protected virtual” everything by default.

Thank you.

Apr 28

What is .NET MVC model binding

Model binding is the part of the framework that takes an input from a HTML form (or other formats) and converts it into an object in code. So that if you have this HTML form:

<form method="post" action="/BindModel">
  <input type="text" name="UserText" />
  <input type="text" name="UserNumber" />
  <input type="submit" value="Send" />
</form>

When you click the Send button, it will send whatever has been put into the input fields to the server, at the URL “/BindModel”. On the server side, in code, you have a simple class:

public class UserData {
  public String UserText { get; set; }
  public int UserNumber { get; set; }
}

Model binding lets you define an action like this:

[HttpPost]
public ActionResult BindModel(UserData input) {
  // code here
}

When the BindModel method is executed in response to clicking the Send button, model binding takes the contents of the form and copies the values over to the object (function argument) “input”. There will even be an error if the user entered something that isn’t a number in the second field, because the UserData class specifies that UserNumber is of “int” data type.

There is, of course, much more to it, but this is the core.

Dec 22

How to get MySQL working with Microsoft .NET’s Entity Framework 6

  1. Download and install the latest MySQL .NET Connector.
  2. Add [MySQL.Data] and [MySql.Data.Entity for EF6] assembly references for your .NET Framework version (hover over the assembly to see its framework version in its .dll path).
  3. Use NuGet Package Manager to install Entity Framework.
  4. Modify Web.config’s section to MySQL values (this will avoid the “No Entity Framework provider found for the ADO.NET provider with invariant name ‘MySql.Data.MySqlClient’.” error):
    <entityframework>
      <defaultconnectionfactory type="MySql.Data.Entity.MySqlConnectionFactory, MySql.Data.Entity.EF6">
        <parameters>
          <parameter value="v11.0"></parameter>
        </parameters>
      <providers>
        <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6"></provider>
      </providers>
    </defaultconnectionfactory></entityframework>
    
  5. Add the following to Web.config’s section:
    <system .data>
      <dbproviderfactories>
        <remove invariant="MySql.Data.MySqlClient"></remove>
        <add name="MySQL Data Provider"
             invariant="MySql.Data.MySqlClient"
             description="Data Provider for MySQL"
             type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.8.3.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"></add>
      </dbproviderfactories>
    </system>
    <connectionstrings>
      <add name="Storage"
           connectionString="server=localhost; User Id=user; Password=password; Persist Security Info=True; database=db_name;"
           providerName="MySql.Data.MySqlClient"></add>
    </connectionstrings>
    
  6. For migrations to work, add this to your migration Configuration class’ constructor:
    SetSqlGenerator("MySql.Data.MySqlClient", new MySql.Data.Entity.MySqlMigrationSqlGenerator());