Adding code to the second form
With the interface elements in place, it's time to add code to the CustomerDetails.aspx code-behind. If it's not showing, use the Solution Explorer (View|Solution Explorer) to navigate to the CustomerDetails.aspx file. Right-click that file in the Solution Explorer and a context menu is displayed as shown below. You can use this to view either CustomerDetails.aspx or its code-behind. In this case, we want to see the Web form, so we'll select "View Designer."
With CustomerDetails.aspx showing in Visual Studio, double-click its OK button. This opens the
code-behind editing window for this form, and stubs in the btnOK_Click
event for you (the subroutine that's executed when
the OK button is clicked).
1. Add the OK button click event code.
In that btnOK_Click
event add this line of code:
Response.Redirect( "Default.aspx" )
this is the code that will redirect the users back to the Default.aspx page when they're done looking at customer details.
2. Add a DB declaration and an F-Spec
Now, scroll up to the top of the code, and immediately after the line that starts with
"BegClass,"
add this code (the entire code for this code-behind is shown at the bottom of the page):
DclDB pgmDB DBName( "DG Net Local" ) DclDiskFile Cust + Type( *Input ) + Org( *Indexed ) + File( "Examples/CMastNewL1" ) + DB( pgmDB ) + ImpOpen( *No )
This code specifies the database platform and an F-spec. The DclDB object is named pgmDB in this program.
It connects to a database named "DG Net Local
". We'll review database connections later, but for now, understand
that this database name looks up database connection attributes in the PC's registry. These connection attributes are used to
connect your AVR program to that database. DG Net Local
is the default database name given to the sample data you downloaded back at the beginning of step 3.
This database name connects your program to your local ASNA PC database. We'll discuss connecting this application to your IBM i in a later step.
The DclDiskFile
should be relatively obvious, if slightly syntactically mysterious. If you come
from an IBM i background, think of the DclDiskFile
like this: Imagine what RPG's old-fashioned column-oriented F-Spec would be
like with CL's command interface applied to it (see Getting to Know AVR for .NET, which covers AVR's
"command" syntax in more detail). The DclDiskFile uses keywords to specify various attributes of the file being declared. In this case:
- the file is named Cust for program purposes
- it's an input file
- it's indexed
- it resides in the Examples library
- it's name is CMastNewL1
- it connects to the database specified by the pgmDB object
- and it must be explicitly opened
In Web applications, files are almost always opened explicitly to give you better programmatic control when errors occur during the open. Having said that, we're skipping robust error handling in this example for the sake of brevity and clarity. A real-world application would have much more error checking than this one does.
3. Add the Page_Load
event code
You page load already has a test to determine if Page.IsPostBack
is occurring or not. Tweak your Page_Load
slightly so that it looks like this:
If ( NOT Page.IsPostBack ) ExSr ReadCustomer EndIf
This code causes the program to read the customer information by calling the ReadCustomer
subroutine. Because this
program is so simple, ReadCustomer
could have been called as is, conditioned by NOT Page.IsPostBack
(indicating the first time the
page is displayed during its event cycle) or unconditionally. While it doesn't matter in this program, it probably would in real
programs, so we'll do like it we probably would in the real world and have ReadCustomer conditioned on NOT Page.IsPostBack
.
4. Add the ReadCustomer
subroutine
Add this subroutine after the Page_Load
subroutine (like green screen RPG, you could really put this subroutine anywhere in the
code, the order of subroutines don't matter.
BegSr ReadCustomer // Connect to the database server. Connect pgmDB // Open the disk file. Open Cust // Get the customer number from the cmcustno session variable. CMCustNo = Session[ "cmcustno" ].ToString() // Put the customer number in the customer number textbox. txtCMCustNo.Text = CMCustNo // Chain into the Cust file with the customer number. Chain Cust Key( CMCustNo ) // If the record was not found, If ( NOT %FOUND( Cust ) ) // Show an error. lblErrorMsg.Visible = *True Else // Populate the user interface with data read from the record. txtCMName.Text = CMName txtCMAddr1.Text = CMAddr1 txtCMCity.Text = CMCity txtCMState.Text = CMState txtCMPostCode.Text = CMPostCode txtCMPhone.Text = CMPhone txtCMFax.Text = %EDITW( CMFax, "0( )& - " ) // Set the ASPX page's title to the customer name just read. *This.Title = "Customer: " + CMName EndIf EndSr
The code is above is clearly commented, however a few parts of it need a little more description.
This line is fetching the customer number stored in the 'cmcustno'
session variable and assigning it to the record
format's CMCustNo
field.
CMCustNo = Session[ "cmcustno" ].ToString()
The jarring part of this code is probably the .ToString()
at the end. If you recall, in section 4, all we did to put a value in
the session variable was do this:
Session[ "cmcustno" ] = txtCMCustNo.Text
Notice that we didn't need to specify the data type of the session variable during the assignment. The downside to this convenience is that you have to specify the data type when you take the variable back out.
CMCustNo = Session[ "cmcustno" ].ToString()
So, in the line above, the .ToString()
says "convert whatever value is in the session variable to a string and
move it to the CMCustNo
field." Hmmm. Why a string when, if you look at the file layout we're using (as shown in Section
4), CMCustNo
is a packed 9,0 value? Because it's easy! AVR's equal sign (=) operator essentially translates to an RPG MOVE operation. As
you learn more about .NET, you'll learn there are other ways to convert values in session variables (and other similar data storage mechanisms).
One more thing, where did the .ToString()
come from!? It is a method, a subroutine, associated with the session variable. Remember, AVR for
.NET is an object oriented language, and you're seeing just a glimpse of the power of OO here. The session variable comes to the party with his
own set of built-in subroutines. (In fact, nearly everything in AVR is an object with its own set of party-ready methods!).
If the Chain
fails with the the customer number provided, we need to get the user a message to that effect. This line of code sets the
visible property of the lblErrorMsg
label to true when the Chain
fails. (Recall that we set lblErrorMsg
's visible property
to false while we were setting up the UI).
lblErrorMsg.Visible = *True
The line of code below is setting the page's title to reflect the name of customer currently being viewed. *This refers to "this page."
*This.Title = "Customer: " + CMName
5. Disconnect the database connection and close the file.
Before any page goes out of scope, you need to be sure to close all of its open files and disconnect its database. This may seem wrong at first, but remember, Web pages are stateless. When a page goes out of scope, everything on that page goes away (except for data you've explicitly saved like we did with the customer number to a session variable). It's important to close files and disconnect the database so that the database job can be pooled. Pooled jobs dramatically reduce connection time (reducing the time it takes to get a job on the IBM i from several seconds to just a few milliseconds). You'll learn more about connection pooling later, but for now understand that for it to work appropriately, you must also ensure files have been closed and the database connection is disconnected before the page is displayed.
For this program, we're going to do this in the page's Unload
event. This event fires just prior to your application's response
leaving the server. It is usually a good place to disconnect and close. To stub this event in, you use the two drop down boxes near the
top of the editor.
In the left dropdown, select "(Page Events)." In the right dropdown, select "Unload." This stubs in the page's
Unload
event for you. Add these two lines of code in the Unload
event.
Close Cust Disconnect pgmDB
That's it! You're ready to run your program. Go to the next chapter.
The entire source code for CustomerDetails.aspx.vr
is shown below.
Using System Using System.Data Using System.Configuration Using System.Collections Using System.Web Using System.Web.Security Using System.Web.UI Using System.Web.UI.WebControls Using System.Web.UI.WebControls.WebParts Using System.Web.UI.HtmlControls BegClass CustomerDetails Partial(*Yes) Access(*Public) Extends(System.Web.UI.Page) DclDB pgmDB DBName( "*Public/DG Net Local" ) DclDiskFile Cust + Type( *Input ) + Org( *Indexed ) + File( "Examples/CMastNewL1" ) + DB( pgmDB ) + ImpOpen( *No ) BegSr Page_Load Access(*Private) Event(*This.Load) DclSrParm sender Type(*Object) DclSrParm e Type(System.EventArgs) If ( NOT Page.IsPostBack ) ExSr ReadCustomer EndIf EndSr BegSr ReadCustomer // Connect to the database server. Connect pgmDB // Open the disk file. Open Cust // Get the customer number from the cmcustno session variable. CMCustNo = Session[ "cmcustno" ].ToString() // Put the customer number in the customer number textbox. txtCMCustNo.Text = CMCustNo // Chain into the Cust file with the customer number. Chain Cust Key( CMCustNo ) // If the record was not found, If ( NOT %FOUND( Cust ) ) // Show an error. lblErrorMsg.Visible = *True Else // Populate the user interface with data read from the record. txtCMName.Text = CMName txtCMAddr1.Text = CMAddr1 txtCMCity.Text = CMCity txtCMState.Text = CMState txtCMPostCode.Text = CMPostCode txtCMPhone.Text = CMPhone txtCMFax.Text = %EDITW( CMFax, "0( )& - " ) // Set the ASPX page's title to the customer name just read. *This.Title = "Customer: " + CMName EndIf EndSr BegSr Page_Unload Access(*Private) Event(*This.Unload) DclSrParm sender Type(*Object) DclSrParm e Type(System.EventArgs) Close Cust Disconnect pgmDB EndSr BegSr btnOK_Click Access(*Private) Event(*This.btnOK.Click) DclSrParm sender Type(*Object) DclSrParm e Type(System.EventArgs) Response.Redirect( "Default.aspx" ) EndSr EndClass