Why I like WPF, yet dislike Web Forms

I have been playing with WPF over the past few weeks, and I kind of like it. What’s odd is I hate Web Forms, which has very similar concepts to WPF. Concepts like controls, data binding, data templates, etc…

Why do I think WPF works while Web Forms don’t?

The first step is really understanding what I dislike in Web Forms. Two reasons, ViewState and controls.

ViewState

I hate the ViewState. It is a very complex mechanism of changing a stateless medium, HTTP, into a stateful one. While it accomplishes that task, I don’t believe the trade-offs are worth it. Developers must understand how HTTP works, and how the ViewState works. It is not an abstraction that allows ignorance because it leaks all the intricacies of HTTP as well as adding a ton of complexity on top of it.

I think understanding HTTP is stateless and coding your application to work in that medium is much easier than coding your application to be stateful and fixing it to work in a stateless medium.

Controls

Imagine you had a markup language that controls how something is displayed. It is ubiquitous and highly standardized. Now create an abstraction that wraps it, hides the simplicity, and adds ViewState, which I obviously don’t like. That is what controls in Web Forms are.

Let me interject that I don’t hate controls like I hate the ViewState. I actually like some of the principles behind them. The ability to easily reuse HTML is great. The ability to data-bind to objects is awesome.

What I don’t like is the fact that I believe it is an unnecessary abstraction. At the end of the day, all a browser cares about is HTML. And I love HTML and am good at HTML. Why take that away from me? Not to mention things like repeaters are just foreach loops.

Why is WPF different?

Two reasons that you can probably guess.

Desktop apps are stateful. There is no ViewState. There is just memory. And I understand memory.

Controls are the real thing, not an abstraction around the real thing (Yes I understand they are actually an abstraction around something, but it is a good abstraction. One that doesn’t leak like crazy. I can ignore how it works under the hood).

Now WPF isn’t perfect. Unit testing out of the bag isn’t easy, but it is possible. Just like using model-view-presenter is possible in web forms.

Importance of trace enabled=”false”

I was reading through some posts on ASP.NET best practices, and a lot is mentioned about <compilation debug=”false” /> on production machines. One thing that seems to be glossed over is <trace enabled=”false” />. Obviously, tracing is a security concern, but does it hurt your application in other ways?

The biggest area I thought tracing could effect an application was memory, so I wanted to see the memory differences of having trace enabled, vs having it disabled.

Test #1 – Trace enabled

<trace requestLimit="5000" enabled="true" mostRecent="false"/>

I loaded up an instance of one of our ASP.NET applications on my machine, and ran a script that generated random hits on a few of the pages.

After about ~4500 requests, here is what perfmon read.
trace

Test #2 – No Tracing

<trace requestLimit="5000" enabled="false" mostRecent="false"/>

Ran the script again, and saw some pretty interesting results.

notrace

The Word

At first, the results look the same, but look closer. With tracing enabled the # of Bytes in all Heaps is 710MB, vs 72MB without tracing. That’s a 10x difference! The Gen 2 heap is where most of the difference lies, which is a whopping 692MB vs 65MB. This heap should only contain very long lived objects. Having a growing Gen 2 heap is also going to indicate the need for IIS to recycle soon, since memory obviously isn’t getting deallocated.

If you are running with <deployment retail=”true”/>, then you don’t have to worry about this on production machines. Still, it is important to know the effects that tracing can have on you live environment.

If this graph isn’t making a lot of sense, check out this article on debugging memory problems.

How to actually use trigonometry in web applications

Disclaimer: my teammate Dellanoce actually coded this, but is too cool to blog, so I am blogging for him.

Mailtrust has many different customers, some of which like to have their own branded control panel or webmail interface. We allow them to customize many different facets of the user interface, including colors. This has some unintended consequences though. Sometimes, a user might select a white font color on top of a white background. This in turns causes support to get involved in fixing the problem, which wastes time on such a trivial problem.

But there is a better way. Use trigonometry, or more specifically the Pythagorean theorem! I had no idea how this worked, but Dellanoce coded up a few lines of C# to compare two colors. It returns a distance value which can be compared to a threshold value you can set.

1
2
3
4
5
6
7
8
9
10
11
        private static double ColorDifference(string htmlColor1, string htmlColor2)
        {
            Color color1 = ColorTranslator.FromHtml(htmlColor1);
            Color color2 = ColorTranslator.FromHtml(htmlColor2);
 
            double rDiff = Convert.ToDouble(color1.R) - Convert.ToDouble(color2.R);
            double gDiff = Convert.ToDouble(color1.G) - Convert.ToDouble(color2.G);
            double bDiff = Convert.ToDouble(color1.B) - Convert.ToDouble(color2.B);
 
            return Math.Sqrt((rDiff * rDiff) + (gDiff * gDiff) + (bDiff * bDiff));
        }

I was quite impressed with the simplicity and elegance this solution provided. I should probably go give my, or his, trig teacher a hug.

If you want to learn more about how powerful Pythagorean theorem is to compare distance values of really any type of object, check this article out.

CallContext isn’t the greatest thing since sliced bread

In ASP.NET, it is quite common to need to store information in the context of a single web request. For example, a NHibernate session should usually exist for one web request. HttpContext is the tool for accomplishing this.

But what happens when you have code embedded in business logic that might not always be running in an ASP.NET web application? HttpContext isn’t valid, so you can’t use it. Why not use CallContext, since HttpContext uses this anyways?

I was starting to convert some of my code to use this, when I found this article. Apparently doing this works most of the time but can cause some nasty bugs since ASP.NET can switch HttpContext‘s without switching CallContext‘s.

Instead, code that could be called from ASP.NET and other applications should first check for context.

1
2
3
4
5
6
7
8
9
10
11
12
if(HttpContext.Current == null)
{
     //Using CallContext example since not in ASP.NET
     CallContext.SetData("blah", new object());
     object contextData = CallContext.GetData("blah");
}
else
{
     //Using HttpContext example since in ASP.NET
     HttpContext.Current.Items.Add("blah", new object());
     object contextData = HttpContext.Current.Items["blah"];
}

In fact, I will probably end up writing a static class to implement this so code doesn’t have to constantly check whether or not in an ASP.NET session.

Policy Inject Me

I just started using the Policy Injection Application Block from Microsoft’s Enterprise library. At first, I thought it was worthless and overly complex. I was wrong. It is a very powerful programming tool that allows me to develop a lot faster and cleaner.

Policy Injection is similar to aspect-oriented programming in that it helps to break away cross-cutting concerns (authorization, logging) from the actual business logic. And yes, I basically copied that from the documentation.

Here is what policy injection means for me. I can build business logic, which performs only what I want it to. So I can have a function called AddUser and all that is done is the actual operation of adding that user. I can then attach policies to that function, which specify how to authorize and log it. This has a couple effects. One, it reduces the amount of code which in turn cleans up the code. Second, it allows me to customize cross-cutting concerns for different projects. If I have an administrative application, I need to authorize differently than a user application. Policy injection makes this possible without dirtying up the code.

After the initial few hours of getting used to using it, I am a huge proponent. I definitely recommend checking it out.