asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search










Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Advanced Web-Enabled Applications and Services Architecture Using XML and XSL - Part 2
By Lee McGraw
Rating: 4.0 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Brief Review

    In review, Part 1 of this article introduced some of the typical issues and problems in corporate IT departments (see http://www.15seconds.com/issue/010806.htm). Here we are going to address those issues in an attempt to minimize their negative impact on IT projects. Topics to be covered include the following:

    1. adding and modifying existing methods and data structures (and the validation of these methods and structures) to our production services and applications without rewriting them and without having to bring our production servers down;
    2. designing an architecture that will allow us to scale out, as well as up;
    3. adoption of a new mindset, a new outlook on our IT projects, an outlook that expects changes and new requirements throughout a product life cycle.

    However, in Part 1, I told you that the eXtensible Stylesheet Language (XSL)/ XSL Transformations (XSLT) that I was going to show you was limited to the Microsoft Parser, more specifically WD-XSL. I have revised this code to not be Microsoft-specific, at the request of various readers.

    The Extended Goal

    Besides the three issues listed above, we want our application architecture to work with any client. I don't care if it's a browser, like Microsoft's Internet Explorer, a Visual Basic application, or another application server requesting access and resources to our service, it should work for everyone. Perhaps a picture does convey a thousand words, so here is one. Figure 1 is a simplified pictorial representation of what we want to accomplish. As you can see, we have several different types of accesses occurring: Web browsers from the secured and/or unsecured Internet; remote employees from a secured zone; and application servers from both secured and unsecured zones. Also, note that not everyone using our application/service has the same entry points -- company A's application server is accessing our application server directly, whereas company A's remote employee might access it either way. This is dependent upon the requestor's needs, as well as our security limitations and implementations. I am not going to discuss security in detail here, so I leave it to you to implement and define what you call unsecured and secured. But, please be aware that I am making this distinction. It should be obvious that this extended goal is achieved here, since HTTP request and XML, which is raw text, is platform-independent.

    In this article, my largest concern and topic will be the connector between the data warehouse and the in-house application servers. This connector component will be the heart of our application and I will call it Data2XML. In essence, it will abstract away the details for data access, be that data stored in a RDBMS, a Microsoft Exchange information store, or a file system eXtensible Markup Language (XML) document. For the purposes of our example, I shall only exploit a connection to the database. If you understand this article, modifying this code to access the Exchange information store or file system XML documents should be easy.


    Figure 1: Architecture that scales out.

    Note: Because we are using HTTP requests for all our services and data, we can easily add a long balancer and more servers anywhere in between connections and increase our capacity for servicing requests. This is what I mean by scaling out. No matter how good your code is, it can only handle so many requests on one server. No matter how much RAM or how many CPUs you add to that one server, soon or later it's going to peak out. However, with our architecture, we can always add more servers, hence never reaching a bottleneck, at least on this service's tier. And, let's be honest, hardware is much cheaper than developer time, and a much more readily available resource too. So, the architecture alone provides us with a solution to typical corporate problem (2) that we detailed in our review section. Many developers know and understand this architecture; all architects should. Unfortunately, with the time constraints given to us by managers, you don't see it implemented as often as you would like. In any case, it's easy to understand how a good architecture can save your corporate applications from future rewrites.

    Abstracting Away Data Access Details with Data2XML

     

    Overview

    This Data2XML component allows us to add and modify data methods and structures without recompiling our component. Further, once implemented, we will no longer need to access our data warehouse directly; we will, instead, be making a request to this component to give us access to these types of resources. Indeed, we won't even care or know, unless we build this into our component, if the data we are looking at comes from a database server or other storage media.

    I shall create a fake entity called "Users" for this component that will suffice to show you how to extend this architecture to incorporate you own real-world entities. In the source code, you will find many more entities and methods. For a full understanding of this project, please peruse the code. Unfortunately, I cannot walk you through how they all work, not without writing a book, but I shall explain the concept thoroughly, in the hope that you can understand the other entities via the code. In actuality, all the entities are just different objects and the methods different operations, so if you understand the difference between a data read and a data write, you should have no problem understanding the source code.

    Requirements of Data2XML

    1. Receive requests.
    2. Validate request.
      a) Identify valid vs. invalid request; report error to calling application when an invalid request is placed.
      b) Reformat request for underlining data store processing.
    3. Process request. a) Connect to the actual data store; report error if one occurs.
      b) Call appropriate method on data store to retrieve information; report error if one occurs.
      c) Reformat output to the calling application/server.

    Source Code Download and Contents

    The first thing you absolutely need to do is download the accompanying source code. There are some absolutely necessary classes and modules that contain functions that you will need, and I can't list them all here. Here is a brief description of those that I shall not cover in depth, just so you understand what is going on. This is not a complete listing. The names of these classes, functions, and variables are purely arbitrary. These classes and functions are only the ones that I shall not cover in depth, as I said above.

    1. Classes
        a) CDSN
          This class allows you to create your data source name connection string. You can look at the source code and it's pretty straightforward. It looks for an XML file that contains connection string information. If it finds the connection string information in that file, it creates the full connection string for you. Otherwise you simply set properties, like DBServer and DBUsername, and CDSN creates your database connection string for you. I got tried of doing this manually, so I created this myself some time ago.
        b) CADO
          This class contains ActiveX Data Object (ADO)-specific method calls. The methods are GetADOType and GetADODirection. I shall explain these when I address CRequest.ProcessCMD later in this article. They are pretty simple, but if you look at them right now, you'll probably want to know why they are used.   c) Cgeneral
          This class is marked PublicNotCreatable. I have all public enumerations in this class, such as application-specific error codes.
    2. Modules
        a) General
      • This module contains all global variables and functions. Most notably, it contains variable declarations for DBCon, RequestItem, and RequestAction. Also, you will find some important global constants that define file names and paths. Feel free to change these for your needs. It also contains my start-up subprocedure, Sub Main. This module also contains any global functions that I call, such as the following:
      • Function FormatParameters - responsible for validating our incoming request for preparation to pass to a stored procedure
      • Function FormatOutput - just like it sounds, responsible for formatting our XML output that is returned to the caller
      • Function FormatError - just like it sounds, responsible for formatting our XML error output
      • Function InsertDataHeader - responsible for inserting our data header for the ensuing FormatOutput call
    3. Other contents and concerns
        Also, I have a MS SQL Server 2000 database named SiteManager, but you can create and name one that fits your needs. You will need a DB username and password. I tend not to use integrated security on servers because it requires them to be logged in and causes other database connection pooling issues to arise, so I use SQL usernames and passwords.

        Just examine the DBConnections.xml file that creates the connection string and tweak it to your needs. Also, with the source code, you will find an SQL file (a file with the extension .sql) that contains the scripts to create the tables and stored procedures I use here. If you don't know what this does, copy the contents of it into the SQL Query Analyzer and run it on the database that you want the tables and stored procedures to appear in after completion. Note you might have to refresh your view after running it in order to see them. Finally, you might need to change the global constants in the Visual Basic (VB) General module. Just check them at the top of the file and verify they exist, and make sure you put the files in their proper location. There are comments in the source code to help you. Also, you'll find a TestEXE project that is a test container for this component.

    Component Modularization, Naming Convention, and Logic

    Before we can start walking through our code, we have to establish some standards for how our XML Request will be made. Further, if we are to be able to add and modify these requests, we have to establish how this will be accomplished without recompiling (that's our goal). In essence, since we will be using XML to make requests, XSLT to validate those requests, SQL Stored Procedures to process those requests, then XSLT again to format the output of those procedures, we have to make a map that connects XML request input with our XSLT output. First, I want to qualify some terms that I shall use. They are only generic names, and "Entity," for example, has nothing to do with XML Entities.

    1. Names
        a) Entity Group - An entity group is a way of addresses and identifying groups of entities I will "act on." For instance, "Users" will be an entity group.
        b) Entity - An entity is an identifier for an object. For instance, "User" is an entity in the Users entity group.
        c) Entity Group Action -- This is the verb context of the entity group. For example, when I "act on" an entity group, I will be doing the entity group action on every entity in the entity group. This lends us another concept; however, in this implementation it remains only a concept.
      d) Entity Action - This is the "act on" verb for each entity. In this implementation, the entity action is specified by the entity group, but you could imagine an implementation that allowed the calling program to specify a different entity action for each entity. I shall leave this up to you to implement in your version of this component. It requires extensive XSLT rework, which is beyond the scope of this article.
        e) Parameters - Despite our obvious use of them in VB method calls and SQL Stored Procedures, I shall use these in the form of XML Elements in our XML Request. These XML Elements have a very close relation, as you will see, with SQL Stored Procedures during the XML Request validation.
    2. Relationships/Mappings
        a) Entity Group : Prefix of XSL Validation file : Prefix of SQL Stored Procedure name : Prefix of XSL Output formatting file.
        b) Entity Group Action : Postscript of XSL Validation file : Postscript of SQL Stored Procedure name.
    By applying these names, you could deduce that this XML request (I am indenting for the reader's sake) ...
    
    <users action="get">
    	<username>lee</username>
    	<password>leespassword</password>
    </users>
    
    
    ... would be validated by a file called UsersGet.xsl, then call a SQL Stored Procedure called sp_UsersGet (using the parameters specified - i.e., username and password), then formatted for output based upon the content in UsersOutput.xsl (users=Entity Group; get=Entity Group Action; username and password are parameters).

      OR ...

    
    <users action="delete">
    	<id>1</id>
    	<username>lee</username>
    </users>
    
    
    ... would be validated by a file called UsersDelete.xsl, then call a SQL Stored Procedure called sp_UsersDelete (using the parameters id and username), then formatted for output based upon the content in UsersOutput.xsl (users=Entity Group; delete= Entity Group Action; id and username are parameters).

      OR ...

    
    <users action="save">
    	<user>
    		<username>MyUsername</username>
    		<password>MyPassword</password>
    		<firstname>MyFirstName</firstname>
    	</user>
    	<user>
    		<username>MyUsername2</username>
    		<password>MyPassword2</password>
    		<firstname>William</firstname>
    		<lastname>Turri</lastname>
    		<preferredname>Willie T.</preferredname>
    	</user>
    </users>
    
    
    ... would be validated by a file called UsersSave.xsl, then call a SQL Stored Procedure called sp_UsersSave (using the parameters specified), then formatted for output based upon the content in UsersOutput.xsl (users=Entity Group; save= Entity Group Action; everything between the user markup, which is an Entity, is parameters). You can see that this last example is different because we are specifying the Entity "user" here. This is assumed and supplied for you with just one Entity, but you can perform the same action on many Entities just by specifying it manually. Further, the parameters are different for each Entity; this is perfectly acceptable here; all of these details are handled by our validating XSL file.

    Therefore...
    XSL Validating filename = Entity Group & Entity Group Action & ".xsl"
    SQL Stored Procedure Name = "sp_" & Entity Group & Entity Group Action
    XSL Output Formatting filename = Entity Group & "Output.xsl"

    Finally, we have our project and component logic.

    Thanks to everyone who has stayed with me since Part 1. I know it has been a long time, but I want to make sure I express this well enough so that you can call and modify it with confidence. Also, please email me with any good ideas you have because I am going to be relying heavily on this component in the near .NET future. After all, .NET recommends that you create a base component for all data accesses.

    Now, I am going to start walking through the code.

    Data2XML Source Code Walk-Through

    I. Start-up and simple validation

    1. Someone needs some data, so a request is made to our component.
    2. The first thing it does is call Sub Main in the General.bas module. All it does is set my computer name. This is for the sake of tracking DB 1205 errors, i.e., the famed deadlock error. For the same reason, I am always sure to include application names in my connection string.
    3. What happens next is not obvious at first glance, but only one thing really can happen. That's a call to the CMain.XMLRequest method, which is really the only accessible Public method call in our project. All other modules are either marked as private, only contain enumerations (which do nothing), and CRequest.Process is a Friend method call and is not visible outside of this project. The calling application calls CMain.XMLRequest and passes to it a string; this string is the XML Request. (Understand the naming convention?) The XML Request string we will be passing is taken from our first example ...
      	
      	<users action="get">
      	<username>TheUsername</username>
      	<password>ThePassword</password>
      	</users>
      	XML Listing 1: The Request.
      
      
    4. Next, the method goes through a series of validation steps.   a) The first step validates that you have passed a valid XML string.
        b) The second step is an Acknowledge function that would, if it weren't mostly rem'd out, check that a certain processor instruction was also passed that was equal to this VB project's Product Name property. This gives you a very simple security check.
        c) The third call validates the Entity Group and Entity Group Action, then populates the respective global variables so in this case ...     RequestItem="USERS"
          RequestAction="GET"
        d) The fourth validation (ValidateXML) is where XSL begins to play a role in our validation, but I am going to skip it for just a second.   If the fourth validation is successful, then the ValidateDB method is invoked. This method creates the database connection string using the CDSN class. The CDSN class relies upon the presence of the XML processing instruction for "productname", but I have added a default connection if this instruction is missing. The CDSN.UpdateDBCon method takes as a parameter the location of the XML file (specified in the General.bas constants section) that contains this information. If all is good with all of this validation, then the flow shifts to the Request method of the CRequest class. (Now I return to the fourth validation step, ValidateXML. While the best method of approaching XSLT might be to explain all of it later on, I am trying to walk you through the actual processing occurring in this component, so I am about to shift gears into XSLT right now. Just remember, after all the validation steps have occurred, then next VB process that occurs within this component is CRequest.Request.)

    II. XSL validation and transformation of XML Request

    1. The XSL file that we will validate and transform with is defined by our Entity Group and Entity Group Action. Recall this file is named ... Entity Group & Entity Group Action & ".xsl" and is located where the constant BASEFILELOCATION specifies. In this case it is equal to http://www.unrealcity.com/xsl/usersget.xsl No, not necessarily; the http value is exactly what is evaluated by a logical operation in the component, so I listed it on a line of its own for clarity.

      (Open this file in Notepad or an editor of your choice and take a brief look at it. If everything goes well, the transformed XML will look like XML listing 2.)

      
      <?xml version="1.0" encoding="UTF-16"?>
      <users>
      <user>
      <username type="adVarChar" direction="adParamInput" size="50">TheUsername</username>
      <password type="adVarChar" direction="adParamInput" size="50">ThePassword</password>
      </user>
      </users>
      
      XML Listing 2: Successfully validated and transformed XML request that is ready to be processed.
      
      
    2. XSL Validation
        a) The call is made by the FormatParameters method in the General.bas module.
        b) The first thing you will notice about our XSL file is that it is XSL version 1.1.
        c) Notice I have created a separate file named CommonAttributeSets.xsl for common attribute sets that I import. This file contains all the database-specific attributes, as well as data type attributes.
        d) Of course, I have several templates defined to process various XML elements. The first one, with match="/", matches the document's root element of the XML file.
        e) Finally, you will see I have a <xsl:choose> markup. For those of you used to the If-Then-Else construct available in various languages, you will understand this easily. What it amounts to is this: each <xsl:when> is processed until it finds one where the test evaluates to true, then it processes the contents of that "when." If all "whens" are false, and an "otherwise" appears, then it processes the "otherwise." Only the first when that evaluates to true is processed, and there is no limit on the number of "whens." The "otherwise" is optional.
          i. The first "when" verifies that we have a combination of username and id (which has to be numeric) or password (which can be blank). This is my required logic for the "get" action. This means that you can retrieve a user by an id and username, or a username and password. I am assuming that if you have the user's id, then you have already retrieved that information by making the same action request with username and password, but someone could just guess it.
          ii. If the first "when" doesn't evaluate to true, then processing drops into the "otherwise" clause. Here, you see why I am validating my request with XSL versus schemas. Schemas are built for this purpose, but have no built-in mechanism for returning "developer-friendly" error messages. A friend named Brian has directed me to MSXML 4 but version 4 is not even beta yet so I have chosen not to use it in a production environment. Nevertheless, it's a good thing to know about for the future. In this "otherwise" clause, I run several "if" clauses to generate XML markup for each type of violation of the rules that I defined in the first "when" clause.
        f) If the rules of the request are valid, then processing occurs on the rest of the templates. These are pretty obvious, except that I have defined one with a match="users|user". This means that this template is matched for both users and user elements. In this way, the calling application could leave out the user Entity markup. Also, in all the templates that are representative of a data entity, I have created an attribute for the data type, the parameter's direction (input or output), and the size, if it's a character parameter.
        g) Ultimately, we get transformed XML in the form of a string ready to be processed by the database or an error with messages.
    (You can image how much hard coding you have just avoided. Also, people might argue that I should just look up the database's parameter types and lengths via the ADO Parameters collection, but that causes a lot of network roundtrips to the database, and I don't want that.)

    III. Processing the validated XML (back in VB now)

    1. The flow now has gone from CMain.XMLRequest to CRequest.Request.
    2. CRequest.Request doesn't do very much really. It more or less just passes the control over the CRequest.Process. I could have gotten rid of one of these method calls, but didn't so that I could have the maximum flexibility when I do add some real security mechanisms. CRequest.Request simply loads the returned string of the Process method call into an XML document object.
    3. CRequest.Process does do some substantial work. It creates a database connection and calls CRequest.ProcessCMD for each child node in the document element. The child nodes will be the same as user Entity elements, while the document element is the users' Entity Group. It concatenates the result of all these ProcessCMD calls into a string, then appends the Entity Group back onto the concatenated string via the InsertDataHeader function.
    4. CRequest.ProcessCMD is the real workhorse here. As the name implies, it processes each ADO command, of which there will be one for each Entity within the Entity Group. ProcessCMD is unaware of how many Entities were specified by the request. In fact, it only receives one Entity as its parameter. Of course, in the case of this "get" action, only one will be there, but recall from our examples that we can save several Entities within one request. Really, there are several operations in which you can specify several Entity elements, depending on how you define your XSL files and stored procedures.
        a) The first thing this method does is create an ADO Command and Stream object. The Command object will execute our stored procedure and the Stream object will contain the returned results. You can see where we specify that the stored procedure is to be "sp_" & RequestItem & RequestAction. Further down, you see where we set the "Output Stream" property to our Stream object. Then we come to the first For-Each loop.
        b) The first For-Each loop is where we process our stored procedures parameters. For each child node of our Entity "user"-i.e., username, password - it sets the parameter and all of its attributes - i.e., type, size, and direction - and appends it to the parameters collection. There are two functions here that are important; these are the GetADOType and GetADODirection located in the CADO class. The two functions convert the textual representation of the XML Attributes to their corresponding ADO Constants.
      Some of you might be wondering why I did it this way, while others might have already guessed why I used ADO string representations of things like adInteger. Initially, I was hoping to use the Eval() function to get this information; I thought that would be a real robust way of doing it. Unfortunately, it didn't work; if any of you can get it to work, please email me with the solution. In any case, I just typed all this out as a quick solution; at least you don't have to do the same. Also, you should note that I have included CADO and CDSN in this project for your sake. In my real world of components, I have separate COM objects for ADO stuff and another one for DB stuff.
        c) Then, after this is all done, we execute the command with the proper parameters to return a stream.   d) The second For-Each loop is where we process our output stored procedure parameters. It looks very much like the first loop, with the exception that we are only concerned with the direction attribute on our check and that we update the passed XML via a reference.
        e) Finally, we set the value of ProcessCMD to the stream and clean up all of our objects. Program control flows back up to the call in Process, then back up to CRequest.Request, in this case anyway.

    IV. Formatting the resultant XML Output

    1. The XSL file that will transform our output is defined by our Entity Group and "Output.xsl". Recall this file is named ... XSL Output Formatting filename = Entity Group & "Output.xsl" and is located where the constant BASEFILELOCATION specifies. So in this case it is equal to ... http://www.unrealcity.com/xsl/usersoutput.xsl (Open this file in Notepad or an editor of your choice and take a brief look at it. If everything goes well, the transformed XML will look like XML listing 3.)

      
      <?xml version="1.0" encoding="UTF-16"?>
      <users xmlns:dt="urn:schemas-microsoft-com:datatypes">
      <user>
      <id type="read-only" dt:dt="int">1</id>
      <username type="read-write" dt:dt="string" length="7">TheUsername</username>
      <password type="read-write" dt:dt="string" length="8">ThePassword</password>
      <createdatetime type="read-only" dt:dt="datetime">2001-07-21T18:42:51</createdatetime>
      <updatedatetime type="read-only" dt:dt="datetime">2001-02-02T00:00:00</updatedatetime>
      <lastlogindatetime type="read-only" dt:dt="datetime">2001-08-13T13:28:53.340</lastlogindatetime>
      <logincount type="read-only" dt:dt="int">8</logincount>
      <enabled type="read-write" dt:dt="boolean">true</enabled>
      </user>
      </users>
      XML Listing 3: Successfully formatted XML for Output.
      
      
    2. XSL Output formatting

        a) It all starts with a call to FormatOutput.
        b) A lot of the same stuff you saw in the validating process, will also be seen here so I won't cover those aspects. First, you can see that I have added another namespace to the output here. This namespace is for data types. It is added for the caller's benefit so that they can perform date functions on date-typed nodes without conversion, number function on numbers, and so forth.
        c) There are also some added attributes to help the caller understand what they are getting and their capacities with it. For instance, you see all strings get a length attribute to aid in formatting. Further, they receive a type attribute that tells them the read-write capacities for each element, should they decide to modify any of them. In my implementation, I am only showing elements that have values written to them. However, there are many more fields in the database tables than you see in your output. I leave this to you to change in your implementation if you want to do so.
        d) Finally, you will see that the second template match is on user and suser (user|suser). This happens because user is a SQL Server keyword and causes problems so I had to alias the table name off to make it work right.

    V. Summary
    I hope I have explained the source code well enough for you to understand it. I am not going to walk you through anymore source code. However, I have included more examples in the code download. My intention was only to make you familiar enough with the operation of this code so that you can confidently modify it to suit your own needs. By showing you the sample operations of this one Entity, and its associated Entity Action, I hope you can understand the others as they appear in the download. Also, I hope you now understand why I did not list a lot of source code in the article itself. Actually, one could write a book about this concept, if they could put up with the proof readers that long without committing murder. I believe Microsoft is working on a similar book now called Web Services (or something like that). Now, let's see if we have achieved our goals.

    Did We Achieve Our Goals?

    The goals I am talking about are our three main goals listed in the first review paragraph. We wanted:

    1. adding and modifying existing methods and data structures (and the validation of these methods and structures) to our production services and applications without rewriting them and without having to bring our production servers down;
    2. designing an architecture that will allow us to scale out, as well as up;
    3. adoption of a new mindset, a new outlook on our IT projects, an outlook that expects changes and new requirements throughout a product life cycle.
    Well, (2) was solved in Figure 1, remember, so I won't even address that in detail. I shall, however, say that building a Web site to use a load-balanced service requires that state not be maintained via ASP's Session variables. Personally, I always opt to storing this information in a database or cookie anyway, but many people use them to store state information. When you can't count on the first request and the second request to be handled by the same server that has the ASP Session information stored, then you need to rethink how this information is maintained. In any case, I am getting off the topic because our service here doesn't rely on state anyway. For our purposes, (2) is solved.

    By far, (1) is the main concern of this article. In my opinion, it has been resolved too, but let's examine it. Our VB component has very little hard-coded in it. By minimizing the hard coding, I have minimized the possibility of needed change. Really, the only unavoidable hard coding we have done is the naming of the Entity attributes, which define the parameters fed to the data source. Recall these attributes are named type, direction, and size. In any case, these names could easily be changed before compile, if you foresee a naming conflict.

    But how do we add or modify a data structure or method? Does this modification require a recompile? No, not only are the validation rules maintained in XSL, so are the parameters and their attributes. If we wanted to add a method or data structure, perhaps for a new customer, we would have to simply add some more XSL and the associated data source procedure to process it. If we wanted to modify a method or data structure, we would modify the existing XSL and procedure. If we wanted to change to validation rules, we would just modify the XSL again. In fact, if you look closely at this, and have a good grasp on XSL, it would be really easy to add version control into this services as well. So, we have achieved a solution to issue #1 too.

    A lot of developers out there will argue that we have moved our hard coding out of VB and into XSL. You know what? They are right. I have done exactly that; however, I have gained something in this move. I can modify the code in the XSL without having to recompile my component and without having to restart my Web server services.

    Others will argue that since I have moved my specification out of a compile VB component; why not just use VB Script classes? Well, there is a reason not to use VB Script classes. VB Script is an interpretive language and scripts are recompiled every time a request is made on them. By using XSL, a declarative language, we have defined what we want, not the steps to take to get it. Further, we have reaped the benefits of compiled components, while maintaining the flexibility of scripting languages.

    Finally, did we achieve any resolve with regard to issue (3)? I hope so. Unfortunately, change is inevitable. Things that don't change simply die away. Not only is change inherent in the IT arena, it is part of the world as a whole. If you are on this earth breathing, then you have learned to successfully cope with change to some degree. I hope that everyone can see the benefit of implementing architectures of this nature. Perhaps you live in an ideal world, where your customer gives you a "set-in-stone" specification for an application. I've never heard of such a place. Those of us who have been in IT for years know, no matter what the manager says, he is always apt to backtrack on his words and redefine what he wants, and when he does, you have to make accommodations. Often, managers will even misinterpret what the redefinition is, and we'll end up changing back to what we changed from; it's called a "code rollback."

    NOTE: I have worked with a manager who initially said things very optimistically and concretely, but from the moment she said it, would backtrack on her words more and more every single time I saw her. In this way, she distanced herself in her mind from any responsibility to the customer or her team. Maybe some of you have experienced the same type of manager; I hope not. Nevertheless, her entire IT team has either left or is trying to leave there to this day.

    The fact is, a change request does happen often, and someone has got to make things happen, to do something to resolve the request. If developers and architects anticipate this change beforehand, then making these changes happen doesn't have to so painful. And, after all, we are the ones that have to make our lives and the lives of our peers at work manageable. Managers will give you problems to solve; developers and architects are responsible for actually doing something to solve these problems. Therefore, if you are a manager, architect, or developer, it is in your best interest to expect change. For those manager's that have issued code rollbacks in the past, I urge you to actively plan your projects with your team in such a way that additions and modifications can be made successfully. For architects...well, if you are still an architect, you already do this or else you would have been fired long ago. For developers, realize that XML and XSL cannot only make the responsibilities of your code more manageable, but also encourage code reuse.

    Conclusion

    I have no doubt that there are many shortcomings to this architecture and feel free to identify them to me via email if you like. For one, this implementation only allows you to group requests into one Entity Group. Wouldn't it be nice to operate on or "act on" multiple Entity types in one request. You could envision it as processing a request like this ...

    
    <users action="save">
    <user>
    <username>MyUsername</username>
    <password>MyPassword</password>
    <firstname>MyFirstName</firstname>
    <emails action="save">
    	<email action="save">
    	<address>blueeyzz@hotmail.com</address>
    	<addresstype>Primary Home</addresstype>
    	</email>
    <email action="save">
    	<address>15Seconds@unrealcity.com</address>
    	<addresstype>alternate work</addresstype>
    </email>
    				</emails>
    </user>
    <user>
    <username>MyUsername2</username>
    <password>MyPassword2</password>
    <firstname>William</firstname>
    <lastname>Turri</lastname>
    <preferredname>Willie T.</preferredname>
    </user>
    </users>
    
    
    That would be nice, but I can think of one even better. Wouldn't it be ideal if we could specify multiple Entity- types and actions. I am not going to list the XML for that request, but you would override the Entity Group Action by specifying an Entity Action. My own copy of the component will process this way. If you would like the source code, email me and I'll send it to you. I am still developing it, but I don't foresee this type of processing as any problem. In any case, finding ways to optimize this certainly isn't impossible. Feel free to let me know what you think about this.

    On a side note, I want to thank Joe Slovinski (jslovinski@unrealcity.com) for helping me proofread and validate this document's concepts.

    About the Author

    As a senior IT consultant with over 14 years industry experience, Lee architects and develops enterprise solutions for companies, including http://Unrealcity.com, of which he is the cofounder. When Lee is not working, which is rare, he likes reading, writing, and white-water rafting. He can be reached at 15seconds@unrealcity.com.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Supporting Products/Tools
    Stonebroom.ASP2XML
    Stonebroom.ASP2XML(c) is an interface component designed to make building applications that transport data in XML format much easier. It can be used to automatically pass updates back to the original data source.
    [Top]
    Other Articles
    Sep 22, 2005 - Implementing Remote Calling Without Using AJAX
    Right now the latest buzzword around town is AJAX. AJAX is an acronym for Asynchronous JavaScript and XML and is a method used to implement remote calling. The problem is that AJAX is only implemented in ASP.NET 2.0. This article will show you one way to implement remote calling without using AJAX or the XMLHttpRequest object. The technique outlined can even be used from classic ASP and is sufficient for most remote calling needs.
    [Read This Article]  [Top]
    Aug 18, 2005 - SQL Server 2005 XQuery and XML-DML - Part 3
    This article is the third and final installment of Alex Homer's series covering the new XML support in Microsoft SQL Server 2005. In it he covers updating the contents of xml columns, comparing traditional XML update techniques with XQuery, and using XQuery in a managed code stored procedure.
    [Read This Article]  [Top]
    Aug 11, 2005 - SQL Server 2005 XQuery and XML-DML - Part 2
    In the second part of his series on SQL Server 2005's new XML support, Alex Homer looks at extracting data from XML columns, comparing traditional XML data access approaches with XQuery, and combining XQuery and XSL-T.
    [Read This Article]  [Top]
    Aug 3, 2005 - SQL Server 2005 XQuery and XML-DML - Part 1
    Microsoft SQL Server 2005 now offers great support for and close integration with XML as a data persistence format. In the first article of his series examining this new support, Alex Homer offers an overview of how SQL Server 2005 stores XML documents and schemas, examines how it supports querying and manipulating XML documents, and provides a simple test application that allows you to experiment with XQuery.
    [Read This Article]  [Top]
    Jun 30, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 3, Cont'd
    In the final article of his series on reading and writing XML in .NET 2.0, Alex Homer looks at how the updated XML document store objects XmlDocument, XmlDataDocument and PathDocument can be used to read, persist and write XML documents and fragments more easily and more efficiently than in .NET 1.x.
    [Read This Article]  [Top]
    Jun 29, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 3
    In the final article of his series on reading and writing XML in .NET 2.0, Alex Homer looks at how the updated XML document store objects XmlDocument, XmlDataDocument and PathDocument can be used to read, persist and write XML documents and fragments more easily and more efficiently than in .NET 1.x.
    [Read This Article]  [Top]
    Jun 16, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 2, Cont'd
    Alex Homer continues his series on reading and writing XML in .NET 2.0. In part one, we focused on the reading side of things, examining the XmlReader and XmlReaderSettings classes. In this article, we move on to look at the XmlWriter and XmlWriterSettings classes, and how they can be used to write XML documents and fragments more easily and more efficiently than in version 1.x of .NET.
    [Read This Article]  [Top]
    Jun 15, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 2
    Alex Homer continues his series on reading and writing XML in .NET 2.0. In part one, we focused on the reading side of things, examining the XmlReader and XmlReaderSettings classes. In this article, we move on to look at the XmlWriter and XmlWriterSettings classes, and how they can be used to write XML documents and fragments more easily and more efficiently than in version 1.x of .NET.
    [Read This Article]  [Top]
    Jun 2, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 1, Cont'd
    In the first part of his series on reading and writing XML in .NET 2.0, Alex Homer discusses the XmlReader and XmlReaderSettings classes. The XmlReader exposes several useful new features and the all new XmlReaderSettings class makes it easy to generate single or multiple instances of an XmlReader with a range of useful properties.
    [Read This Article]  [Top]
    Jun 1, 2005 - Reading and Writing XML in .NET Version 2.0 - Part 1
    In the first part of his series on reading and writing XML in .NET 2.0, Alex Homer discusses the XmlReader and XmlReaderSettings classes. The XmlReader exposes several useful new features and the all new XmlReaderSettings class makes it easy to generate single or multiple instances of an XmlReader with a range of useful properties.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers