Saturday, November 05, 2005

ASP.NET without JavaScript

It is possible, contrary to popular belief... asp.net without JavaScript

Saturday, October 15, 2005

Spring.NET - Application Framework

Check out the .NET version of the popular Spring framework. In short, Spring is a framework that allows your application to be highly configurable by using IoC (Inversion of control) principles, such as Dependency Injection. That is the heart of the framework. Framework also provides quite a few other goodies, such as ADO.NET helpers, threading utils, pooling. It is built to support Aspect-oriented programming, so most of the features require little changes to existing code. As of now, a preview of version 1.1 is available for download. Version 1.1 includes Spring.Web package, which is a set of features to simplify ASP.NET development by using Spring. It is really great, check it out! Here's a some of the features offered: master pages, bidirectional data binding, dynamic page navigation, a better way of writing web services.

Friday, October 07, 2005

XmlSerializer bug when "xsi:type" is used in the XML

There’s a subtle bug in the .NET Framework v1.1 that I have just uncovered. Firstly, a little background into the issue, which is related to .NET XML serialization.

Consider following XML (later assumed to be in a file “text.xml”):

<?xml version="1.0" encoding="utf-8" ?> <Test>  <Persons xmlns=”http://tempuri.org/” xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>   <Person xsi:type=”Male”>    <Name>Jeff</Name>    <FavouriteBeer>Monteith</FavouriteBeer>   </Person>   <Person xsi:type=”Female”>    <Name>Jessica</Name>    <FavouriteNailpolish>Revlon</FavouriteNailpolish>   </Person>  </Persons> </Test>

This would have been produced if you serialize the object of type Test, defined in the following code fragment:

[XmlIncludeAttribute(typeof(Male))] [XmlIncludeAttribute(typeof(Female))] [XmlTypeAttribute(Namespace=”http://tempuri.org/”)] public class Person {   public string Name; } [XmlTypeAttribute(Namespace=”http://tempuri.org/”)] public class Male : Person {   public string FavouriteBeer; } [XmlTypeAttribute(Namespace=”http://tempuri.org/”)] public class Female : Person {   public string FavouriteNailpolish; } [XmlTypeAttribute(Namespace=”http://tempuri.org/”)] [XmlRootAttribute(Namespace=”http://tempuri.org/”)] public class Test {   public Person[] Persons; }

The problem is that now you would not be able to deserialize the XML, if you write code similar to following:

XmlDocument doc = new XmlDocument(); doc.Load( “test.xml” ); XmlSerializer serializer = new XmlSerializer( typeof( Test ) ); Test test = (Test) serializer.Deserialize( new XmlNodeReader( doc ) );

And this is due to a bug in the XmlNodeReaderclass. I uncovered it only by stepping through the temporary serialization assembly generated by .NET framework. Without going into more detail, it is because LookupNamespace method does not return a canonical string from the reader’s NameTable. So the reference equality on the namespace inside the generated reader fails, and you get an exception similar to:

“The specified type was not recognized: name='Male', namespace='http://tempura.org/', at <Person xmlns='http://tempuri.org/'>.”

Fixing the problem is quite easy. All we have to do is write a class which extends from XmlNodeReader, and override the LookupNamespace method:

public class ProperXmlNodeReader : XmlNodeReader {   public ProperXmlNodeReader( XmlNode node ) : base( node )   {   }   public override string LookupNamespace(string prefix)   {     return NameTable.Add( base.LookupNamespace( prefix ) );   } }

Then you can use the ProperXmlNodeReader instead of the XmlNodeReader in the above example, and you should be able to deserialize the above XML with no problems.