Archive

Archive for May, 2007

Command-Line Google Updated

I toyed around with using my command-line Google interface and noticed a couple serious flaws. I fired up the source code and cleaned it up a bit.

  • Still very lightweight and simple
  • You can now open a URL that was listed in a previous page
  • If you change your query term, the page number correctly resets itself to Page 1

http://www.jondavis.net/codeprojects/CmdGoogle/CmdGoogle.zip

Categories: Pet Projects

Windows Communication Framework (WCF): Beware the fake IDisposable implementation !!

Yeesh. My fascination with WCF became red-faced shame overnight.

We’re using WCF client/server both on a server, so an ASP.NET web app can query a custom indexing service. Since this was a fresh project with no legacy constraints, I opted to use WCF rather than remoting to…, well, to drink the kool-aid I suppose, but I thought the argument made at the AZGroups presentation that “you shouldn’t have to worry about the plumbing” was compelling. (Now that the solution is almost fully baked, I am really annoyed I went down this path simply because of the hassle I went through in having to manually populate the original strong types in a shared codebase between client and server. IMO, DataContract-driven proxy code is only useful for third parties.)

An initial WCF implementation with a simple loop of create, invoke, and drop scope a WCF client that used named pipes to a WCF service was freezing up after 12 iterations. Executing manually, roughly one iteration per second, it froze up on the 50th or so iteration.

Turned out I wasn’t calling Close() and should have been. *blush* Of course. But I looked for Dispose() to see if I could use the using() statement, and it wasn’t there. Or, wasn’t explicit, one must cast to IDisposable first before calling its Dispose() method.

Fixing that, now I was getting exceptions on Close() / Dispose() if the server had returned a Fault message. Buried deep in the far back of the WCF book I’m reading–and actually I had to use Reflector to figure this out before I looked in the book to see if I was right–is a brief mention not to use the using() statement with WCF clients, and don’t call Dispose(), either, but to call Close() manually. Dispose() on WCF clients actually call Close() internally. But just don’t expect the CLR / compiler to pick that up, and you shouldn’t always call Close(), either, but rather Abort(). Confused yet?

As I posted in Microsoft.public.windows.developer.winfx.indigo,

IDisposable was always percieved to be the happy, safe haven for getting rid of objects that use unmanaged resources. If something implemented IDisposable, Dispose() was always callable. Not so anymore.

((IDisposable)client).Dispose() can only be called on a WCF client if Close() can be called, because internally it calls Close(). Close() cannot be called unless basically it’s in the Open state; otherwise, you have to execute Abort() instead, which is not a memeber of IDisposable. This means that, even though the object does indeed implement IDisposable, its *SUPPORT* for IDisposable is 100% dependent upon the caller evaluating the State of the object to determine whether or not it’s open. In other words, Microsoft has established a new precedent: IDisposable mandates extraneous state-checking code before its IDisposable implementation is usable, and the only thing you can do about it is wrap it.

I might’ve opted to create a new interface, IReallyDispose, but then I’d still have to implement it. I could create an abstract class, WcfDisposable, but C# doesn’t support multiple inheritance. The best I can do is put a sticky note on my computer monitor that reads: "WCF client objects don’t REALLY implement IDisposable unless they’re Open!" Then I can only hope that I’ll pay attention to my stickynote when I’m going about WCF coding.

Does anyone else besides me find this to be unacceptably stupid and messy? I really *WANT* to like WCF. I love greenfield projects that use promising new technology, but when new technology abandons key design patterns like this, it really gets under my skin.

Discussing the matter further, ..

This isn’t about the object not being able to Close(). I don’t mind Close() raising exceptions. The core problem is that IDisposable throws an exception just because the object is in a "Faulted" state, while the object retains unmanaged resources!! IDisposable is generic and agnostic to connections/sockets/pipes/channels/streams, so I disagree when most people say "Dispose() and Close() are one and the same", because they’re not. What Dispose() is supposed to do is safely unload unmanaged resources, whether that means to Close() or not. WCF shouldn’t implement IDisposable if IDisposable.Dispose() will ever throw exceptions. I don’t care if Dispose() calls Close(), it should wrap that call with …

void IDisposable.Dispose()
{
	if (this.State == CommunicationState.Closing ||
		this.State == CommunicationState.Closed ||
		this.State == CommunicationState.Faulted)
	{
		this.Abort();
	}
	else
	{
		this.Close();
	}
}

Instead, Reflector says it’s implemented as such:

void IDisposable.Dispose()
{
	this.Close();
}

Since IDisposable has compile-time support for managing resources with Dispose, including the using() statement, this implementation is garbage.

There should be a working IDisposable.Dispose() that clears out unmanaged resources if you are *NOT* working in a transaction and have nothing to "abort" except the open connection itself. IMO, outside of a transaction, disposal of any object is an "abortion".

The bug in the design isn’t just faulty Dispose(), but that IDisposable was implemented in the first place. The practice we are told to use is to ignore it, and to call Close() or Abort() ourselves. Therefore, it’s not disposable, it’s only Closable/Abortable, depending on state. Why, then, did they implement IDisposable?

Where does Microsoft stand on this? Well, according to this forum post [link], they couldn’t figure out what to do themselves, so they released it with it with no real solution. Literally, "for good or for ill we have landed where we have", which was to try{} to Close, catch{} to Abort. Oh, nice planning. My respect for Microsoft just went down about 50 points.

Categories: Software Development

AJAX Based Bandwidth Test

At work, I was tasked to add auto-playing Flash video feeds on the home page of one of our web sites, and I decided that before I do anything I should implement a quick AJAX-driven bandwidth check so that dial-up users aren’t fed a heavy video feed without prior user consent. I threw the test together in a matter of three or four hours, and sent the engineering team an e-mail letting them know that this is new working functionality we can use any time.

The funny thing about the timing is that on the same day another co-worker working on another web site needed the same functionality immediately. To be honest, I overheard talk about this, and so I hoped my contribution would be useful for that project as well. I have no doubt my co-worker could have accomplished the same task, but being able to drop off sharable solutions like this is part of what makes a team environment so valuable.

 

The Bandwidth Test: What It Is and How it Works

The functionality I’m referring to here is a bandwidth test using AJAX.

Actually, truth be told, it’s not all-out AJAX as there is no XML in use here, but there is an asynchronous Javascript-driven HTTP request for a string of bytes, and a measurement of the amount of time that took. Actually, there are two asychronous HTTP requests. The first request is for a single byte of data–this measures latency and HTTP overhead. The second request is for a larger set of bytes of data, i.e. 128KB, which is configurable as a control property. The amount of time taken for the first request (1B) is subtracted from the amount of time taken from the second request (128KB), and this measures Pipe Speed. The requests are both sent to a "callback" URL that you can configure, but by default it’s an .aspx file stored as "~/controls_callback/GenBytes.aspx?len=number_of_bytes".

(Please excuse the horribly crappy illustration — I had to use Paint.NET as I don’t have Adobe Illustrator installed on my laptop, and then on top of that Live Writer and/or Live Spaces does weird things to the image. Click to enlarge.)

The test is not intended to be exact, but to be an approximation to determine whether your connection is moderately fast or dog slow. But the accuracy of the test gets better the slower the connection is, so a slow connection–which comprises the more vulnerable web audience–will be less likely to have incorrect test results than a higher speed user.

The test is implemented on a site by adding a small, simple ASP.NET tag:

(Add to top of .aspx file:)
<%@ Register Src="~/controls/SpeedTest.ascx" TagPrefix="ajax" TagName="SpeedTest" %>

..

<ajax:SpeedTest runat="server" ExecuteTest="true" UseCookie="false" ClientCompleteFunction="myJavascriptFunction" />

The control automatically registers a block of Javascript to the containing Page. ExecuteTest="true" is the default setting–if you do not include this attribute, the test will execute, but setting it to False will result in no Javascript being added to the page at all. Why would the tag still be useful? Setting UseCookie="true" will add the test results to the cookie ("astLatency" and "astPipeSpeed") and will expose these values as properties. (If the cookies are already set and UseCookies is true, the test won’t execute anyway.) You might choose to execute the test on one page and then redirect (ExecuteTest="true"), and only read the resulting cookie on another page (ExecuteTest="false"). But if the first hit can make a safe, untested assumption — the test is asynchronous, after all — then you might as well just put the control on your content page, turn on the test, and set ExecuteTest="false" on the next hit from the same visitor, when the cookie has been set.

Properties:

ExecuteTest (gets/sets bool) true = Adds test script which auto-executes.
false = Doesn’t do anything client-side.
UseCookies (gets/sets bool) true = Disables test execution if the Request already has the assigned cookie.
false = Doesn’t evaluate cookies.
CookieExpires (gets/sets TimeSpan) TimeSpan in granularity of days to retain the cookie if UseCookies == true.
CookieLatency (gets/sets int?) Nullable<Int32> of the cookie value astLatency.
CookiePipeSpeed (gets/sets int?) Nullable<Int32> of the cookie value astPipeSpeed.
ClientCompleteFunction (gets/sets string) The name of your own Javascript function that executes when the test is complete. The function should accept two parameters: latency and pipeSpeed.
CallBackUrl (gets/sets string) The URL of the support .aspx file that dynamically generates bytes of a requested length.
ByteLength (gets/sets int) The number of bytes to be requested from the CallBackUrl.

You can download the whole thing and examine the Javascript in the control file (SpeedTest.ascx) here…

Download: http://www.jondavis.net/CodeProjects/SpeedCheck/SpeedCheck.zip

Demo (from a slow cable connection as host): http://www.jondavis.net/CodeProjects/SpeedCheck/SpeedTest.aspx

Categories: Web Development

XML-to-C# Code Generation

Altova probably hates me. Not their products, but the company. I’ve frequently wanted to give their product line a noble shot for utilization, but I never have time to give it a fair shot, so I am never able to afford to purchase it or give it a full recommendation to my employer. My old user ID shows up in their tutorial videos alongside generic examples of hackers and spammers. For years, I’d try reinstalling the product to get past the 30-day trial in hopes that I’d have time to really check their cool tools out. When they killed that ability, I tried doing it within a virtual machine. Now in VMs I cannot get a trial key anymore; perhaps my e-mail domain name is blocked.

