When I have a problem and I spend a few hours scouring the internet only to find nothing related, I'm forced to draw one of three conclusions:

  1. I'm searching for the wrong thing.
  2. No one else has had this problem before. Ever.
  3. It isn't a real problem and I've done something dumb to get myself into a pickle.

I'm not sure which one this problem fits into, but I hope it will help someone anyways.

We recently implemented friendly error pages into our ASP.NET MVC app, which was a pain in of itself. Ben Foster outlined nicely the problems and a very nice solution on how to do this in this blog post. Thank you sir, for doing it right and sharing it with the world.

These worked beautifully until we tried to do a deployment. We pushed our app_offline.htm file to take the site offline, and instead of the nicely designed "Site undergoing maintenance" page, we saw this piece of junk:

The service is unavailable

The service is unavailable

Well, that's fantastic. After some troubleshooting we realized if we turned off httpErrors:

<httpErrors errorMode="Off" existingResponse="Replace">

The app_offline.htm page would work. How interesting? It seems that error codes not handled in this httpErrors section just output the default HTTP status code message. In this case, 503: The service is unavailable.

So, we can simply just handle 503 errors here:

<httpErrors errorMode="Custom" existingResponse="Replace">
    <remove statusCode="404"/>
    <error statusCode="404" path="404.html" responseMode="File" />
    <remove statusCode="500"/>
    <error statusCode="500" path="500.html" responseMode="File" />
    <remove statusCode="503"/>
    <error statusCode="503" path="app_offline.htm" responseMode="File" /> 
</httpErrors>

In theory, the only time a 503 is returned is when the app_offline.htm is present, so this works beautifully for us. Hope it works for you too!

Cheers, Rich
By Richard Rout
Feed
1 Comments
Only used for Gravatar avatar.

The kncokout js library is amazing. It's capable of making even the most complex JavaScript applications super simple and robust. Obviously it's not ideal in al situations, and there are a bunch of libraries that do similar things, but this one is incredible and it scales so well.

Enter Knockout!

We're now making a fairly large ASP.NET MVC application and we need a nice way of displaying and saving arrays of objects in our forms. Obviously there is no standard MVC EditorFor for doing this, so we looked at ways to make our own.

"Wouldn't it be cool if we didn't have to worry about arrays of JSON objects, having to send them to the page, edit them and then post them back?" Said one developer.
"That would be super cool... but how?" Said another.

Enter knockout! 

We can do this with a knockout binding. And we don't have to worry about setting model data to JavaScript objects, editing them or posting them back. That can all be handled. Here's how:

First we have an HTML element that uses the binding

<div data-bind="hiddens: { data: @Json.Encode(model.ComplicatedArray), name: 'ComplicatedArray' }">

Are you with me so far? Then we define our binding that looks a little something like this:

ko.bindingHandlers.hiddens = { 
    update: function(element, valueAccessor) { 
        var value = ko.mapping.toJS(valueAccessor().data); 
        $(element).empty().append(objectToHiddenDom(value, valueAccessor().name)); 
    } 
};

function objectToHiddenDom(value, namePrefix, hiddenArray) { 
    if (!hiddenArray) { 
        hiddenArray = []; 
    } 
    
    if (utils.isArray(value)) { 
        for (var i = 0; i < value.length; i++) { 
            utils.objectToHiddenDom(value[i], namePrefix + '[' + i + ']', hiddenArray); 
        } 
    } else if (utils.isObject(value)) { 
        for (var key in value) { 
            utils.objectToHiddenDom(value[key], namePrefix + '.' + key, hiddenArray); 
        } 
    } else { 
        // simple type, push to array 
        hiddenArray.push($('<input />').attr('type', 'hidden').attr('name', namePrefix).val(value)); 
    }
    return hiddenArray; 
};

When you run it your DOM might end up with a little something like this:

<div data-bind="hiddens: { data: [], name: 'ComplicatedArray' }">
    <input type="hidden" name="ComplicatedArray[0].Id" value="_1367629733949">
    <input type="hidden" name="ComplicatedArray[0].Name" value="Thing 1">
    <input type="hidden" name="ComplicatedArray[1].Id" value="_1367629738172">
    <input type="hidden" name="ComplicatedArray[1].Name" value="Thing 2">
    <input type="hidden" name="ComplicatedArray[2].Id" value="_1367629742061">
    <input type="hidden" name="ComplicatedArray[2].Name" value="Another Thing">
</div>

You don't have to care about what's inside the object, it doesn't even have to be an array. It figures all that out. This code does, however, have some performance issues with very very very large objects because it empties the DOM and recreates it every time. If anyone has any suggestions about this I would love to hear them.

Cheers, Rich
By Richard Rout
Feed
0 Comments
Only used for Gravatar avatar.