Web Q&A

Web Services

Edited by Nancy Michell

Q I just converted my application to ASP.NET. All the middle-tier components return XmlDocuments. I'm planning to create Web Services for most of the components. How can I avoid making any further changes to the middle-tier components in the process?

Q I just converted my application to ASP.NET. All the middle-tier components return XmlDocuments. I'm planning to create Web Services for most of the components. How can I avoid making any further changes to the middle-tier components in the process?

A If you're just interested in the XML contents of the document, you should type your Web methods as XmlElement and return the XmlDocument's DocumentElement property. This will serialize the XML document from the root node, skipping the document declaration and any processing instructions (PIs) or other nodes before the document root. This is the safest way to return an XmlDocument from a Web method.

A If you're just interested in the XML contents of the document, you should type your Web methods as XmlElement and return the XmlDocument's DocumentElement property. This will serialize the XML document from the root node, skipping the document declaration and any processing instructions (PIs) or other nodes before the document root. This is the safest way to return an XmlDocument from a Web method.

Q I have to collect complex electronic forms from many external parties. The form is made up of a number of Microsoft® Excel 2000 spreadsheets with many macros, returned with a digital signature. The form takes a long time to fill in and is therefore usually saved offline before final submission.

Q I have to collect complex electronic forms from many external parties. The form is made up of a number of Microsoft® Excel 2000 spreadsheets with many macros, returned with a digital signature. The form takes a long time to fill in and is therefore usually saved offline before final submission.

I would like to know how to collect these forms using current Microsoft technology, taking advantage of the Microsoft .NET Framework and Web Services in my solution. Could the Microsoft Excel 2002 form template or file attachment be returned in a response for a Web Service? Could the completed form be submitted in a Web Service?

A Take a look at the Microsoft Office XP Resource Kit for BizTalk Server. It has a good, simple sample of how data is captured in Excel 2002, gets converted to XML, and then gets submitted to BizTalk via a Web Service. This should address some of your questions.

A Take a look at the Microsoft Office XP Resource Kit for BizTalk Server. It has a good, simple sample of how data is captured in Excel 2002, gets converted to XML, and then gets submitted to BizTalk via a Web Service. This should address some of your questions.

Q I'm having problems making POST requests to a Web Service. I can only use GET requests:

var x = new ActiveXObject("Microsoft.XMLHTTP");
      x.open("POST", "https://web",false);
      x.send("<foo/>");
      alert(x.status); //returns error code 500
 
var x = new ActiveXObject("Microsoft.XMLHTTP");
      x.open("GET", "http:web?sXml=",false);
      x.send();
      alert(x.status); //returns error code 200

If I POST to the page using an HTML form with its method attribute set to POST (to "https://web"), the server does not return a code 500 error and the Web method is invoked without issue. Why does this happen?

Q I'm having problems making POST requests to a Web Service. I can only use GET requests:

var x = new ActiveXObject("Microsoft.XMLHTTP");
      x.open("POST", "https://web",false);
      x.send("<foo/>");
      alert(x.status); //returns error code 500
 
var x = new ActiveXObject("Microsoft.XMLHTTP");
      x.open("GET", "http:web?sXml=",false);
      x.send();
      alert(x.status); //returns error code 200

If I POST to the page using an HTML form with its method attribute set to POST (to "https://web"), the server does not return a code 500 error and the Web method is invoked without issue. Why does this happen?

A The short answer to this problem is that you have to set Content-Type header to "application/x-www-form-urlencoded".

A The short answer to this problem is that you have to set Content-Type header to "application/x-www-form-urlencoded".

You can also find information in the Knowledge Base article "HOWTO: Submit Form Data by Using XMLHTTP or Server XMLHTTP Object". It explains why you have to change your content type, what's in the header and body, and shows how to use those two objects.

Q I'm looking for tips on getting the best performance from my use of the System.Xml classes in an ASP.NET Web Service. Would I see a benefit from long-term caching and reuse of System.Xml objects, like XmlDocument? What can and should I cache persistently and under what circumstances will I benefit?

Q I'm looking for tips on getting the best performance from my use of the System.Xml classes in an ASP.NET Web Service. Would I see a benefit from long-term caching and reuse of System.Xml objects, like XmlDocument? What can and should I cache persistently and under what circumstances will I benefit?

Also, when I load my XML document into an XmlDocument, my document is parsed and the resulting data is represented in some format internally. If I frequently load XML documents that look very similar—same tag names, same attributes, but some different inner text data—is there an advantage to pooling XmlDocument instances by the type of document they will be used to parse? In other words, document type A would be serviced by a single pool of XmlDocuments, and document type B would be serviced by another pool.

A Consider using XML serialization—you can deserialize your XML document into an object form and then use the objects you get to navigate to the data you want, all with IntelliSense support and type safety. Generally, XML serialization is much faster (by about a factor of 10) than loading the XML document each time. Plus you get many other advantages. For instance, you can provide code to process queries using virtual methods, and so on.

