Click to return to the Essentials home page    
Web Workshop  |  Essentials

Something Old, Something New: Visual Basic and XML


Jeff Brown
Rafael M. Muñoz
Microsoft Corporation

September 8, 1998
Updated: December 15, 1998

The following article was originally published in the Site Builder Magazine (now known as MSDN Online Voices) "Web Men Talking" column.

Contents
XML marks the spot - Transporting data using XML
ER - Using CDO to create and send mail
Remember me? - Retaining user logon information
B-4 ... Miss - Dynamically included external script files and scriptlets

Heads up! With this month's column, Jeff and Rafael introduce a brand new feature, a monthly hot-button issue, brought to you by some of their developer friends. This time, Shawn Vita looks at those pesky access-denied messages you might get when recompiling components. After all, nobody likes to feel left out.

The Web Men are as excited about XML as anyone else on the virtual block, and this month they ponder how that new technology fits with an old friend, Microsoft Visual Basic®.

Other topics on the plate include CDO (read on to find out what it is), scriptlets, and cookies -- always an inspiring topic. So grab a handful of gingersnaps to go with your cup of joe, and get answers to your September questions.

XML marks the spot

Dear Web Men:

I am trying to find out any information about using Visual Basic to work with XML documents. Specifically, I am trying to do the following: I have a server COM component written in Visual Basic that generates XML based on the data it pulls out of a database. I have a client, a Visual Basic application, that calls that method of server component to retrieve data structure formatted in XML.

I am having a hard time figuring out how to pass the XML generated on server to client. Unfortunately, after looking through hundreds, literally, Web sites that discuss XML/XML programming, I came to the conclusion that such programming techniques have never been discussed yet. Your last article does not cover the information I need to do what I've described above.

I would greatly appreciate if you e-mailed me any information or reference to some site that would give me some clues.

Thank you,

Ken Borinsky

The Web Men reply:

XML is fast becoming the talk of the town, and definitely doesn't appear to be a passing fad. (We thought Beanie Babies were just a fad, but it doesn't look as though the world's obsession with them will be letting up anytime soon, either.) For those who haven't been talking the XML talk, we'll provide a little background first. And don't forget to check out MSDN Online Voices's regular column on the subject -- Extreme XML.

The XML 1.0 specification got its stamp of approval from the World Wide Web Consortium (W3C)Non-MS link earlier this year. And Extensible Stylesheet Language (XSL)Non-MS link, a mechanism to attach presentation information to XML data, was recently accepted as a Working Draft by the W3C. So it has started on its way to becoming a standard on the Web, too.

Microsoft has provided strong support for XML in Internet Explorer 4.0, and is adding a ton of new XML features in Internet Explorer 5. Several authoring-tools vendors are creating new XML authoring systems, or adapting their existing SGML tools to fully support XML. Free prototyping tools, such as Microsoft XML Notepad and the Arbor Text XML Styler Non-MS link, are also available.

Now, let's get to Ken's specific question. You can call methods of your server component through Distributed Component Object Model DCOM), just as you would call any other remote method. To pass XML from the server to the client is no different than passing any other textual data, because that's what XML is -- text.

But you're right in that there doesn't seem to be a lot of discussion of what you are trying to do. What there has been a lot of discussion of is creating XML documents by using Active Server Pages (ASP) technology on the server, and then parsing and presenting the XML in the browser using client script, HTML, and Dynamic HTML (DHTML). That is what the XML Auction Demo on the Microsoft XML site does.

If you want your Visual Basic client to parse the XML, then you can create an instance of the XML parser, also known as the XML document object. Rather than calling the methods of your server component directly, you can call them from an ASP file. The ASP file outputs an XML file, and you pass the URL in the load method of the XML document object to read and parse the XML file from the client application.

For an example of a Visual Basic application using the Internet Explorer 5 XML document object, see the Extreme XML column How Much Is That in Balboas? Accessing the Typed Value of XML Elements via Visual Basic. For more information about XML, and pointers to other XML resources, see the XML area in the Web Workshop.

TopBack to top

ER

Dear Web Men:

We are developing a site for a medical institution. I have a form where a doctor can describe the problem his patient has. Then let's say some one else is treating the same problem. They could attach images of examinations, X-rays and etc. The problem is the following one: The form works fine until the phase of attaching the pictures and later transforming everything into an e-mail to send to their peers.

We have to make this work through the use of one form using ASP/HTML. We use Windows NT® 4.0 Server, IIS 4.0, and ASP. This procedure must work fine in Internet Explorer as well as in Netscape. Do you have any suggestions? Please, this site is very important. It will help a lot of people to improve their life quality. Of course, you can't send the code, but please, give us some tips! Okay?

Marcelo Fernandes Costa

The Web Men reply:

Stat -- we recommend 4 cc of baby aspirin, and where are those GIFs, er, X-rays we ordered an hour ago. Wow, just think how we would fit in the medical world -- but maybe we should stick to Web doctoring. That said, we recommend the use of Collaboration Data Objects for NT Server, or CDO for NTS.

Marcelo, you look to have everything you need to do just what you are asking for: Windows NT 4.0 ServerNon-MSDN Online link with Internet Information Server (IIS) 4.0Non-MSDN Online link. IIS 4.0 includes the simple mail transfer protocol (SMTP) server component, and that provides us with the CDO for NTS library, which exposes messaging objects that can be used with such languages and programming systems as Microsoft Visual Basic, C/C++, Microsoft Visual C++® and Visual Basic Scripting Edition (VBScript). If we can access the objects through VBScript, we have access through Active Server Pages (ASP), which completes our tool list for this surgery.

Composing the mail is easy; the sticky part for some could be ensuring that your SMTP services are working correctly. The SMTP services are part of the Windows NT Option Pack and are available only for Windows NT Server. The services come with great documentation. Should you run into trouble getting things set up, check out the section called Troubleshooting Microsoft SMTP Services.

Once you have the SMTP services working correctly the rest is a snap -- and Marcelo, we are going to provide you with enough code snippets here that you should be on your way in no time. When creating a mail using the CDO object, picture a basic mail message and its components -- To, From, Subject, Body, and Attachments. These are the basic components to provide when you configure your NewMail Non-MSDN Online link object.

You mentioned having a form already set up for your doctors. To provide an attachment to your message, use the <INPUT type=file> tag, which allows the user to specify the location of the attachments. This tag also provides a browse button that will allow users to browse the file system for the attachments. The HTML will look something like this:

<INPUT id=mailattachment name=mailattachment type=file>

When this is posted to your ASP file, you will want to grab all your fields and set them to the corresponding property of the NewMail object. The VBScript will look something like this:

Set objMyMail = CreateObject("CDONTS.NewMail")

objMyMail.To = Request.Form("mailto")
objMyMail.From = Request.Form("mailfrom"
objMyMail.Subject = Request.Form("mailsubject")
objMyMail.Body = Request.Form("mailbody")
objMyMail.AttachFile(Request.Form("mailattachment"))

objMyMail.Send

Set objMyMail = Nothing

We create the mail object using the CreateObject() function, and send it using the Send Non-MSDN Online link method. Then to clean up, we set the object to Nothing to remove it from memory. You can see we have all the basics covered -- ToNon-MSDN Online link, FromNon-MSDN Online link, SubjectNon-MSDN Online link, BodyNon-MSDN Online link, and AttachFile Non-MSDN Online link. The first four fields are properties of the NewMail object, while AttachFile is a method. You also have other properties, such as BccNon-MSDN Online link, CcNon-MSDN Online link, and ImportanceNon-MSDN Online link. Two of our favorites are the BodyFormatNon-MSDN Online link property and the AttachURLNon-MSDN Online link method, which allow you to include HTML in the body and include an attachment that is associated with a URL.

Two great places for complete information and sample code on CDO for NTS are Collaboration Data Objects for NTS Component Non-MSDN Online link and Overview of CDO, the latter is found on MSDN Online.

Oh, Marcelo, did we mention that, as requested, this will work with Internet Explorer 4.0 Non-MSDN Online link and Netscape Navigator, because all the work is being done on the server side? If none of this works, take two aspirin and call us in the morning.

TopBack to top

Remember me?

Dear Web Men:

I frequently need to program Web pages that require a logon. Usually, the logon is authenticated by a mainframe computer, so NT username/password schemes can not be used.

Before the user has logged on, the only pages she can access are the logon pages. After logging on, it would be good if she did not have to return to the logon page. Usually, the Web design involves frames: There is a navigation bar somewhere and some applet sitting behind it all providing some basic functionality.

All this is possible using .asp, etc., but the real problems start when the user hits Refresh or Back buttons. Since I believe I am not the only one experiencing problems handling Back and/or Refresh buttons, I turn to you to ask if you could provide some good examples how this problem should be tackled.

Erkki Riekkola

The Web Men reply:

Yeah, this brings to mind times when you think you recognize someone, and are in mid-smile or mid-greeting only to encounter a sort of "I have absolutely no clue who you are" look on her face. Okay, maybe it's just us.

Erkki, what you ask can be done through smart use of browser cookies. Once the user has been authenticated by the mainframe computer, you can set a cookie on her computer to identify that she have been authenticated.

You can put all your pages that require authentication in a particular virtual directory on the server, and set the path value in the cookie to be that directory. That way, the user's browser will send the cookie to the server whenever a page in that directory is requested.

Then on each page that requires authentication, include some server script that checks to see if a valid cookie has been sent. If the cookie has not been sent, then the script redirects the user to the logon page. The script will look like the following:

<% ' COOKIE_CHECK.ASP

' Check for a cookie whose value is set to
' "authenticated".
' If the cookie does not exist, redirect the user to
' the logon page.

If Request.Cookies("authenticated") = "" Then
Response.Redirect("logon.asp")
End If
%>

And could simply be included in other pages, like the following:

<% ' SAMPLE_PAGE.ASP %>

<!--#include virtual="COOKIE_CHECK.ASP"-->

<% ' additional script ... %>

You will probably want to set an expiration date for the cookie to be a matter of hours or one day, so that the user is not able to browse the pages for an unlimited amount of time without having to be re-authenticated.

Hopefully, the username and password are just being used for initial authentication and for overall access to the site. But if they are needed to gain access to other resources while the user is browsing the pages on the site, then you probably will want to store and retrieve them from the cookie, too. However, you will want to think carefully about how to store them in the cookie without compromising their security.

If you're not familiar with programming with cookies, you can check out our archived answer Bake a batch. In addition to explaining the basics of cookies, it includes a sample of sending and retrieving cookies using ASP.

TopBack to top

B-4 ... Miss

Dear Web Men:

I am trying to create an HTML page where user input (like an edit control with the user's name) would decide what JavaScript script to load. For example if the user is jeffbrown, the page will load jeffbrown.js, and if it's RafaelMunoz, it will load RafaelMunoz.js.

In both files will be the same JavaScript function, which, for example, returns a string that I insert into a paragraph using DHTML.

My solution was to use body.insertAdjacentHTML("<SCRIPT SRC=\"" + nameField.value + "\" ....., but insertAdjacentHTML ignores the <script> tag.

My next solution was to use insertAdjacentHTML to load an <OBJECT>, where that object is a scriptlet. Same results. Testing proved to me that insertAdjacentHTML put the object in the proper place, but that it wasn't instantiated. See code below (the code does not work!).

So, how do I dynamically load JScript™ source and use it?

Code I used:

<HTML>
<SCRIPT>
function showMessage ()
{
var obj = "<OBJECT ID=\"Scriptlet1\"
TYPE=\"text/x-scriptlet\"
DATA=\"gil.htm\" width=100 height=100></OBJECT>";

document.body.insertAdjacentHTML("BeforeEnd", obj);

messageText.innerText = Scriptlet1.theMessage;
}
</SCRIPT>
<BODY>
<P>
<BUTTON onclick="showMessage()">Get Message</BUTTON>
<P>
<P ID="messageText"><P>
</BODY>
</HTML>

Where the scriptlet GIL.HTM is:

<SCRIPT>
function public_get_theMessage()
{
return "Hi, I'm Gil!";
}
</SCRIPT>

Gil Tayar

The Web Men reply:

Gil, remember the old game Battleship? Well, you are just one hole away from sinking your opponent's battleship. Both of your ideas will work; you just need to make a few changes, and you'll have that battleship sunk in no time.

First, let's set up some rules for ourselves and then use them while we discuss your problem.

  1. You must be using JavaScript, because VBScript events are bound when the page is first parsed.
  2. You must cause the HTML page to be re-parsed.
  3. You must use the <SCRIPT DEFER> tag.

With these steps in mind, let's take a look at using a scriptlet first, since you so graciously provided us with the code you were trying. Nice work on creating a simple, stripped-down example; it definitely made things much easier to look at! At first glance, we can see that we are using JavaScript, so Step 1 has been taken care of.

The scriptlet checks out fine, so we know the problem isn't there. Looking at the basic HTML, we can see that everything checks out fine there -- leaving us with the problem child, the script function.

One might say, "But Gil's script looks just fine," and it does. So why doesn't our scriplet work? Because we are jumping the gun just slightly with our call to our theMessage() function. Can't drive the car before you turn it on, right? The same situation applies to your scriptlet. You can't call any functions within your scriptlet until the object is completely loaded.

How do we know when an object is completely loaded? When not working dynamically, we just create an event handler for onreadystatechange that looks like such:

<Script language=javascript for=Scriptlet1
event=onreadystatechange>
messageText.innerText = Scriptlet1.theMessage;
</Script>

But adding this before we have the object loaded will cause the parser to ignore the handler, and it will never get fired. We could try adding it after the object is loaded, but then we are adding a script that is looking for an event after the event has fired. Sort of a catch 22, we'd say. Our next option is to watch for another event to occur, and we chose to watch for the mouse events onmousedown and onmouseup. We also took the liberty of changing your <BUTTON> tag a wee bit to read as such:

<BUTTON onmousedown="insertScriptlet()"
onmouseup="displayWelcome()"
type=button id="button1" name=" button1">
Get Message</BUTTON>

Then we replaced your script with:

<SCRIPT>
function insertScriptlet ()
{
var obj = "<OBJECT NAME=\"Scriptlet1\"
ID=\"Scriptlet1\"
TYPE=\"text/x-scriptlet\" DATA=\"gil.htm\"
width=100 height=100></OBJECT>";
document.body.insertAdjacentHTML("beforeEnd",obj);
}

function displayWelcome()
{
messageText.innerText = Scriptlet1.theMessage;
}
</SCRIPT>

As you can see, we are providing a chance for the scriptlet to successfully load during the onmousedown event. We then make a call to the scriptlet function theMessage() in the onmouseup event to provide our welcoming message.

Now, let's take a quick look at your external script situation. Here we don't have to wait for an object to load, but we do need to ensure that the script will be executed and that the page is re-parsed. To do this, we will need the use of the DEFER attribute, Rule 3, to ensure the parser that we don't have any inline script in our script block and that our script needs to be parsed. We also need to have the page re-parsed, and for that we use a little DHTML trick, Rule 2.

Our final code would look like such:

function insertScript()
{
var obj = "<SPAN style='display:none'></SPAN>
<SCRIPT DEFER SRC=\"gil.js\" >
<\/script>"
document.body.insertAdjacentHTML("beforeEnd",obj);
messageText.innerText = theMessage();
}

You can see that we are using the DEFER attribute within our <SCRIPT> tag; before that, you'll notice <SPAN style='display:none'></SPAN>. This is our DHTML trick. Basically, this code creates a <SPAN> tag that is not seen by setting the style to &ldquo;display:none&rdquo;, which causes the parser to re-parse the page to hide an empty SPAN.

There you have it -- a way to dynamically insert a scriptlet or refer to an external script on your Web page. For two other great references on this topic, see the Microsoft Knowledge Base articles Q185140: PRB: Trouble Inserting Non-Displayable HTML into Web PageNon-MSDN Online link and Q185128: HOWTO: Insert Event Handler Into Web Page from WebBrowser AppNon-MSDN Online link.

TopBack to top

 


This Month's Hot-Button Issue

Each month, the Web Men ask Microsoft Developer Support to pick the most burning issue they're hearing from Web developers. This month, Shawn Vita looks at errors received when recompiling components:

Have you ever written a component in Visual Basic or Visual C++, tested it, made modifications to it, and then recompiled it -- only to receive an access-denied or permission-denied error? Everyone who has developed a component for use in pages created with Active Server Pages technology has encountered this error message at one time or another. I will describe why this error occurs, and some common tricks to use to avoid the error.

Why is the error occurring? The default setting for Internet Information Server (IIS) 4.0 is to run all Web applications in the same memory space. This means any components (typically DLLs) that are instantiated in a Web page will be loaded into the same memory space and will process as IIS 4.0. The process is called INETINFO.EXE, and you can see how much memory it is using by opening the task manager, and looking for it in the list of running processes.

Once a request for your component has been made, it is loaded into the INETINFO process. When you recompile the component, the compiler attempts to overwrite the old DLL and register it, if it is not already registered. Since the component is loaded in the INETINFO process, INETINFO has to release it before the old component can be recompiled. One common way to do this is to stop the Web server, and then restart it once the component has been recompiled. The most common way I've seen this done is using a command/batch file. Sample 1 represents the code inside a batch script that properly stops the World Wide Web Publishing Service and all of its dependencies.

Sample 1: Sample batch file script to stop the Web server

NET STOP IISADMIN / Y

Notice that I did not use the Microsoft Management Console (MMC) to stop and restart the default Web site. To get INETINFO to release the component, the IISADMIN service and all of its dependencies must be stopped (WWW publishing service, FTP, and MCIS servers). Once you've stopped the IISADMIN service, you should be able to recompile the component. After you've recompiled the component, you will need to restart the Web server. Sample 2 contains the batch file script that will restart the World Wide Web publishing service.

Sample 2: Sample batch file script to start the World Wide Web Publishing Service

NET START W3SVC

Most of the component developers I've seen in action put the batch file scripts on their desktop, so that one click does the trick. The stopping and starting of the Web server can also be accomplished using the Services applet in the Control Panel.

The recommended IIS configuration for component development projects is to enable the run in a separate memory space option by clicking the checkbox option on the directory properties from within MMC. Once the component is loaded into memory, and you want to recompile it, click the unload button. This methodology is especially useful for situations where you do not have control over the Web server, and you cannot stop and start the Web server at will.

How you stop and start the service, and which IIS configuration method you use, is relative to your particular situation. What is important is making it as easy as possible to recompile server-side components.

Back to topBack to top

Jeff Brown, when not forcing family and friends to listen to Zydeco and country blues music, helps develop training courses in the Microsoft Mastering Series -- with a smile.

Rafael M. Muñoz is a part-time Adonis, and full-time support engineer for Microsoft Technical Support. He takes it very, very personally every time you flame Microsoft.

Shawn Vita has worked at Microsoft for 1 1/2 years as a tester, test lead, and now in developer support for Internet technologies, and he has a bachelor's degree in Computer Programming Technology from Purdue University.


The Web Men in Short

September 8, 1998

Q: Patrick Leroux wants to build database-driven Web sites using Active Server Pages (ASP) technology and SQL Server.

A: Check out the Server Technologies area in the Web Workshop, and Mastering Web Application Development Using Visual InterDev 6.0Non-MSDN Online link.

Q: Brian wants to know how those cool pop-up menus are done on the MSDN Online navigation bar.

A: Refer to A Tour of the Code -- Navbar: Dynamic Menu Generation.

Q: Bill Wolf asks how to do online searches of an Access 97 database on an intranet.

A: Search for "Publish to the Web Wizard" in the online help, and see Use Microsoft Access 97 to Access Live Data on the WebNon-MSDN Online link.

Q: Wendy Melander wants to create a chat room at her new Web site.

A: Refer to the archived Web Men article Hello, is anybody out there?.

Q: Starman asks what TARGET=SISTER means.

A: SISTER is an arbitrary name for a new browser window. If a browser window with that name is not already visible, then a new one with the name will be created, and the HTML page being loaded will be displayed in it.

Q: Justin wants information registering ActiveX controls.

A: Refer to the Component Development section of the MSDN Online Workshop.

Q: Mark thinks that Remote Data Service (RDS) and XML are competing technologies, and wonders what the story is.

A: Both technologies can be used to transport database records between server and client. RDSNon-MSDN Online link is a complete solution today, while XML is not. RDS provides all infrastructure required to transport, access, and update records in ODBC data sources on the server from the client. As XML matures, similar infrastructure is being developed to support database record transport across a network.

Q: Mike Garoutte, a new Web developer, is interested in learning how to perform MouseOver effects.

A: Refer to the Rollover Effects sample in the Samples section of the MSDN Online Downloads area.

The Web Men's Greatest Hits

List of Web Men Topics

Write us!



Back to topBack to top

Did you find this article useful? Gripes? Compliments? Suggestions for other articles? Write us!

© 1999 Microsoft Corporation. All rights reserved. Terms of use.