KeyValuePair<,> capable ASP.NET MVC5 model binder

Once upon a day I created a viewmodel class:

public class MyViewModel
{
    public List<KeyValuePair<string, int>> MyList { get; set; }
}

I wanted to use it as a parameter in my MVC action method. The wonderful model binding feature of MVC allows me to do that and it seemed to be working without error.
I got the exact number of key value pairs in my list property but the Key and Value props were always null and 0. I repeat: without any error!

After checking DefaultModelBinder’s source I realized that it will never work: KeyValuePair<,> is a struct, so assigning to variable means a copy and it’s members are readonly so can be set only during construction. The logic in DefaultModelBinder is different: it creates the model objects, handles them over via variable assignations, evaluates their member values and then assigns those values to members. There is a workaround implemented inside related to Dictionary<,>, but it’s logic isn’t reusable for my situation because the programmer didn’t intended to allow that (private methods) and the logic there is a bit smells for me.

There are solutions on the net, but those I found suffer from one common problem: they evaluate Key and Value on their onnw, which skips some goods of model binding, e.g. validation and model state propagation. Not too good.

Here comes my solution. ūüôā

First I created a new default model binder which in case of KeyValuePair<,> model type calls my BindModelViaKeyValuePairSubstitute from BindModel method but leaves all other things handled by original implementation.

public class KeyValuePairCapableDefaultModelBinder:DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
       object ret = null;

       if (TypeHelper.IsSubclassOf(bindingContext.ModelType, typeof(KeyValuePair<,>)))
       {
           ret =&nbsp;BindModelViaKeyValuePairSubstitute(controllerContext, bindingContext);
       }
       else
       {
           ret = base.BindModel(controllerContext, bindingContext);
       }

       return ret;
    }
}

I created a substitute class which overcomes the limitations: not a struct and has writable members.
To make the trick transparent to model binding the substitute class must contain members of same name and type as the KeyValuePair<,> we want to handle.


        /// <summary>
        /// KeyValuePair substitute.
        /// </summary>
        private class KeyValuePairSubstitute<TKey, TValue> : KeyValuePairSubstituteBase
        {
            public TKey Key { get { return (TKey)KeyAsObject; } set { KeyAsObject = value; } }
            public TValue Value { get { return (TValue)ValueAsObject; } set { ValueAsObject = value; } }

            public KeyValuePairSubstitute()
            {
                // set values to defaults to avoid NullReferenceExceptions when trying to get
                // an uninitialized null value from a generic type which cannot stand that (e.g. int).
                this.Key = default(TKey);
                this.Value = default(TValue);
            }
        }
        
        /// <summary>
        /// Base class for KeyValuePair substitute to allow access to generic values in handy way.
        /// </summary>
        private class KeyValuePairSubstituteBase
        {
            public object KeyAsObject { get; set; }
            public object ValueAsObject { get; set; }
        }

Now my BindModelViaKeyValuePairSubstitute is trivial.
The logic here is to let DefaultModelBinder bind our substitute object instead of a KeyValuePair<,> and then instantiate a KeyValuePair<,> from that object’s content.

        /// <summary>
        /// Default BindModel call doesnt handle KeyValuePair well, because it is a struct and has readonly props.
        /// It will return an instance with default values without any error!
        /// </summary>
        private object BindModelViaKeyValuePairSubstitute(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            object ret = null;

            var keyValuePairSubstituteGeneric = typeof(KeyValuePairSubstitute<,>).MakeGenericType(bindingContext.ModelType.GetGenericArguments());

            var kvpBindingContext = new ModelBindingContext()
            {
                ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, keyValuePairSubstituteGeneric),
                ModelName = bindingContext.ModelName,
                ModelState = bindingContext.ModelState,
                ValueProvider = bindingContext.ValueProvider
            };

            var keyValuePairSubstitute = (KeyValuePairSubstituteBase)base.BindModel(controllerContext, kvpBindingContext);

            ret = Activator.CreateInstance(bindingContext.ModelType, keyValuePairSubstitute.KeyAsObject, keyValuePairSubstitute.ValueAsObject);
            return ret;
        }

The last step: the new model binder should be registered in Application_Start as usual:

            ModelBinders.Binders.DefaultBinder = new CustomModelBinder();

That’s all. You have bindable and validable KeyValuePair<,>s now!

Danger of IEnumerables

IEnumerables and IEnumerable<T>s are a good thing:

  • They allow returning set of values with a minimum contract and behaviour promise. You may alter the underlying data structure later to virtually anything, because nobody was able to use Your retval in a way You didnt mention. For example if You used a List instead Your retval consumers may add to or remove items from it and become coupled to that retval type. See next too.
  • They allow returning unchangeable “lists”. Did You ever hunted a bug where Your retval instance was containing values which wasnt created by Your method?
  • They may be lazy. You shouldnt known that Your retval consumers how want to use Your data. You may have a resource eater mapping process to run on 1000s of items, but the consumer may only want the Firts() item!
  • LINQ. Just the whole thing uses IEnumerable‘s features and is returning something of this type.
  • Etc. There could be a lot of things.

