The world has moved on, have you? Xml APIs you should avoid using.

There is a few Xml APIs you should not be using. In some cases the complier makes this obvious – the API is marked as obsolete and you will get a warning when compiling an application that uses any of these APIs. All the obsolete APIs have their replacements. The replacement for the obsolete XmlSchemaCollection class is the XmlSchemaSet class. The replacement for the obsolete XslTransform class is the XslCompiledTransform class (btw. I recommend reading Effective Xml Part 3: Didn’t you say XslCompiledTransform was fast? before moving from XslTransform to XslCompiledTransform. While it is pretty easy (too easy?) to move by just changing class name and fixing up parameters in method calls such a move will most likely make you transformations slow) . The reason why you should not be using deprecated APIs is that there is no active work going on in these areas – non security-critical bugs are not being fixed, new features are not being added, performance improvements are not being coded and finally the API may be removed in a future version of the .NET Framework (meaning the user of your application will update his/her machine and out of sudden the application may stop working).

Obsolete APIs are easy since the compiler helps identifying them but there are two more APIs you should avoid using – namely XmlTextReader and XmlTextWriter. We found a number of bugs in these classes which we could not fix without breaking existing applications. The easy route would be to deprecate these classes and ask people to use replacement APIs instead. Unfortunately these two classes cannot be marked as obsolete because they are part of ECMA-335 (Common Language Infrastructure) standard (http://www.ecma-international.org/publications/standards/Ecma-335.htm) – the companion CLILibrary.xml file which is a part of Partition IV).

The good news is that even though these classes are not deprecated there are replacement APIs for these in .NET Framework already and moving to them is relatively easy. First it is necessary to find the places where XmlTextReader or XmlTextWriter is being used (unfortunately it is a manual step). Now all the occurrences of XmlTextReader should be replaced with XmlReader and all the occurrences of XmlTextWriter should be replaced with XmlWriter (note that XmlTextReader derives from XmlReader and XmlTextWriter derives from XmlWriter so the app can already be using these e.g. as formal parameters). The last step is to change the way the XmlReader/XmlWriter objects are instantiated – instead of creating the reader/writer directly it is necessary to the static factory method .Create() present on both XmlReader and XmlWriter APIs. The factory method will create and return an implementation of XmlReader/XmlWriter depending on the settings (XmlWriterSettings/XmlReaderSettings) passed to the .Create() method (or default settings if no settings were passed). This pattern allows for introducing new settings and new implementations of XmlReader/XmlWriter classes in the future without having to change or add new APIs.

Thanks for reading the blog post. I appreciate your taking the time to express your opinion in a thoughtful way. One of the intents of providing such guidance as in our last post is to trigger valuable comments from outside Microsoft such as yours. Such input will help us in shaping this to be a better API in the future.

One of the main reason why we have two kinds of APIs for the doing same thing is compatibility. It was extremely important that applications written for .NET Framework 2.0 continued to work on .NET Framework 3.0 and 3.5. since both .NET Framework 3.0 and 3.5 were in-place updates. This means that once you installed a newer version of the .NET Framework on your machine all applications compiled against .NET Framework 2.0 would automatically run against the newer version you just installed. This excluded the possibility of removing any API in .NET Framework 3.0 or 3.5. From this point of view .NET Framework 4 was the first release we could potentially remove the APIs deprecated in .NET Framework 2.0. Unfortunately even in .NET Framework 4 there are still some classes not owned by the Xml team (e.g. System.Web.UI.WebControls.Xml) that use the obsolete APIs.

– XmlTextWriter allows for writing invalid Xml documents e.g. by not checking whether the characters written by the writer are valid Xml characters – msdn.microsoft.com/…/ms172416.aspx

Changing any of the above behaviors would break existing applications people may not even be able to fix (e.g. the source code has been lost). On the other hand not fixing these issues feels wrong. You can find more details about improvements introduced to the XmlReader and XmlWriter classes here:

Moving from XmlTextReader and XmlTextWriter to XmlReader and XmlWriter respectively is relatively easy for applications that use classes shipped with .NET Framework to read and write Xml documents which. I believe this is the way the vast majority of applications use Xml reader and writer APIs.

However if an application is using a reader/writer derived from XmlTextReader/XmlTextWriter then I agree that it may require a lot of effort to move. In any case it is still up to the user to decide whether to move or not. If the user decides that the benefits (e.g. character checking) won’t justify the cost then s/he may stick to the old APIs. In case of new applications – the msdn documentation for XmlTextReader and XmlTextWriter (and XmlReader and XmlWriter) for .NET Framework 2.0 and up recommends using XmlReader and XmlWriter APIs and creating instances using factory methods. Indeed, customizing the behavior of XmlReader and XmlWriter requires a bit more work than just deriving and overriding selected methods as you need to wrap the XmlReader/XmlWriter and forward the calls (as described http://www.tkachenko.com/…/000585.html) but it gives you all the functionality that is missing in XmlTextReader and XmlTextWriter classes.