But I often forget that there is no real need for an investment in some third party XML code generation tool like Altova’s XMLSpy or MapForce if you need a complete object model written in C# to introspect a deserialized XML file. After spending hours Googling for C# code generators from XML, I realized that the solution is right under my nose. And I don’t have to spend a dime for it.

Why Generate?

You might be asking, why are you trying to generate C# code? Doesn’t System.Xml.XmlDocument and its XPath support work well enough to do what you need to do with an XML document? The answer is, yes, sometimes. Sometimes Notepad.exe is sufficient to edit an .aspx file, too, but that doesn’t mean that having a good ASP.NET IDE w/ code generation, like Visual Studio, should be ignored for Notepad.

In fact, I was happy with using XmlDocument until I realized that some of the code I was tasked to maintain consisted of hundreds of lines of code that would read CDATA values into a business object’s own properties, like this:

XmlNode node = storyNode.SelectSingleNode("./title");
if (node != null && node.ChildNodes.Count > 0 && node.ChildNodes[0].value != null)
{
	this._title = node.ChildNodes[0].Value
}

node = storyNode.SelectSingleNode("./category");
if (node != null && node.ChildNodes.Count > 0 && node.ChildNodes[0].value != null)
{
	this._category = node.ChildNodes[0].Value
}

...

This just seemed silly to me. When I started working with a whole new XML schema that was even more complex, I decided that manually writing all that code is just ludicrous.

XML -> XSD

Visual Studio 2005 (of which there are freely downloadable Express versions, of course) has the ability to introspect an XML document to generate an XML Schema (.xsd). It’s really very simple: load the XML file into the IDE, then select "Create Schema" from the "XML" menu. Overwhelmed by the complexity of it all yet?

Bear in mind that the resulting Schema is not perfect. It must be validated–by you. If at first glance the schema looks fine, there’s a simple test to validate it: simply programmatically load your XML document while enforcing the schema. For my purposes, I found that most of the adjustments I needed to make were just to make "required" elements "optional", unless of course they were indeed required.

XSD -> C# Code

If the schema’s clean, all you need is the .NET Framwork SDK, which comes bundled with Visual Studio 2005. Tucked away therein is XSD.exe, which does the magic for you. All you have to do is pass it "/c" along with the name of the .xsd file and the new name of the .cs file you want it to auto-generate.

The generated C# code isn’t always perfect, either. To say nothing of the rough comment stubs, one or two textual content elements were completely ignored in my case–the attributes were exposed as C# properties but the content, which was CDATA, was not. Easy enough to fix. This was likely due to an imperfect XSD file, but since this was really a run-once-and-forget-about-it effort, I was not afraid of diving into the C# to add the missing properties.

        private string _value;
        [System.Xml.Serialization.XmlText()]
        public string value
        {
            get { return _value; }
            set { _value = value; }
        }

System.Xml.Serialization.XmlSerializer works flawlessly with the generated C# code. I created the following generic class for the generated classes to inherit, so that they automatically offer a Deserialize() method:

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;

namespace MyProject.XmlGen
{
    public class XmlDeserializer<T>
    {
        public static T Deserialize(string xmlFilePath)
        {
            using (FileStream stream = new FileStream(xmlFilePath, FileMode.Open))
            {
                return Deserialize(stream);
            }
        }
        public static T Deserialize(Stream xmlFileStream)
        {
            return (T)Serializer(typeof(T)).Deserialize(xmlFileStream);
        }

        public static T Deserialize(TextReader textReader)
        {
            return (T)Serializer(typeof(T)).Deserialize(textReader);
        }

        public static T Deserialize(XmlReader xmlReader)
        {
            return (T)Serializer(typeof(T)).Deserialize(xmlReader);
        }

        public static T Deserialize(XmlReader xmlReader, string encodingStyle)
        {
            return (T)Serializer(typeof(T)).Deserialize(xmlReader, encodingStyle);
        }

        public static T Deserialize(XmlReader xmlReader, XmlDeserializationEvents events)
        {
            return (T)Serializer(typeof(T)).Deserialize(xmlReader, events);
        }

        public static T Deserialize(XmlReader xmlReader, string encodingStyle, XmlDeserializationEvents events)
        {
            return (T)Serializer(typeof(T)).Deserialize(xmlReader, encodingStyle, events);
        }

        private static XmlSerializer _Serializer = null;
        private static XmlSerializer Serializer(Type t)
        {
            if (_Serializer == null) _Serializer = new XmlSerializer(t);
            return _Serializer;
        }

    }
}

So with this I just declare my generated C# as such:

public class MyGeneratedClass : XmlDeserializer<MyGeneratedClass>
{
 ...
}

Literally, now it takes a whopping ONE line of code to deserialize an XML file and access it as a complex object model.

MyGeneratedClass myObject = MyGeneratedClass.Deserialize(xmlFilePath);

Cheers.

Categories: Software Development