So I tend to be using these as a retval in every place where the only thing I want to return multiple instances of something.

Now the 50cent question: will this test run green?

 

[TestMethod]
public void MyTestMethod()
{
    IEnumerable<MyClass> result = GetMyClassList();
    Assert.AreSame(result.First(), result.First());
}

Yes? Are You sure? Sure! The first item of an IEnumerable will always be the same!
Or not?
Lets see GetMyClassList‘s implementation:

 

public IEnumerable<MyClass> GetMyClassList()
{
    IEnumerable<MyClass> ret = new MyClass[] { new MyClass(1) };
    return ret;
}

Yes, in case of this implementation the test becomes green.
But how about this:


public IEnumerable<MyClass> GetMyClassList()
{
    IEnumerable<MyClass> ret = null;
 
    var someSourceList = new int[] { 1 };
    ret = someSourceList.Select(i => new MyClass(i));
 
    return ret;
}

Now the test became red!

Why?

Because IEnumerable promises only a sequential access to items.

To items they contain.

In the first case these are items of a fixed array.

But in the second case the items are the values returned by a LINQ projection, which contains a mapping body.

When I call First() twice the IEnumerable‘s enumerator can only be recreated or Reset() and start over the evaluation. So the new MyClass(i) will run again and again resulting in different instances and failing test. And the resource friendly lazy evaluation may become shortly really bad too…

There is nothing new in the above, but in my head the parts of the explanation didnt connect to each other before.

But wait a minute! Is this meaning that when I use an IEnumerable I should known about its creation method?!?! This would break the basics or OOP!

No, I shouldnt known anything about it, just remember: IEnumerable only promises a sequential access to items!

When I consume it in a way that dont requires Reset() or enumerator recreation I need no extra steps:


var firstItem = result.First();

But when the consumption method results in multi-enumeration I should “fix” its items via explicit enumeration, for example:


var fixedResult = result.ToArray();

That allows You to use IEnumerable in a way it was designed and saves some ugly moments of You valuable life. ūüôā

Misleading message

What You would do if You get the following result after running a unit test?

Assert.AreEqual failed. Expected:<2016.04.27. 8:22:52>. Actual:<2016.04.27. 8:22:52>.

My head was full with abstractions waiting to be coded, but the above result brings me in
unexpected state. Everything suspended and my eyes were scanning the two values character by
character repeatedly to find out what is the difference? Nothing!
A quick debug revealed that the values differ in milliseconds which are not shown in the message.

But what a misleading message! Maybe the difference should be emphasized somehow!
Because I lost my concentration, my flow, etc.
It was the same when You cannot work quietly because somebody always coming to You and asks
something. Anything. Applying the 8th point of the great article I found on Joel’s blog years before
to this situation: such messages are breaking down productivity and should be avoided.

Facebook SDK v4 behind a proxy

This is a really short note.

If You try to use this SDK behind a proxy e.g. in a Drupal site with simple_fb_connect module You may experience that the SDK wont honor Your proxy_server settings done sitewide. All requests try to go to FB servers directly and timing out. ūüôĀ

I made the change below to workaround this.

--- facebook-php-sdk-v4/src/Facebook/HttpClients/FacebookCurlHttpClient.php.orig        2016-04-04 21:42:21.846561162 +0200
+++ facebook-php-sdk-v4/src/Facebook/HttpClients/FacebookCurlHttpClient.php     2016-04-04 21:55:18.024673677 +0200
@@ -178,6 +178,8 @@
       CURLOPT_SSL_VERIFYHOST => 2,
       CURLOPT_SSL_VERIFYPEER => true,
       CURLOPT_CAINFO         => __DIR__ . '/certs/DigiCertHighAssuranceEVRootCA.pem',