A Consider using XML serialization—you can deserialize your XML document into an object form and then use the objects you get to navigate to the data you want, all with IntelliSense support and type safety. Generally, XML serialization is much faster (by about a factor of 10) than loading the XML document each time. Plus you get many other advantages. For instance, you can provide code to process queries using virtual methods, and so on.

If you don't need to edit the XML document, a faster way to get the data is via the pull-model XML parsers: XmlTextReader and XmlValidatingReader. Use XmlTextReader for simple parsing or XmlValidatingReader if you need to validate the document or if you are using entities (XmlTextReader does not expand entities). For simple forward-only editing scenarios you can use XmlWriter to write the data out while you're reading from the XmlReader.

If you need to load the data in XmlDocument in order to store and edit it, then caching XmlDocument instances won't significantly improve your performance. You might gain some performance, however, by reusing the NameTables for the documents with the same type.

Q I plan to use Bulk Load of XML Data features in SQLXML 3.0 to load XML data directly into staging tables. Where can I specify the number of records in a batch? Otherwise, what kind of performance and scalability can I expect from the Bulk Load of XML Data features in SQLXML 3.0 for a very large XML data file?

Q I plan to use Bulk Load of XML Data features in SQLXML 3.0 to load XML data directly into staging tables. Where can I specify the number of records in a batch? Otherwise, what kind of performance and scalability can I expect from the Bulk Load of XML Data features in SQLXML 3.0 for a very large XML data file?

A Bulk Load uses the SQLOLEDB FastLoad interface (in nontransactional mode) or the BULK INSERT T-SQL command (in transactional mode) for the actual bulkloading, but this should not affect performance. Unless you are using the IgnoreDuplicateKeys option, the rows are only committed in the end, and the batching size is optimized by the FastLoad mechanism.

A Bulk Load uses the SQLOLEDB FastLoad interface (in nontransactional mode) or the BULK INSERT T-SQL command (in transactional mode) for the actual bulkloading, but this should not affect performance. Unless you are using the IgnoreDuplicateKeys option, the rows are only committed in the end, and the batching size is optimized by the FastLoad mechanism.

Since XML is not a row-based format, you cannot specify batch sizes. However, the data is streamed through a fast loading mechanism, so it should perform well for large amounts of XML.

Q I have some C# code that throws an exception that is caught in JScript®. However it seems that an entirely different object is caught, and any additional properties that existed in the C# exception are lost. Is there any way to specify the properties of the exception caught by JScript? I have complete control of the C# code, but the JScript must stay as it is. Here is the JScript:

try{
txt.deleteData(0, 10); // call my C# method
}
 
catch(e){
var result = e.code;// result should be 1
output(result);
}

Q I have some C# code that throws an exception that is caught in JScript®. However it seems that an entirely different object is caught, and any additional properties that existed in the C# exception are lost. Is there any way to specify the properties of the exception caught by JScript? I have complete control of the C# code, but the JScript must stay as it is. Here is the JScript:

try{
txt.deleteData(0, 10); // call my C# method
}
 
catch(e){
var result = e.code;// result should be 1
output(result);
}

A For reasons that are a little complicated to explain, JScript .NET wraps all exceptions in a JScriptException exception. You can access the wrapped exception through the InnerException property of the JScriptException exception. However you can say

catch(e : MyExceptionType)

in which case the engine will do the unwrapping for you.

A For reasons that are a little complicated to explain, JScript .NET wraps all exceptions in a JScriptException exception. You can access the wrapped exception through the InnerException property of the JScriptException exception. However you can say

catch(e : MyExceptionType)

in which case the engine will do the unwrapping for you.

Note, however, that the problem can only be solved on the catch side, not on the throw side.

Q I need to get the name of the current user (Windows® NT login) from JScript. How can I do this?

Q I need to get the name of the current user (Windows® NT login) from JScript. How can I do this?

A If the script runs in the browser and the browser is running in safe mode, then it should be impossible to get the user name. (Otherwise any Web page could determine your user name. Imagine the joy of hackers if they could harvest millions of user names by just hosting a popular Web page!)

A If the script runs in the browser and the browser is running in safe mode, then it should be impossible to get the user name. (Otherwise any Web page could determine your user name. Imagine the joy of hackers if they could harvest millions of user names by just hosting a popular Web page!)

If the script runs in the browser and it is running in unsafe mode, then you can use the Windows Script Host (WSH) Network object to fetch the current logged-in user name. See WshNetwork Object for documentation of this feature.

If the script is not running in the browser, your best bet is to try it and see. If you get a security failure, then you're in safe mode.

Q I have an ASP Web site project that fetches data from two primary sources. One is a resource DLL that is used to fetch static strings to put on the Web page. The second is data that I fetch from a SQL Server™ database via an ActiveX® control which uses ADO commands to fetch the SQL Server data. This resulting data is displayed in a standard HTML table.

