Friday, July 23, 2010

The Difference Between XmlNode and XmlElement

Symptom:

You are confused why there are XmlNode and XmlElement classes.

Answer:

I was confused by this too. The confusion stems from the fact that if we deal with XML text (especially coming from the understanding of HTML and editing them with Notepad or whatever), what we normally deal with in XML are XmlElements. But in the Xml Standard, even the attributes within an element is a Node.

The detail is that XmlElements are the ones that has tags.

The second source of confusion is that just about everything in Xml is a subclass of XmlNode. That includes attributes in an XmlElement.

We should also note that in System.Xml namespace, XmlElement is a subclass of XmlLinkedNode class which is worthwhile examining in the Microsoft document.

All of this stems from the fact that Xml DOM (Document Object Model) dictates that everything is derived from the single Node class and System.Xml class classes closely follow this hierarchy.





Sunday, July 18, 2010

Creating XMLDocument from Program Embedded String in C#

Problem:

You want to quickly create a simple XML document without needing to write data to a file.

Solution:

Use StringReader class and feed that into the Load() function.

 Example Code:
XmlDocument doc = new XmlDocument();
doc.Load(new StringReader("<myNode>Hello</myNode>"));


Update: Well, that was doing too much, Load(string) would have worked just as well.

How To Use InsertAfter() in XmlDocument and Copy Nodes from another XmlDocument

Symptom:

You tried to insert an element (actually it has to be an XmlNode) using InsertAfter() or InsertBefore() method as doing so results in an exception with "The reference node is not a child of this node."

You also want to do the same but take a node from one XmlDocument to another.

Personally I feel that the Xml classes in the .NET Framework is not very intuitive. If you approach them as if they are regular List or Tree class type collection, then you will get a bunch of exceptions.

In terms of InsertAfter() type operations, this is a Node based operation and you normally cannot run InsertAfter() against the XmlDocument object. You must at least go down to the first child of the document, then invoke InsertAfter() at the node with the new node data (to be inserted) and the reference node location. This is most puzzling to me but that's what you need to do.

In terms of copying the data from a node in one document to another, all the nodes created or inserted in one XmlDocument have the membership to that XmlDocument. This is why new nodes must be created from the originating document using CreateElement() type calls. If you are familiar with creating a new row from the DataTable class, then you also know that you have to add that row to the table later is similar to this approach.

