September 2004 - Posts

Ugly XmlSerializer bug that generates invalid XML for required+fixed attributes.

Note: this entry has moved.

One common way of signaling the version of a configuration file that the processor of that file understands, is having an attribute (i.e. SchemaVersion) with the attributes use="required" fixed="[required version]". This way, all config files need to include such an attribute. When you evolve the schema, you can allow say "2.0" and most probably have  XSLTs that automatically upgrades older versions, based on the version number you receive.

But this will not work with the XmlSerializer, not in Everett, neither in Whidbey so far.

The XSD 2 classes conversion process transforms an attribute that is both required and has a fixed value into the following class member (will be just a public field in v1.x):

        [System.ComponentModel.DefaultValueAttribute("1.0")]
        public string SchemaVersion {
            get {
                return this.schemaVersionField;
            }
            set {
                this.schemaVersionField = value;
            }
        }

The class constructor will initialize the field value to the fixed value specified in the XSD (and the serialization attribute).

When the XmlSerializer finds such a property, it generates the following code:

if (((global::System.String)o.@SchemaVersion) != @"1.0") {
    WriteAttribute(@"SchemaVersion", @"", ((global::System.String)o.@SchemaVersion));
}

This means that it will only serialize the attribute to the XML output if it was given a value other than the required one. This rule doesn't make sense. This means it will generate XML that doesn't validate against the schema it was created from.

So if you create an instance of the class (or deserialize from a valid XML file), assign the required property to the required value (which isn't necessary because it will already have the initialized value), that property it will never get serialized, no matter what.

This effectively means that you not roundtrip:  valid XML -> Object Model -> valid XML. The third step will always be invalid, as the attribute is not emited.

Repro:

  1. Create an XSD file with an element that has an attribute required and with a fixed value.
  2. Call XSD.EXE /c with it to generate the class.
  3. Create an XML that is valid according to the schema.
  4. Create a console app that uses the XmlSerializer to deserialize the XML into the classes, using XSD validating reader
  5. Use the serializer to serialize the in-memory representation of the XML into a stream again
  6. Try to deserialize again with this new stream, using an XSD validating reader.

Solution to the problem may be to have a new XML Serialization attribute which signals the attribute has a fixed value (so it should always be emited, unlike the DefaultValue one).

Please vote for this bug, I think it's an important one.

How to make Microsoft work for you

Note: this entry has moved.

Microsoft Patterns & Practices (a.k.a. PAG or Prescriptive Arquitecture Guidance) ships guides and application blocks based mostly on customer feedback. They are now working on the next generation of Smart Client tools. If you develop rich client apps, you know it's not easy to be "smart" besides just being "rich". Now you have an opportunity to put MS to work on your problems by filling the survey they prepared for that.

Believe me, they do extensive analysis on these surveys, and they definitely shape what's delivered.
When a bug becomes a really useful feature

Note: this entry has moved.

I have to take quite a few screenshots for Victor's and mine last book and they have to be taken with 120dpi screen resolution. There's no way I will use such resolution in my laptop, and I also have to test the app in a fresh machine. Of course, the solution is using virtual machines, and I started using VPC 2004.

Well, I'm a keyboard guy, and as soon as I discovered that there's no way of getting out of the VM control unless you click on the host machine, I started to get annoyed. Just by chance, I discovered what looks like a bug but works like a really useful feature for me. Look at the following picture:



From inside the VM, hit Ctrl+Alt and release them. Now do Alt+Tab and voila!! You get TWO simultaneous popups for Alt+Tab, and when you release, you'll be taken to the selected one on the host machine! I don't really thing this is expected behavior, as what's happening is that both machines are being controlled at the same time, something that is usually contrary to VM's regular behavior. What's more, when you release the Alt key, both machines will change to the app selected (of course a different one in each!).

Anyway, very cool, and I don't need to touch the mouse anymore to go back and forth between them. Amazing "bugture".
vsCommandStatus illogical rules put to work

Note: this entry has moved.

I spend quite a bit of time trying to make the most "natural" scenario work:
  • you have an addin that creates some commands
  • you want those commands to be invisible when the addin is not loaded
  • you want your code (through QueryStatus) to determine if the command is shown or not when the addin is loaded
Well, look at these illogical rules for vsCommandStatus:
  1. vsCommandStatusInvisible: QueryStatus never gets called even if the addin is loaded (?!?!)
  2. vsCommandStatusInvisible + vsCommandStatusSupported: commands are always visible and enabled even if the addin is not loaded (?!)
  3. vsCommandStatusInvisible + vsCommandStatusEnabled: when the addin is loaded, commands are always grayed-out and QueryStatus is never called (?!). When the addin is not loaded, commands do not appear (OK).
  4. vsCommandStatusInvisible + vsCommandStatusUnsupported: commands are always visible, but grayed-out, even if the addin is not loaded and the QueryStatus is never called (?!)
  5. vsCommandStatusInvisible + vsCommandStatusEnabled + vsCommandStatusSupported: when the addin is loaded, commands are always visible/enabled and QueryStatus is never called (?!). When the addin is not loaded, commands do not appear (OK).
  6. vsCommandStatusInvisible + vsCommandStatusEnabled + vsCommandStatusLatched: commands are always visible but grayed-out and QueryStatus is never called (?!).
Is it just me or the vsCommandStatus rules don't make any sense at all?!?!?!?!

So far, I couldn't find a @#$%@#$%^ way to do the simplest thing in the world.... I'm runing out of ideas/status combinations... any ideas?!
A different paradigm for XML validation: all about Schematron

Note: this entry has moved.

In a very timely article, Dare Obasanjo introduces Schematron in an MSDN article entitled Improving XML Document Validation with Schematron.

I discovered Schematron two years ago, and decided to develop a pure XPath-based implementation in C#, which was also an amazing project to learn System.Xml in depth. In November that year, I presented the project in .NET ONE 2002 in Frankfurt (in an really surprising move and amazing lack of netiquette, the company organizing the event has simply removed all previous conferences materials, so I could only find a link to last year's .NET ONE 2003. Maybe I should let Ralf know, he was one of the organizers...).

I found Schematron to be an amazing extension to my XML toolbox. It makes it very easy to declaratively specify rule-based conditions that must be satisfied in a document in order to be valid. But not only that, it allows natural language reporting of errors in the document, which makes it far more user friendly than XSDs criptic (for an end-user) error messages. Schematron is already on Dare's list of nice-to-have features for System.Xml v3.

Aaron Skonnard has already shown the power of XPath-based rules for XML validation and how it can be integrated with the WebMethod framework, although this approach is fundamentally flawed, as it puts again business rules in the compiled code, removing all benefits of a declarative language as XML and XPath.

This year it's time to present Schematron at Applied XML Developer's Conference. Besides showing the basis of Schematron, and what it's good for and how it can suplement XSDs, I'll show cool WebMethod framework integration, which allows you to specify a schema, phase, and output format for Schematron validation of incoming messages. I'll also discuss the future of Schematron and its upcoming ISO standarization (there's a prelimiar draft of the spec).

