Choosing the right Development Model

Web Connection supports a number of different ways for creating Web applications from very high level approaches like the Web Control Framework to low level approaches where you can use pure code to output every single byte of content sent back over the HTTP connection yourself. Which approach you use depends on your preferences and your application's needs. Here's an overview of some of the approaches available.

Process Class Templates or Scripting (MVC style)

If the Web Control Framework is too high level for you you can also use a more traditional and low level approach that is based method based processing and templating to display view data. Web Connection's core engine is based on Process Method routing: Each request is routed to an endpoint method that handles a request. The method receives objects like Request, Response, Server, Session, Cache etc. that can be used to handle input and output. Using this approach you can use low level Response.Write() commands to directly create output, or use templates to render data that was set up as part of the process method code. Templates are simply HTML markup pages that include embedded FoxPro Expressions and/or code blocks and that are used to render the 'view' of the data the code in the method created. This approach is known as MVC (Model View Controller) where the model is your business objects (or your raw cursor data if you don't use BOs), the View is the template, and the controller is the Process method code that sets up to call the template view.

Templates and Scripts work really well for read-only views and simple data entry operations, but can get complex quickly if you have multiple operations that need to be handled off a single page (ie. multiple buttons or change operations). Templates and scripts are code intensive. You write a lot more markup, but you get full control over your layout. You tend to write a bit of plumbing code in each request to route logic.

Pros

  • Very easy to understand and get started with
  • Efficient and fast executing code
  • Easy to modify templates on the fly

Cons

  • Code intensive
  • Code complexity for multi-action pages

Hello World Example

HTML Markup:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>HelloWorld</title>
    <link href="../westwind.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server" method="POST">

    <h1>HelloWorld</h1>
    
    <div class="containercontent">    
        Enter your name:
        <input type="textbox" id="txtName" name="txtName" value="<%= pcName %>" />
        <input type="submit" id="btnSayHello" name="btnSayHello" value="Say Hello" />
        <hr />
        <%= pcMessage %>
    </div>
    
    </form>
</body>
</html>

The FoxPro Controller code in a Process class method then looks like this:

FUNCTION HelloWorldTemplate
PRIVATE pcName, pcMessage

*** Variables to embed in the Template View
pcName = ""
pcMessage = ""

*** if we're posting back
IF Request.IsFormVar("btnSayHello")
   pcName = Request.Form("txtName")
   pcMessage = "Hello World " + pcName + ". Time is: " + TIME()
ENDIF

* **Call the template from Web path (HelloWorldTemplate.wwd)
* **Alternately you can explicitly point at a path
Response.ExpandTemplate( Request.GetPhysicalPath() )
ENDFUNC

REST API

You can also build API Services quite easily with Web Connection. APIs are non-visual interfaces that return raw data, rather than HTML. You pass data/parameters to a service, the service does some work based on the input and then returns a data result - most commonly in JSON format.

The approach is very similar to the way you build an MVC application minus the HTML template merging to render your model. Rather than rendering a model to HTML, an API simply returns a result value which is turned into JSON or XML.

As with MVC, REST API services work with a custom Process class (which is the top level 'handler') that handle the routing of requests to the appropriate methods as well as de-serializing incoming JSON data to FoxPro value/objects and serializing the return value into JSON.

Each method can take a single POST or PUT JSON parameter as input, or you can use Form and Query variables just as you can in standard wwProcess handlers.

What does a REST API Look like?

An API endpoint is just a method inside of a wwProcess class with a single input parameter and a return value. The input can map an optional single JSON value, object or collection into a FoxPro object. Your code can then use that object to create new output in the form of a result value, object, collection or cursor.

Here's a simple example:

*********************************************************************
FUNCTION GetData(lvParm)
************************

*** Any posted JSON string is automatically deserialized
*** into lvParm FoxPro object or value 

*** In this example an object with multiple query values
*** was passed
lcSearchName = lvParm.searchName
lcSearchDate = lvParm.searchDate


*** Run your business logic...
select * from customers ;
    where lastName = lcSearchName AND ; 
          entered > lcSearchDate ; 
    into cursor TCustomers
    

*** Simply create objects, collections, values and return them
*** they are automatically serialized to JSON

*** Create an object on the fly here to return 'multiple' values
*** But you can return any object, collection, cursor or value
loObject = CREATEOBJECT("EMPTY")
ADDPROPERTY(loObject,"searchFor",lcSearchName)
ADDPROPERTY(loObject,"serachDate", lcSearchDate)

*** Attach the cursor as a JSON array
ADDPROPERTY(loObject,"customers","cursor:TCustomers")


*** Properties by default serialize to *all lower case*
*** This allows overriding property case for specific properties
Serializer.PropertyNameOverrides = "searchFor,searchDate"

*** Return value of this API - serialized to JSON
RETURN loObject

A client could POST to this API with the following JSON:

{
    searchFor: "Strahl",
    searchDate: "2018-09-27T18:00:00Z"
}

The method then produces the following output:

{
    searchFor: "Strahl",
    searchDate: "2018-09-27T18:00:00Z",
    customers: [  
        lastname: "Strahl",
        firstname: "Rick",
        entered: "2018-09-29T18:00:00Z",
        ...
    ]
}

In short it's very simple to create APIs using this interface.

Pros

  • Very easy to understand and get started with
  • Efficient and fast executing code
  • Great for any sort of Data access from HTTP clients

Cons

  • FoxPro type issues - casing requires special fix up

Low Level Code Only Development

Templates are pretty low level in that you are only using a thin templating engine ontop of Web Connection to help with HTML generation. However the templating is completely optional - you can directly generate output from code if you choose to do so. This tends to be more work obviously, but can be a good choice in a number of scenarios:

  • Completely Meta Driven Applications
  • Non-Visual Data Service Applications (XML/JSON Servers for example)
  • Application Frameworks like the Web Control Framework (WCF is written ontop of low level output)
  • Simple applications that have to be of the fastest possible performance

All this said, for standard line of business applications I would not recommend using low level code rendering as it becomes tedious quickly. It might be the easiest way to get started and understand but in the long run a lot of repetitive and unmanagable code is likely to get written this way. Code only approaches work best in generic engines that serve a multitude of requests such as services or meta driven applications that create all HTML content dynamically based on meta data.

The Low Level approach works through the Response object which provides the raw HTTP output into the HTTP output stream. Response.Write() writes output and is the fastest way to send output back to the client. The Response and Process objects also include a few minimal high level helpers that help create controls and a few simple page layouts but beyond that you're on your own.


© West Wind Technologies, 1996-2018 • Updated: 09/26/18
Comment or report problem with topic