Skip to content
September 14, 2010 / Thomas Danemar

Unit testing HtmlHelper extensions that use Response.Write in ASP.NET MVC

Unit testing HtmlHelper extensions is usually fairly straight forward. However, when the extension uses Response.Write to output text, the way to test it is less obvious. Fortunately, the solution is simple.

The trick is to mock the HttpResponse and capture the printed text in a callback. Here’s how to do it using Moq, though you can easily do using any other competent mock framework:

private HtmlHelper helper;
private string responseText;

[SetUp]
private void Setup
{
	var viewContext = new Mock<ViewContext>();
	var response = new Mock<HttpResponseBase>();

	response.Setup(r => r.Write(It.IsAny<string>()))
		.Callback((string s) => responseText += s);
	viewContext.Setup(v => v.HttpContext.Response).Returns(response.Object);

	helper = new HtmlHelper(viewContext.Object, new Mock<IViewDataContainer>().Object);
}

You can then easily test what response text you got. Here I’m testing to make sure my extension printed the number of divs I told it to:

[Test]
private void SomeTest()
{
	helper.PrintSomeDivs(4);
	Assert.That(new Regex("<div>").Matches(responseText).Count, Is.EqualTo(4));
}
August 24, 2010 / Thomas Danemar

JQuery Serialize Method and Checkboxes

JQuery’s serialize method is handy when you want to convert the values of a form to a standard URL encoded query string, like so:

$("#myform").serialize(); // 'a=1&b=2&c=3'

However, only successful controls are included in the query string. That means checkboxes may not be serialized the way you expect them to. Checked checkboxes will be included with name only, and unchecked boxes won’t be included at all. So while you may expect a query string like:

'checkbox1=true&checkbox2=false'

What you’ll actually get is:

'checkbox1='

Sometimes you want the true/false type string though. Here’s a plugin that replaces the standard jQuery serialize with one that returns just that:

(function ($) {

     $.fn.serialize = function (options) {
         return $.param(this.serializeArray(options));
     };

     $.fn.serializeArray = function (options) {
         var o = $.extend({
         checkboxesAsBools: false
     }, options || {});

     var rselectTextarea = /select|textarea/i;
     var rinput = /text|hidden|password|search/i;

     return this.map(function () {
         return this.elements ? $.makeArray(this.elements) : this;
     })
     .filter(function () {
         return this.name && !this.disabled &&
             (this.checked
             || (o.checkboxesAsBools && this.type === 'checkbox')
             || rselectTextarea.test(this.nodeName)
             || rinput.test(this.type));
         })
         .map(function (i, elem) {
             var val = $(this).val();
             return val == null ?
             null :
             $.isArray(val) ?
             $.map(val, function (val, i) {
                 return { name: elem.name, value: val };
             }) :
             {
                 name: elem.name,
                 value: (o.checkboxesAsBools && this.type === 'checkbox') ? //moar ternaries!
                        (this.checked ? 'true' : 'false') :
                        val
             };
         }).get();
     };

})(jQuery);

This plugin is based on the actual jQuery serialize method, so most of it is not my code. Usage:

$("#myform").serialize({ checkboxesAsBools: true });

The default behaviour with no options passed in (or checkboxesAsBools set to false) is just like the standard jQuery serialize method.

//moar ternaries, moar!
January 19, 2010 / Thomas Danemar

Global Events with jQuery

Someone over at the jQuery Google group asked if it’s possible to use global events with jQuery, and to have individual elements listen to those events. A scenario could be to have a div update its content when a global update event is triggered.

This is certainly possible, but the solution is perhaps not entirely obvious. As you may know, you can use jQuery’s trigger function to trigger events on any object. The easiest way to implement global events is to just trigger an event on the global document object:

$(document).trigger("myCustomEvent");

And then listen to it with bind():


$(document).bind("myCustomEvent", function() {
   //code to execute when event triggers
});

Tinkering with the global document object is a bit icky though, and may even make Doug Crockford come over to your house and beat you with a stick. Better to use a dedicated object to hold your events, app.eventHolder, or whatever you feel like calling it.

Either way, having individual elements listen to these global events isn’t difficult, but there’s no dedicated function for it, and scoping it right may be tricky. I made a tiny plugin to help with this:

$.fn.bindToGlobalEvent = function(eventName, func) {
   $(app.eventHolder).bind(eventName, this, function(e) { func.call(e.data);
});

That’s all it takes, really. With this plugin, you could for example have a div change content when a global even triggers like so:

$("#someDiv").bindToGlobalEvent("myCustomEvent", function() {
   $(this).html("I was updated!");
});

November 19, 2009 / Thomas Danemar

Verbose Type Checking Must Die!

Ever since taking the plunge into the WPF world, I’ve found myself doing type checking more and more often, especially when using the MVVM (Model-View-Viewmodel) or MVP (Mode-View-Presenter) patterns. The main reason being the loosely typed nature of WPF databinding.

Our presenter/viewmodel code would be littered with snippets like this:

if (obj is SomeObject)
{
	var someObject = (SomeObject)obj;
	someObject.SomeProperty = true; // or whatever we want to do
}

Ew. Type checking data objects, then casting. Over and over again.

I believe that whenever you find yourself typing the same line of code you just typed minutes before, that’s your queue to take a pause and think about if there may be a better way of doing it. And, of course, there is, with a little help from extension methods and C# generics:

public static class Extentions
    {
        public static MyDataObject DoIfType<T>(this MyDataObject obj, Action<T> action)
		where T : MyDataObject
        {
            if (obj is T)
            {
                action((T)obj);
            }
            return obj;
        }
}

Here “MyDataObject” is the base class for all our data objects.

This lets us remake the first snippet like so:

obj.DoIfType<SomeObject>(s => s.SomeProperty = true);

Or if our intention is to pass SomeObject to another method:

obj.DoIfType<SomeObject>(AnotherMethod);

Serenity at last! I think this is cleaner and a lot more legible than the code we started with.

November 15, 2009 / Thomas Danemar

Using the VisualStateManager with the Model-View-Viewmodel (MVVM) pattern in WPF or Silverlight

The visual state manager is a powerful addition to WPF 4.0 that facilitates handling state visuals for WPF and Silverlight controls. For example, a button control could have the states “Pressed”, “Normal”, “Disabled”, etc., and have different looks for each of those states, with transitions between them. If you’re unfamiliar with the Visual State Manager, check out the Visual State Manager Overview, or ScottGu’s post.

The Visual State Manager is already a part of Silverlight 2, and will be in WPF 4.0. You can, however, use it already if you download the official WPF Toolkit.

Now, as nice as the VisualStateManager (VSM) is, anyone who has tried to use it with the Model-View-Viewmodel (MVVM) or Model-View-Presenter (MVP) will have run into some issues. The big showstopper is that to change states using the VSM, you have to pass the view as an argument:

VisualStateManager.GoToState(View, stateName, true);

If you’re using the MVP pattern, this is okay, since your presenter will likely be aware of the view. For example, if you’re using Caliburn (which, by the way, is an awesome framework for MVP or MVVM), you can do something like this:

private object View { get; set; }
public override void ViewLoaded(object view, object context)
{
	View = view;
	base.ViewLoaded(view, context);
}

private void ChangeStateTo(string stateName)
{
	Application.Current.Dispatcher.Invoke((System.Action) (delegate()
	{
		VisualStateManager.GoToState((Control)View, stateName, true);
	}), null);
}

This works just fine. But if you’re using MVVM this isn’t really a solution, since the viewmodel should not have to know about the view. Also, ideally you’d like to bind your visual state to a property on the presenter/viewmodel. Unit testing states will also be difficult like this.

The solution lies in WPF’s attached properties (ooh, don’t we just love those?). We’ll create a helper class with a VisualState depencency property, and in the PropertyChangedCallback method for that property we’ll pass the sender (which will be our view) and the new property value (which will be the name of the state) to the VisualStateManager:

public class StateManager : DependencyObject
{
	public static string GetVisualStateProperty(DependencyObject obj)
	{
		return (string)obj.GetValue(VisualStatePropertyProperty);
	}

	public static void SetVisualStateProperty(DependencyObject obj, string value)
	{
		obj.SetValue(VisualStatePropertyProperty, value);
	}

	public static readonly DependencyProperty VisualStatePropertyProperty =
		DependencyProperty.RegisterAttached(
		"VisualStateProperty",
		typeof(string),
		typeof(StateManager),
		new PropertyMetadata((s, e) =>
		{
		var propertyName = (string)e.NewValue;
		var ctrl = s as Control;
		if (ctrl == null)
			throw new InvalidOperationException("This attached property only supports types derived from Control.");
		System.Windows.VisualStateManager.GoToState(ctrl, (string)e.NewValue, true);
	}));
}

Now in XAML we can bind the VisualStateName string property on our viewmodel to our new helper class:

<UserControl x:Class="MyApp.SomeView"
//namespaces omitted for brevity
MyApp:StateManager.VisualStateProperty="{Binding VisualStateName}">

And that’s it! Our helper class will switch states on the view for us. The viewmodel no longer has to be aware of the view, and unit testing states becomes a lot easier.

November 9, 2009 / Thomas Danemar

JavaScript Stringbuilder, Because Concatenating With += Won’t Cut It

This is my StringBuilder. There are many like it, but this one is mine.

Ahem. Oh yes, StringBuilder. Why would you need a tool to help you build strings? Because concatenating a large amount of strings using += is pretty inefficient. Pushing the strings onto an array and then joining the array together at the end is a lot faster.
For an interesting analysis of the differences in performance, check out this post by by Josh Powell.

To the point. To faciliate adding to and joining arrays of strings, I made a version of the .NET StringBuilder class for JavaScript. Here it is:

var tools = {
	getStringBuilder: function() {
		var data = [];
		var counter = 0;
		return {
			// adds string s to the stringbuilder
			append: function(s) { data[counter++] = s; return this; },
			// removes j elements starting at i, or 1 if j is omitted
			remove: function(i, j) { data.splice(i, j || 1); return this; },
			// inserts string s at i
			insert: function(i, s) { data.splice(i, 0, s); return this; }
			// builds the string
			toString: function(s) { return data.join(s || ""); return this; },
        	};
    	}
};

The object “tools”, as your probably understand, is where I like to keep most of my utility functions like this one. Using it is fairly straight forward:

var sb = tools.getStringBuilder();
sb.append("Hi");
sb.append("there");
sb.append("buddy");
var greeting = sb.toString();

Or if you’re really a fan of the jQuery style of method chaining:

var greeting = tools.getStringBuilder()
   .append("Hi")
   .append("there")
   .append("buddy")
   .toString();

And that’s it!

(Yes, I’m aware I’m not the first one to write a StringBuilder for JavaScript. But I like this one so I’ll blog about it anyway.)

Follow

Get every new post delivered to your Inbox.