September 2007 - Posts

Using C# 3.0 Anonymous Types as Dictionaries

During a design meeting for a new feature in ASP.NET we had a requirement that a new method accept a dictionary of name/values pairs. An obvious solution is to have the method accept a parameter of type IDictionary (or its generic cousin):

public static string GetHtmlLink(string text, IDictionary<string, string> properties) {
...
}

While it looks nice and neat from the perspective of our function, the caller of this function has a real mess to deal with. Creating dictionaries is definitely somewhat of a pain. Since Dictionary<TKey, TValue> doesn't have an Add() method with one parameter you can't use C# 3.0's collection initializer syntax. This is some ugly code:

Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("key1", "value1");
values.Add("key2", "value2");
values.Add("key3", "value3");
GetHtmlLink("Click me", values);

My proposal: Have the method accept a parameter of type object. Callers could pass in a type that has properties with the appropriate names and values. They can use C#'s object initializer syntax to save some space:

MyParams myParams = new MyParams { Key1 = "value1", Key2 = "value2", Key3 = "value3" };
GetHtmlLink("Click me", myParams);

However, there was the added work of defining the MyParams type. Admittedly, it wasn't that hard with C# 3.0's automatic properties, but I hate defining types that are used in only one place. If the user can pass in an arbitrary object with properties, why not let that object be of an anonymous type? Here's the final code:

GetHtmlLink("Click me", new { Key1 = "value1", Key2 = "value2", Key3 = "value3" });

Woah! We went from five lines of code with dictionaries to two lines of code with object initializers (minus the type definition), to just one line of code with anonymous types!

So what does the GetHtmlLink method look like, anyway? Download the code from the attachment. You can now use the two helpers like so:

Sample link: <%= HtmlHelpers.GetHtmlLink("My Site", new { @class = "someStyle", href = "http://www.example.org" })%>
<br />
Sample URL: <%= HtmlHelpers.GetUrl("http://www.example.org/search", new { query = "kitten's mittens", mode = "details" })%>

And it'll render this HTML:

Sample link: <a class="someStyle" href="http://www.example.org">My Site</a>
<br />
Sample URL: http://www.example.org/search?query=kitten's+mittens&mode=details

So, what do you think?

I'm obviously ignoring certain aspects of this technique such as performance. There are certainly ways to optimize the performance with some clever caching. Performance might not be an issue anyway, depending on where this code is used.

Have you come up with a novel way to use a new language feature that you'd like to share?

Posted by Eilon with 54 comment(s)
Filed under:

ScriptManager's EnablePartialRendering and SupportsPartialRendering properties

In ASP.NET AJAX's ScriptManager control there are two properties that seem quite similar, but are in fact very different:

namespace System.Web.UI {
public class ScriptManager : Control {
public bool EnablePartialRendering { get; set; }
public bool SupportsPartialRendering { get; set; }
...
}
}

The primary difference between these two properties is who the audience is for each. EnablePartialRendering is intended for the page developer. That is, the person who is building the ASP.NET page and placing the ScriptManager on it. They get to decide whether they're interested at all in using the partial rendering feature. For example, for optimization purposes they might disable the partial rendering feature entirely to prevent any extra script from being downloaded. Or perhaps to debug an issue they want to temporarily disable UpdatePanels from doing async postbacks.

On the other hand, SupportsPartialRendering is mostly for component developers and sometimes for page developers. It's used in two ways, depending on the scenarios. The most common way is for control developers to check its value to see whether the current request is using partial rendering. The value is a combination of whether the page developer wants to use partial rendering (EnablePartialRendering) at all along with whether the current request supports partial rendering. To determine whether the request supports partial rendering the ScriptManager looks at the request's browser capabilities.

The other way that SupportsPartialRendering is used is for page developers who want to override the ScriptManager's default browser detection logic. When we release ASP.NET AJAX 1.0 we came up with a set of checks that worked great for the browsers we knew we supported at the time (IE6, IE7, Firefox, Safari, and maybe some others). Inevitably, the market of browsers has changed since then with newer browsers appearing, and our logic isn't always right. There's your chance to override it!

Another case people want to override our default browser detection is when proxies alter the browser headers. For example, I've heard from a number of customers that they are using web proxies that replace the HTTP User Agent header with the proxy's name and version. While I think that's a ridiculous thing for a proxy to do, that's how some of them do it. When ScriptManager sees "FooProxy v1.23" as the agent, it decides that it's not a known browser and won't let you use partial rendering. The customer's workaround was to set SupportsPartialRendering to true when EnablePartialRendering was true and the user agent was the FooProxy.

Posted by Eilon with no comments
Filed under: , , ,
More Posts