+      CURLOPT_PROXY    => variable_get('proxy_server',''),
+      CURLOPT_PROXYPORT        => variable_get('proxy_port',''),
     );

     if ($method !== 'GET') {

Now the requests going to the proxy.

I didnt found any other solutions on the Internet. This may mean that there is a trivial point somewhere for this setting which I didnt found or nobody used before that SDK behind proxy?

A bug hunting story

Today I found a bug. It was so interesting that I decided to write a longer post here about it.
I created a strip down solution with the only classes and methods I need to demonstrate the bug. This is the reason if the story wont seem too realistic.

A long long time ago I need a dictionary to store some integers with a key which was based on a string but has some other features (not shown here). So I created MyKey class for this:

[Serializable]
public class MyKey
{
    private string key = null;

    public MyKey(string key)
    {
        if (key == null)
        {
            throw new ArgumentNullException("key");
        }

        this.key = key;
    }

    private int? hashCode = null;
    public override int GetHashCode()
    {
        int ret = 0;

        if (hashCode == null)
        {
            hashCode = this.key.GetHashCode();
        }

        ret = hashCode.Value;

        return ret;
    }

    public override bool Equals(object obj)
    {
        bool ret = false;

        MyKey other = obj as MyKey;
        if (other != null)
        {
            ret = Equals(other);
        }

        return ret;
    }

    public bool Equals(MyKey other)
    {
        bool ret = false;

        if (other != null)
        {
            if (this.hashCode == other.hashCode)
            {
                if (this.key == other.key)
                {
                    ret = true;
                }
            }
        }

        return ret;
    }

    public override string ToString()
    {
        string ret = String.Concat("\"", key, "\"");
        return ret;
    }
}

It was used happily like this:

// create data
var data = new Dictionary&lt;MyKey, int>();
data[new MyKey("alma")] = 1;

Later I wrote some code to persist these data via serialization.
Everything was working like a charm.

// serialize and save it
var serializedData = Serializer.Serialize(data);
SaveToFile(serializedData);

...

// load and deserialize data
var serializedData = LoadFromFile();
var data = Serializer.Deserialize(serializedData);

There was a usecase when after deserialization some of the values in data must be changed:

// as in deserialized data
var specificKey = new MyKey("alma");
if (data[specificKey] == 1) // a KeyNotFoundException occures here!
{
    data[specificKey] = 2;
}

KeyNotFoundException? I was sure that there should be a value in all of data instances with the given key! Lets see in QuickView:

quickview1

There is an “alma” key!
Let’s comment out the line causing the exception and check data after the expected value modification to “2”:

 

quickview2

Much more interesting isnt it?
I quickly put all the data creation, serialization, deserialization code into one unit test to have a working chunk of code I can use for bug hunting:

[TestMethod]
public void TestMethod1()
{
    var d = new Dictionary<mykey, int="">();
    d[new MyKey("alma")] = 1;

    var serialized = Serializer.Serialize(d);

    var data = Serializer.Deserialize(serialized);

    var specificKey = new MyKey("alma");
    {
        data[specificKey] = 2;
    }
}

But in the unit test everything was working! I simply cant reproduce the bug in such a way.
But when running App1, which was creating and serializing the data and running App2 which was deserializing and modifying it the bug always presents itself.
How can be a duplicate key in a Dictionary<,>? MyKey‘s implemetation, especially the Equals() override is so trivial that it cannot allow two instances created from
same string to be not equal.

But wait a minute!

quickview3

 

How can the hashCode’s differ?!?!?!

Yes. A quick search on the net answers everything. MSDN¬† clearly describes in a big “Important” box:

The hash code itself is not guaranteed to be stable. Hash codes for identical strings can differ across versions of the .NET Framework and across platforms (such as 32-bit and 64-bit) for a single version of the .NET Framework. In some cases, they can even differ by application domain.

As a result, hash codes should never be used outside of the application domain in which they were created, they should never be used as key fields in a collection, and they should never be persisted.

App1 was running in x86 and App2 in x64 environment. Thats why the string hashcodes differ.

The fix is really easy. Just turn off hashCode calculation optimalization for serialization:

[Serializable]
public class MyKey
{
   ...

   [NonSerialized]
   private int? hashCode = null;
   ...
}

Now hashCode will be recalculated once in all runtime environments.

I never thought about the possibility of unstable hashcodes.
I hope I am not the only man in the world with such wasteful brain.

IE11 on Win7: no password sent during Basic Authentication

Today I set up a download directory for one of our customers. I turned on basic authentication, gave a nice /=%27gujdw765 password and tried out from Firefox.
Everything worked. Then I tried via IE11. IE started to prompt me for credentials again and again.

I checked error log on webserver and found password mismatch messages. Tried again with same results.
Tried on my second machine with same results again.

I sent over the info to my deskmate. He tried the same in IE and it worked for him!
What the hell is happening to my machines?

I modified apache config to log Authorization header value:

CustomLog ${APACHE_LOG_DIR}/access.log  "\"%{Authorization}i\""

Now from access log it becomes clear, that my IE does not send my password over the wire!
E.g. in case of typed user name “myuser” and password “blahblah”:

"Basic bXl1c2VyOgo="

I started some experiments and found that sometimes the password was sent sometimes not.
But why?

You will never guess.

Because I was copy&pasing that nice password via clipboard AND used Shift+Insert key combination for pasting!
When I was doing my experiments I was typing directly “12345” into password field and it was sent gracefully.
My deskmate was using Ctrl+V which was working too.
But no one was able to send the password pasted via Shift+Insert!

After these it was easy to find the official info: https://support.microsoft.com/en-us/kb/2547752
It is known problem since 2011 and there is a fix for it.
But why wasnt it distributed via Windows Update since then?

assemblyBinding not working in web.config?

Check Your config’s configuration tag! Has it any namespaces? e.g.:

<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
   <runtime>
      <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
         <dependentAssembly>
            <assemblyIdentity name="SomeAssembly" publicKeyToken="..." />
            <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
         </dependentAssembly>
         ...

Remove namespace!

<configuration>
...

Voil√°, it starts working!

Credits to this poster.