Q I have an ASP Web site project that fetches data from two primary sources. One is a resource DLL that is used to fetch static strings to put on the Web page. The second is data that I fetch from a SQL Server™ database via an ActiveX® control which uses ADO commands to fetch the SQL Server data. This resulting data is displayed in a standard HTML table.

The problem is that I have a US/English SQL Server database that has collected data from several Japanese machines. When using a Japanese client machine to connect to my Web site, I can view the Japanese text in the HTML table in the proper typeface. However, the Japanese text strings from my resource DLL appear as all question marks. If I change my session code page in global.asa (Session.CodePage = 932), then the Japanese text strings from my resource DLL appear correctly. However, the data fetched from the SQL database in my HTML table is now scrambled. Whenever I fix one problem, I create the other.

A The way to solve this is to move to UTF-8 as the encoding solution. Then, if anything is still broken, determine why the information is not being loaded properly. SQL Server and your script both use Unicode, so if the ActiveX control does not handle it, then you need to move to straight ADO which will not corrupt the data. It's not clear how you are loading from the resource DLL, but the same rules apply there as well.

A The way to solve this is to move to UTF-8 as the encoding solution. Then, if anything is still broken, determine why the information is not being loaded properly. SQL Server and your script both use Unicode, so if the ActiveX control does not handle it, then you need to move to straight ADO which will not corrupt the data. It's not clear how you are loading from the resource DLL, but the same rules apply there as well.

Q Does W3C XML spec allow XML data in the which the value of the VALUE attribute is the empty string? Does the XML spec distinguish nulls from empty strings in attributes?

Q Does W3C XML spec allow XML data in the which the value of the VALUE attribute is the empty string? Does the XML spec distinguish nulls from empty strings in attributes?

A The empty string as an attribute value is perfectly fine. The difference between having an attribute with an empty string value and not having an attribute at all is in the way you get the value. For example, XmlTextReader.GetAttribute will return an empty string if the attribute is there and the value is the empty string, and it will return null if the attribute is missing. The same is true for XmlElement.Attributes.GetNamedItem.

A The empty string as an attribute value is perfectly fine. The difference between having an attribute with an empty string value and not having an attribute at all is in the way you get the value. For example, XmlTextReader.GetAttribute will return an empty string if the attribute is there and the value is the empty string, and it will return null if the attribute is missing. The same is true for XmlElement.Attributes.GetNamedItem.

Q Is there a way to sort an array in VBScript? I just need the sort feature to remove any strings that are duplicated. The size will not exceed more than 1000 records. I thought of converting the array to XML and using the Document Object Model (DOM) Sort feature, but I'm not sure if this will work.

Q Is there a way to sort an array in VBScript? I just need the sort feature to remove any strings that are duplicated. The size will not exceed more than 1000 records. I thought of converting the array to XML and using the Document Object Model (DOM) Sort feature, but I'm not sure if this will work.

A In VBScript there is no built-in array sort function (as there is in JScript), so you'd have to roll your own. If you did, the algorithm you'd use to sort an array would depend on the kind of data in the array and the size. Keep in mind, though, that if the goal is only to find duplicates, then you can do much better than sorting!

A In VBScript there is no built-in array sort function (as there is in JScript), so you'd have to roll your own. If you did, the algorithm you'd use to sort an array would depend on the kind of data in the array and the size. Keep in mind, though, that if the goal is only to find duplicates, then you can do much better than sorting!

For an n item list, sorting the list and then checking each consecutive pair for duplicates is at best a performance hit of O(n log n). Using a dictionary as a hash table is O(n). Furthermore, even if the performance is no better, the algorithm is conceptually much simpler and much shorter.

dim a(5)
 
a(1) = "D"
a(2) = "A"
a(3) = "D"
a(4) = "C"
a(5) = "A"
 
set dictionary = CreateObject("Scripting.Dictionary")
for i = 1 to 5
    if dictionary.Exists(a(i)) Then
        print i & " and " & dictionary(a(i)) & " are duplicates."
    else
      dictionary.Add a(i), i
    end if
next
 

The previous code produces this result:

3 and 1 are duplicates.
5 and 2 are duplicates.

That's an eight-line duplicate finder, and shorter programs have fewer bugs.

Of course, if you need to have a sorted list for some other reason, then you'll have to go ahead and implement a full sort algorithm.

Got a question? Send questions and comments to WebQA@microsoft.com.

Thanks to the following Microsoft developers for their technical expertise: Eric Baudouin, Philip Beber, Scott Cottrille, Alex DeJarnatt, Bruno Denuit, David Hill, Julia Jia, Michael Kaplan, Helena Kupkova, Anton Lapounov, Eric Lippert, Han Pin Loke, Dare Obasanjo, Martin Pichardo, Manu Puri, Vivek Ramamoorthy, Michael Rys, Dmitry Starostin, Selina Tng, Charles Torre, Chung Webster, Sai Wong.