To use the business object we need to do a couple of admin tasks first before we can start creating data access code. We need to make sure that the wwBusiness and wwDeveloper classes are visible from our process class. To do this we need to SET CLASSLIB to in the server's startup code. We can do this in the SetServerProperties method of the WebDemoServer class. Add the following to the bottom of the SetServerProperties method in WebDemoMain:
*** Add any SET CLASSLIB or SET PROCEDURE code here SET CLASSLIB TO wwBusiness ADDIT SET CLASSLIB TO wwDeveloper ADDIT
Next let's think about what we want to do here. We want to retrieve some records from the developer registry and display them. Although this query will be very simple let's first create a business object method to retrieve this data rather than explicitly using a SQL statement from our Web method. To do so let's:
MODI CLASS cDeveloper of wwDeveloper
Add a method called DeveloperList:
LPARAMETERS lcCountry,lnMode
IF EMPTY(lcCountry)
lcCountry = "United States"
ENDIF
RETURN THIS.Query("SELECT company,name as contact,state,City,Country from " + THIS.cFileName + ;
" WHERE country like '" + lcCountry +"%' " + ;
"ORDER BY State,City,Company","TDevelopers",lnMode)
Why add a method for this simple SQL statement? Simple - it allows you to isolate all data access in the business object. If changes need to be made you can always come back here to do it in this single location. This becomes more important with more important query operations where you can pass parameters or property values into the method to set up for complex tasks. Using the Query method (or the lower level Execute() method) rather than a Fox SQL DML statement will allow this code to migrate to SQL Server later on.
Ok let's use the code in a Web method and display it on the Web. For kicks let's display the list in a paged mode to something a little bit different than before.
Open DevProcess.prg and add a method ShowDevelopers:
FUNCTION ShowDevelopers()
Response.HTMLHeader("Developer List")
loDev = CREATEOBJECT("cDeveloper")
lnCount = loDev.DeveloperList()
IF lnCount < 1
THIS.ErrorMsg("No matches","No developers match your query")
RETURN
ENDIF
loSC = CREATEOBJECT("wwShowCursor")
loSC.lAlternateRows = .T.
*** Size each page to 10 items
loSC.nPage_ItemsPerPage = 7
loSC.cPage_PageUrl = "ShowDevelopers.dp?"
loSC.ShowCursor()
Response.Write( loSC.GetOutput() )
Response.HTMLFooter(PAGEFOOT)
ENDFUNC
I made two additional changes in DevProcess. I added:
#DEFINE PAGEFOOT [<hr><small><a href="ShowDevelopers.dp">List</a></small>]
to add a page footer to my pages. I also added:
FUNCTION Process THIS.oResponse.cStyleSheet = "/wconnect/westwind.css" DODEFAULT() RETURN .T. ENDFUNC
To use a consistent style sheet with my pages so things look nice right from the get go. The result is:
Notice that the list is pageable - the query is re-run on each hit as you click on different pages and wwShowCursor automatically handles the paging for you. Nice with very little effort isn't it?
The whole list is cool but to filter we need to do a little more work. Let's allow fltering by country. Change the method as follows:
FUNCTION ShowDevelopers()
*** Retrieve the country entered
lcCountry = Request.QueryString("Country")
IF EMPTY(lcCountry)
lcCountry = Request.Form("Country")
ENDIF
*** We have to persist the Country in order for paging to work
THIS.InitSession()
IF EMPTY(lcCountry)
lcCountry = THIS.oSession.GetSessionVar("ShowCursor_Country")
ELSE
THIS.oSession.SetSessionVar("ShowCursor_Country",lcCountry)
ENDIF
loDev = CREATEOBJECT("cDeveloper")
lnCount = loDev.DeveloperList(lcCountry)
IF lnCount < 1
THIS.ErrorMsg("No matches","No developers match your query")
RETURN
ENDIF
loSC = CREATEOBJECT("wwShowCursor")
loSC.lAlternateRows = .T.
*** Size each page to 10 items
loSC.nPage_ItemsPerPage = 7
loSC.cPage_PageUrl = "ShowDevelopers.dp?"
loSC.ShowCursor()
Response.HTMLHeader("Developer List")
*** Display Country dialog
Response.FormHeader("ShowDevelopers.dp")
Response.Write("Country: ")
Response.FormTextBox("Country",lcCountry,20)
Response.FormButton("btnSubmit","Go")
Response.Write("</form><hr>")
Response.Write( loSC.GetOutput() )
Response.HTMLFooter(PAGEFOOT)
ENDFUNC
* DevProcess :: ShowDevelopers
The result now looks like this: