By examining many of the high-end Web applications on the Internet today, the ATL Server team discovered that most (almost all) Web pages require very simple flow control. This flow control is designed to be used to aid with HTML layout aspects as opposed to actual application logic.
For this reason, the ATL Server flow control system provides very limited flow control out of the box. This helps development teams keep application logic out of the SRF file, and it makes the stencil processor more efficient. In the ATL Server team s experience, this minimal flow control should be sufficient for 99 percent of Web applications.
Of course, if the provided flow control does fall short of your requirements, the flexibility and extensibility of ATL Server means that you can extend the flow control language to include new syntax. We demonstrate this capability later on in the book later on in Chapter 17. For now, let s look at the existing (provided) flow control and see how to go about using it.
One of the most useful flow control constructs is the if statement, with the else statement being a productive relative. An if / else block must be terminated with an {{endif}} tag.
The if statement is placed before the method name (i.e., the name you would normally use in the tag of the method that will be called to evaluate the if statement) and it generates the HTML nested within it only if the method returns HTTP_SUCCESS . If the method returns HTTP_S_FALSE , the corresponding else section (if it exists) will be rendered.
Listings 2-1 through 2-3 present some simple examples of if / else blocks and what the client would end up seeing based on return values.
<html> <head> Basic SRF </head> {{handler BasicSrf.dll/Example}} <body> Hello {{if World}}World!{{endif}} </body> </html>
If the World() method returns HTTP_SUCCESS , then the client will see this:
<html> <head> Basic SRF </head> <body> Hello World! </body> </html>
If the World() method returns HTTP_S_FALSE , then the client will see this:
<html> <head> Basic SRF </head> <body> Hello </body> </html>
Note | The World() method itself doesn t inject anything into the stream in the Listing 2-1 example ”it simply returns success or false. |
<html> <head> Basic SRF </head> {{handler BasicSrf.dll/Example}} <body> Hello {{if World}}World! {{else}}Foo! {{endif}} </body> </html>
If the World() method returns HTTP_SUCCESS , then the client will see this:
<html> <head> Basic SRF </head> <body> Hello World! </body> </html>
If the World() method returns HTTP_S_FALSE , then the client will see this:
<html> <head> Basic SRF </head> <body> Hello Foo! </body> </html>
<html> <head> Basic SRF </head> {{handler BasicSrf.dll/Example}} <body> {{if LoggedOn}} Here is the classified information {{ShowInformation}} {{else}} Please Login {{endif}} </body> </html>
In Listing 2-3, the LoggedOn() method will check if the user is correctly logged on. If the user is correctly logged on, it returns HTTP_SUCCESS , thereby sending the following to the client:
<html> <head> Basic SRF </head> <body> Here is the classified information OUTPUT OF ShowInformation </body> </html>
If the LoggedOn() method fails (i.e., the user isn t logged on), then the user will be asked to Please Login and ShowInformation() will never even get called. What about if you use static HTML for the classified information ? It still doesn t matter ”the client has no way of getting the string Here is the classified information once the request to LoggedOn() has failed, because all processing is done on the server.
The other statement that proves to be very useful in generating HTML layout is the while statement. This statement will continue repeatedly calling the method indicated and process the block (terminated with {{endwhile}} ) until HTTP_S_FALSE is returned from the method.
The while statement is particularly useful for generating structures such as HTML tables, as you can see in the following example:
<html> <head> Basic SRF </head> {{handler BasicSrf.dll/Example}} <body> <table> {{while AuthorsRemain}} <tr> <td>{{AuthorName}} </td> </tr> {{endwhile}} </table> </body> </html>
By now the logic presented here should be fairly straightforward. As long as AuthorsRemain() returns HTTP_SUCCESS , you ll generate another row in your HTML table. In this case, it s up to the AuthorName() method to inject data into the table (you ll learn how the method can do this in Chapter 3).
Here s an example of output the preceding code snippet might generate for the client:
<html> <head> Basic SRF </head> <body> <table> <tr> <td>Grewal </td> </tr> <tr> <td>Lee </td> </tr> <tr> <td>Kumar </td> </tr> <tr> <td>Crivat </td> </tr> </table> </body> </html>
As you would expect, there are no rules against nesting statements. End calls are matched with the last relevant opening of flow control. Thus, expressions like the following are perfectly valid:
{{if True}} {{if NestedTrue}} {{while NestedNestedTrue}} {{if NestedNestedNestedTrue}} Spit this text {{endif}} {{endwhile}} {{endif}} {{endif}}
The formatting system you use should make it clear which endif goes with which if statement. As you would expect, endif or endwhile will be associated with the last opened if or while statement.
There s no limit on the number of nesting levels and the kinds of statements you can use within nested expressions. You can have while statements within while statements, while statements within if statements, if statements within if statements, if statements within while statements, and unlimited combinations of these.