So, if you want to lean more about it, or if you engage with a bunch of amazing industry-renowned professionals in the XML field (not that I consider myself one, of course), register for the conference ASAP, as all previous DevCons were sold out. You should really hurry up, as there's little extra space left.

Microsoft is listening

Note: this entry has moved.

You may have heard about the MSDN Product Feedback Center: it's MS's new way of communicating with the community of users of their products, not only to report bugs but to receive suggestions. At first, I wouldn't believe what they said: that most of what you enter in this site goes directly to the appropriate product group **real** bug database. I saw it with my own eyes. Believe it, and take advantage of it.

I've reported some that have been fixed, and some others that are not fixed but allowed us to know why MS made certain decisions. You can agree or disagree with them, but at least you know the reason.

But most importantly, you can get NEW features implemented, if they are well justified. For example, based on previous experience, I suggested that the XPathNavigator.Compile should be static in addition to the virtual one, as XPathExpression compilation does not actually require an instance document. They listened, and after some time (I admit I was skeptical about it) they decided you'll have such static method, and it will be thanks to me!!! Isn't that fantastic? Having your very small piece of responsiblity on what's there and how it behaves?

So, next time you find a method you think is missing overloads, or a missing one, or some behavior you don't like, or generally any bug, don't just find a workaround for it. Go report it, and become part of the history of .NET (well, maybe that's saying too much for a little contribution... hehe... but it makes me feel really good... you should definitely give it a try).
More Posts

Search

Go

This Blog

News

     

      Microsoft MVP Profile

Syndication