To confuse the matter, there are Clone type functions in XmlNode (see note below*). In this context they seem to be of no use (again that's not intuitive to me, since I tend to think if you clone it, I would say you created a detached instance.)

In actuality though, it is an error condition if you simply copy the node to another XmlDocument. This is also separate from where the node resides in overall tree of the nodes. ImportNode() simply buys the membership in another XmlDocument without reserving exactly where your own seat is.

Another important point to remember is that the Node (or Element) you insert to another XmlDocument should be the one returned from the ImportNode() method and not the one you passed to ImportNode(). If you try to insert the node that you passed to the ImportNode() method, you will get an exception "The node to be inserted is from a different document context."

XmlNode useThisNode = doc.ImortNode( myOriginalNode );


Solution Example:

The following code example demonstrates how InsertAfter() should (or at least could) be used, then add yet another node from another XmlDocument (created in-line in the code).

 XmlDocument Insertion Example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;
namespace XMLDocumentExample
{
class Program
{
static void Main(string[] args)
{
// === EXAMPLE 1: How To Use InsertAfter in XMLDocuments ========================
XmlDocument doc1 = new XmlDocument();
// This XPathNavigator creates a convenient way to Write out the tree on the console.
// we don't use it for nothing else in this example.
XPathNavigator nav1 = doc1.CreateNavigator();
// This creates the root document, which all XML documents will need.
// i.e. <doc1></doc1>
XmlElement e = doc1.CreateElement("doc1");
doc1.AppendChild(e);
// Everything in thid document are the child of the root. I will purposely make a
// Mistake here so that I don't have doc1.2.0 element. I will demonstrate inserting
// doc1.2.0 using InsertAfter.
/*
*
* <doc1>
<doc1.0.0 />
<doc1.1.0 />
<doc1.3.0 />
</doc1>
*
*/
XmlElement c = doc1.CreateElement("doc1.0.0");
e.AppendChild(c);
c = doc1.CreateElement("doc1.1.0");
e.AppendChild(c);
c = doc1.CreateElement("doc1.3.0");
e.AppendChild(c);
Console.WriteLine(nav1.OuterXml); // Will show you you have doc1.0.0, doc1.1.0 and doc1.3.0 now.
// Now we will try to add the missing doc1.2.0 and just as a bonus I will attach doc1.2.1 as the
// child of doc1.2.0
// First let's get to the node AFTER where we will insert doc1.2.0, so that will be doc1.1.0
// Note you can either use /doc1/doc1.1.0 or //doc1.1.0 as the XPath query.
XmlNode nod1_1_0 = doc1.SelectSingleNode("//doc1.1.0");
// This block of code assembles doc1.2.0 node and its child doc1.2.1
XmlElement n2 = doc1.CreateElement("doc1.2.0");
XmlElement n2c = doc1.CreateElement("doc1.2.1");
n2.AppendChild(n2c);
// This is the most tricky important part. You have to ask the parent node to InsertAfter, and not
// directly with doc1.
//XmlNode myParent = nod1_1_0.ParentNode;
//myParent.InsertAfter(n2, nod1_1_0);
XmlNode mp = doc1.FirstChild;
mp.InsertAfter(n2, nod1_1_0);
// The result would look like this:
/*
<doc1>
<doc1.0.0 />
<doc1.1.0 />
<doc1.2.0>
<doc1.2.1 />
</doc1.2.0>
<doc1.3.0 />
</doc1>
* */
// Write the tree out on the console.
Console.WriteLine(nav1.OuterXml);
// === EXAMPLE 2: Copy A Node from One XMLDocument to Another ==============
// Create the Second XmlDocument, and then copy a node in the second
// document into the first document.
XmlDocument doc2 = new XmlDocument();
doc2.AppendChild(doc2.CreateElement("doc2"));
doc2.FirstChild.AppendChild(doc2.CreateElement("doc2.0.0"));
XPathNavigator nav2 = doc2.CreateNavigator();
Console.WriteLine(nav2.OuterXml);
XmlNode node_2_0_0 = doc2.SelectSingleNode("//doc2.0.0");
// Note that this does not append the node, it simply says that
// a foreign node can now belong to the first document.
XmlNode importableNode = doc1.ImportNode(node_2_0_0, true);
doc1.SelectSingleNode("/doc1/").AppendChild(importableNode);
Console.WriteLine(nav1.OuterXml);
Console.ReadLine();
}
}
}



*Note: Cloning of a node is required when you need to make a copy of a node and insert that back into the same XmlDocument. It appears that you cannot make a reference to a node and insert that (of course, if you can do that then there is a side effect of both node data changing if you edit the content of one node.)


Handling Customer or Press Complaints of Issues

Symptom

Customers are equivocally complaining about some aspect of your product.

Solution:

I just watched the 15-minute video of Steve Jobs iPhone 4 July 16th Press Conference and I was very impressed the way he handled the situation. So next time something like that happens to me I am going to note what I've learned from this lesson.

Before you contact the customer the following preparation should be made:
  • Gather as much facts and historical information about the performance of the product, for example issue call or email history from the customer or other customers, and the same for other similar customer set. Note: This is why you should rigorously record all issues using some type of database.
  • Know the workarounds. In other words, don't even contact the customer or give a conference before you know the workarounds.
  • Be prepared with the software patch but do not release it before you contact the customer. Since visibility of your effort is important, do not install it until the customer can expect to see the improvements.

While contacting the customer:
  • First, create a less stressful and friendly atmosphere. Tell jokes, other stuff.
  • Begin with a positive tone by saying that your product is the best available, worked hard on it by best people and if you do have good reviews and so forth, tell them about that.
  • Next, indicate that you are puzzled why the customer is making such claims to the best product available.
  • But show that the customer is always right, so you say that "we have started to look into it."
  • First, say: "Nothing is Perfect. You know that, and I know that."
  • With not-so-surprised expression, talk about similar situations on other similar products. Tell customers that it is not just "our" product that is having the issue. Bring up the facts by video or verifiable statistics.
  • With a surprised expression (if your number is actually lower), explain about the claim by other verifiable (or at least authentic) figures such as previous dissatisfaction statistics (number of issue tickets, number of returns).
  • If you have a patch, inform the customer about it and then release or install it.
  • Deny most of allegations, but admit a little
  • Offer workarounds until the issue is completely solved, including refunds if that's possible.

Saturday, July 17, 2010

Unable to switch the encoding at System.Data.SqlClient.SqlConnection

Symptom:

You have done the following:
  • You have set up an SQL table with XML data type in it.
  • You have a Strongly Typed DataSet
  • You try to write XML from a C# String
  • You get the following error
You have a DataSet unable to switch the encoding at System.Data.SqlClient.SqlConnection

What Fixed It For Me

The part of the original XML which went into the string had


in the XML heading

by simply switching this to


That fixed the problem.

Note:
  • In my case the real issue was that the actual strung was encoded in Unicode (UTF-16) but the XML header said utf-8. That mismatched.
  • In your case the actual string may be encoded in some other format such as utf-8. Be sure to check. If the real encoding is the issue then you could re-encode your string from what you have into UTF-16. Look for System.Text.Encoding class on MSDN for further information.


Tuesday, July 13, 2010

Finding Uptime Using 'net statistics server' on Windows 2008 Server Does Not Work

Symptom:

You type in to a CMD.exe the following command,

net statistics server

and it was showing the uptime of the server on your Windows 2003 server, but when you tried this on a 64-bit Windows 2008 Enterprise R2, it does not show correct time.

Fix:

Though bizarre, try

net statistics workstation


Please note that in my situation the server is 2008 R2 SP2 but it still does not work with 'net statistics server' Since the workstation command works, I am OK by it.

Saturday, July 10, 2010

Ignoring .MySCMServerInfo in Visual Studio Web Project

Problem:
  • You are using Microsoft Visual Studio 2005, 2008, or 2010 with Seapine SurroundSCM.
  • When you are working with Web project you see annoying .MySCMServerInfo file in each directory and furthermore, VisualStudio make you check them in when SurroundSCM does not want you to check them in. You don't get this issue when you are working on non-Web (e.g., "desktop" or class library) projects.
Solution:


Just in case the answer link is lost in the future, the idea is to add the Ignorable File Key (yes, Key with the name of the file(s) you want to ignore and not the Data) with file names you want to ignore from the source control. It works on Version 8.0 (VS 2005), Version 9.0 (VS 2008) and Version 10.0 (VS2010).

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\10.0\Packages\
{8FF02D1A-C177-4ac8-A62F-88FC6EA65F57}\IgnorableFiles\.MySCMServerInfo]

Monday, July 05, 2010

ASP.NET MVC2 New Project Fails To Build with 'The type or namespace name 'Controllers' does not exist in the namespace..."

Symptom:

You have just created a brand new MVC2 Web project and tried to compile and run without anything modified and you get the following error:

The type or namespace name 'Controllers' does not exist in the namespace

What Fixed For Me:

The Unit Test project does not have the reference to the Main project. Just go to the Reference folder of the Unit Test Project and make a reference to the Main project.